- WaSQL Wired
- Posts
- File Foreign Data Wrappers
File Foreign Data Wrappers
Harnessing the power of Postgres File FDW to access system info
Postgres Foreign Data Wrappers are incredibly useful for many things, especially for monitoring system resources. This article explains what FDWs are, how to install them, and how to use FDWs to monitor server resources.
Foreign Data Wrappers (FDWs) are a powerful feature within PostgreSQL that allows you to access and query data residing in external data sources as if they were native PostgreSQL tables. You can use FDWs to connect to other databases like MySQL, Oracle, MongoDB, etc. You can also use them to access files or programs on your server.
Installing FDWs is pretty simple. First make sure that Postgres-contrib is installed.
sudo yum install postgresql-contrib
OR
sudo apt-get install postgresql-contrib
Once that is installed enable the file FDW extension and create a server that will be used to access external files:
CREATE EXTENSION file_fdw;
CREATE SERVER "import" FOREIGN DATA WRAPPER file_fdw;
Now we are ready to create some really cool system tables… let’s go!
public.system_df - create this function to see drive space from a query. This is useful in monitoring hard drive space. Notice that we are calling the system command df and piping it to awk in order to get the results in a csv format.
CREATE FOREIGN TABLE IF NOT EXISTS public.system_df (
filesystem text,
size numeric,
used numeric,
available numeric,
use_pcnt text,
mount text
)
SERVER "import" OPTIONS (
PROGRAM 'df -B1 | tail -n+2 | awk ''{print "\\""$1"\\",\\""$2"\\",\\""$3"\\",\\""$4"\\",\\""$5"\\",\\""$6"\\""}''',
FORMAT 'csv',
HEADER 'off'
);
--example query
SELECT
filesystem,
PG_SIZE_PRETTY(size) AS size,
PG_SIZE_PRETTY(used) AS used,
PG_SIZE_PRETTY(available) AS available,
use_pcnt,
mount
FROM public.system_df
public.system_cpu - this table shows results from lscpu to monitor cpus. Notice that we are calling the system command lscpu and piping it to sed in order to get the results in a csv format.
CREATE FOREIGN TABLE IF NOT EXISTS public.system_cpu (
name text,
value text
)
SERVER "import" OPTIONS (
PROGRAM 'lscpu|sed -E ''s/^/"/''|sed -E ''s/:/",/''|sed -E ''s/ +/ /g''|sed -E ''s/, /,"/''|sed -E ''s/$/"/''|sed -E ''s/\\\(s\\\)/s/''',
FORMAT 'csv',
HEADER 'off'
);
--example usage
SELECT * FROM public.system_cpu
public.system_loadavg - to get the system load average we will call “cat /proc/loadavg” and pipe it to sed to get the results in a CSV format.
CREATE FOREIGN TABLE IF NOT EXISTS public.system_loadavg (
load_avg_1_min numeric,
load_avg_5_min numeric,
load_avg_15_min numeric,
number_of_running_over_number_of_threads text,
last_created_pid numeric
)
SERVER "import" OPTIONS (
PROGRAM 'cat /proc/loadavg|sed ''s/\\s/\\,/g''',
FORMAT 'csv',
HEADER 'off'
);
--example usage
SELECT * FROM public.system_loadavg
public.system_mem - lets use the free command to get memory stats and pipe that to awk to format the results to CSV. Then we can use Postgres’s PG_PRETTY_SIZE function to make it a bit more readable.
CREATE FOREIGN TABLE IF NOT EXISTS public.system_mem (
total numeric,
used numeric,
free numeric,
shared numeric,
buffers numeric,
cached numeric
)
SERVER "import" OPTIONS (
PROGRAM 'free -b | awk -v RS="" ''{print $8 "," $9 "," $10 "," $11 "," $12 "," $13}''',
FORMAT 'csv',
HEADER 'off'
);
--sample usage
SELECT
PG_SIZE_PRETTY(total) AS total_mem,
PG_SIZE_PRETTY(used) AS used,
PG_SIZE_PRETTY(free) AS free,
PG_SIZE_PRETTY(shared) AS shared,
PG_SIZE_PRETTY(buffers) AS buffers,
PG_SIZE_PRETTY(cached) AS cached
FROM public.system_mem
public.system_ps - to get a list of processes running on your server lets take the ps command and output the results in CSV format.
CREATE FOREIGN TABLE IF NOT EXISTS public.system_ps (
pid text,
username text,
cpu_pcnt text,
mem_pcnt text,
command text
)
SERVER "import" OPTIONS (
--FILENAME '/var/ddfa/system_ps.csv',
PROGRAM 'ps --no-headers -e -o %p, -o %U -o ,%C, -o %mem -o ,"%c"',
FORMAT 'csv',
HEADER 'true'
);
--example usage
SELECT * FROM public.system_ps
public.system_mpstat - if you happen to have mpstat installed on your server you can use the following to capture it.
CREATE FOREIGN TABLE IF NOT EXISTS public.system_mpstat (
checktime text,
cpu text,
user_pcnt text,
nice_pcnt text,
sys_pcnt text,
iowait_pcnt text,
irq_pcnt text,
soft_pcnt text,
steal_pcnt text,
guest_pcnt text,
gnice_pcnt text,
idle_pcnt text
)
SERVER "import" OPTIONS (
PROGRAM 'mpstat -P ALL | tail -n+5 | awk ''{print "\\""$1"\\",\\""$2"\\",\\""$3"\\",\\""$4"\\",\\""$5"\\",\\""$6"\\",\\""$7"\\",\\""$8"\\",\\""$9"\\",\\""$10"\\",\\""$11"\\",\\""$12"\\""}''',
FORMAT 'csv',
HEADER 'off'
);
select * from public.system_mpstat
Hopefully this gives you a new perspective on how useful Postgres File Foreign Data Wrappers can be. What other system commands would you add to this list?