pgsnmpd is an SNMP agent for PostgreSQL which implements RDBMS-MIB, as defined in RFC 1697. This MIB was developed by a group of representatives from different database manufacturers, and describes various attributes common to most relational database management systems. Because it was designed as the least common denominator, it doesn't show very much detail and there are definitely a number of things RDBMS-MIB doesn't cover that PostgreSQL administrators would be very interested in. Future versions of pgsnmpd will support a second MIB, tentatively called PGSQL-MIB, in addition to RDBMS-MIB. This PGSQL-MIB will be PostgreSQL-specific, and will include many more data points of interest to PostgreSQL users and administrators.
pgsnmpd has been used on Linux, OpenBSD, and FreeBSD, and perhaps other systems. Future versions will likely also work on Windows-based platforms.
PostgreSQL can be compiled within the PostgreSQL source tree, by putting the pgsnmpd distribution into the postgresql-XXX/contrib directory and running "make" (note: GNU make, referred to as gmake on some platforms, is required for the build).
jtolley@uber:~/devel/postgresql-8.2.3/contrib$ tar -zxf pgsnmpd.tgz
jtolley@uber:~/devel/postgresql-8.2.3/contrib$ cd pgsnmpd
jtolley@uber:~/devel/postgresql-8.2.3/contrib/pgsnmpd$ make
...
Alternatively, pgsnmpd can also be built without the postgresql source tree. This will probably require installation of a postgresql-dev package, though that depends on the operating system and distribution. In this case, the user must first set the USE_PGXS variable to tell the make process how to behave, as follows:
jtolley@uber:~/devel$ tar -zxf pgsnmpd.tgz
jtolley@uber:~/devel$ cd pgsnmpd/
jtolley@uber:~/devel/pgsnmpd$ env USE_PGXS=1 make
Note that building pgsnmpd requires Net-SNMP development files.
pgsnmpd can run in one of three different modes:
As a standalone SNMP agent, pgsnmpd itself listens on a network socket for SNMP queries, and requires the same configuration as the Net-SNMP SNMP daemon. SNMP is sometimes difficult to configure, and Net-SNMP provides a program called snmpconf to help the user create a suitable configuration file.
pgsnmpd can also run as a sub-agent in two different ways. A sub-agent is like a slave to a master agent; when it starts, the sub-agent registers itself with the master to tell the master which parts of the MIB it knows about. The master communicates with the SNMP client, and forwards requests for appropriate sections of the MIB to the sub-agent. Pass-through agents are actually identical to standalone agents — the only difference is that the master is configured to pass queries through to the sub-agent. AgentX sub-agents, on the other hand, don't listen to the network at all, and instead communicate with the master agent through UNIX sockets.
pgsnmpd is implemented using net-snmp and libpq, and most of the command-line options available are intended to control those libraries. pgsnmpd supports the following options:
jtolley@uber:~/devel/pgsnmpd$ ./pgsnmpd -?
./pgsnmpd: invalid option -- ?
Version PGSQL-SNMP-1.0beta
usage: pgsnmpd [-s] [-b] [-c FILE ] [-x address ] [-g] [-C "Connect String"]
-s : run as AgentX sub-agent of an existing snmpd process
-b : run in the background
-c : configuration file name
-g : use syslog
-C : libpq connect strings
-x : address:port of a network interface
-V : display version strings
Perhaps the simplest way to run pgsnmpd is as a standalone SNMP agent, as described below. The most difficult part is to write a proper configuration file. The pgsnmpd regression tester, pgsnmpd_regress.pl, contains a workable sample configuration file, shown here:
com2sec readwrite default public
group MyRWGroup v2c readwrite
view all included .1 80
access MyRWGroup "" any noauth exact all all none
agentaddress localhost:10161
Users interested in making more complex configuration files are encouraged to read the snmpd.conf(5) manpage. This configuration file will create one SNMP community called "public" and grant it read-only access on the entire MIB. It will also tell the SNMP agent to listen on port 10161 instead of the default 161. This is useful for pgsnmpd_regress.pl because listening on port 161 would require root privileges.
pgsnmpd also requires a libpq connection string, so it can connect to PostgreSQL. Note that nothing requires pgsnmpd to run on the same machine as PostgreSQL — the agent can easily monitor a remote PostgreSQL instance, if the network configuration allows it to connect. The configuration string can contain the database name, the host name, the port number, the username, the password, and other information where needed. One sample configuration string could say "dbname=pgsnmpd host=localhost user=pgsnmpd password=pgsnnmpd".
Still using pgsnmpd_regress.pl as an example, one way to start pgsnmpd as a standalone agent is as follows:
jtolley@uber:~/devel/pgsnmpd$ ./pgsnmpd -c pgsnmpd.conf -C "dbname=jtolley host=localhost user=jtolley password=jtolley"
PGSQL-SNMP-1.0beta is up and running.
A user could then query pgsnmpd with a Net-SNMP client program such as snmpwalk:
jtolley@uber:~$ snmpwalk -v 2c -c public localhost:10161 .1
SNMPv2-SMI::mib-2.39.1.1.1.2.1 = OID: SNMPv2-SMI::enterprises.27645.1
SNMPv2-SMI::mib-2.39.1.1.1.2.10818 = OID: SNMPv2-SMI::enterprises.27645.10818
SNMPv2-SMI::mib-2.39.1.1.1.2.10819 = OID: SNMPv2-SMI::enterprises.27645.10819
SNMPv2-SMI::mib-2.39.1.1.1.2.16384 = OID: SNMPv2-SMI::enterprises.27645.16384
SNMPv2-SMI::mib-2.39.1.1.1.3.1 = STRING: "PostgreSQL"
...
jtolley@uber:~/devel/postgresql-8.2.3/contrib/pgsnmpd$ perl pgsnmpd_regress.pl
1..7
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pgsnmpd_rdbmsdbtable_pkey" for table "pgsnmpd_rdbmsdbtable"
** Redirecting pgsnmpd child process STDOUT and STDERR to /dev/null
ok 1 - Found OID for this database
** Getting DbInfoTable
** Getting rdbmsDbParamTable
Can't parse: .1.3.6.1.2.1.39.1.3.1.5.16384.4.103.101.113.111.0
***** ERROR parsing .1.3.6.1.2.1.39.1.3.1.5.16384.4.103.101.113.111.0 MIB OID
Can't parse: .1.3.6.1.2.1.39.1.3.1.5.18033.4.103.101.113.111.0
***** ERROR parsing .1.3.6.1.2.1.39.1.3.1.5.18033.4.103.101.113.111.0 MIB OID
** Getting rdbmsDbLimitedResourceTable
** Getting rdbmsSrvTable
** Getting rdbmsSrvInfoTable
** Getting rdbmsSrvParamTable
ok 2 - rdbmsDbInfoTable has a row for this database
ok 3 - geqo should be off
ok 4 - XID should be reported in rdbmsDbLimitedResourceTable
ok 5 - Contact name should be set to pgsnmpd_regress
ok 6 - Finished transactions should be reported
ok 7 - Lots of server parameters should be defined
** Killing pgsnmpd
** Dropping test database pgsnmpd_regress
pgsnmpd is implemented using libpq and Net-SNMP, which includes a templating system to generate a C implementation of an SNMP table given the MIB definition of that table. Net-SNMP includes all the SNMP protocol code, network code, authentication and access control code, etc., and leaves the implementer with only the job of gathering the data published in the MIB. One important feature of the system used to obtain the SNMP data is that Net-SNMP provides a cache for each table implemented in an agent, and each cache has an expiration timeout. For most tables in pgsnmpd, this timeout is 60 seconds, meaning that the data published by the agent are updated at most every 60 seconds. Note also that pgsnmpd will only refresh cached values if both the timeout is past and someone queries the table in question, so a table might go much longer than the timeout value without refreshing, if it isn't queried for a long period of time.
The current version of pgsnmpd implements only RDBMS-MIB, but future versions will implement a PGSQL-MIB (which needs to be defined still) which will describe a PostgreSQL instance in much greater detail than is possible with RDBMS-MIB. RDBMS-MIB describes nine tables, as follows:
Some comments on the above are in order. First, since some of the tables contain contact information, vendor names, or other data not normally tracked by PostgreSQL, pgsnmpd supports a set of supplementary tables, by default kept in a schema called "pgsnmpd", which will track this information. One table contains database information, and is indexed by OID from pg_database, and the other tracks server specific information.
Second, since pgsnmpd supports only one libpq connection, it only supports one PostgreSQL server in its current version. It is not possible to monitor multiple PostgreSQL clusters with one pgsnmpd instance. It is, however, possible to run multiple instances of pgsnmpd on one machine to monitor multiple PostgreSQL clusters, however the pgsnmpd instances will need to be configured so as not to conflict (for instance, configuring each to listen on a different UDP port). This limitation means that rdbmsSrvTable and rdbmsSrvInfoTable are fairly boring, containing only one entry each, and rdbmsRelTable is similarly boring, since each database must necessarily be connected to the one server pgsnmpd knows about.
RDBMS-MIB refers to another MIB defined in an RFC, specifically APPLICATION-MIB from RFC 1565. pgsnmpd doesn't implement this yet. Specifically, entries in rdbmsSrvTable are supposed to be indexed to match indices in APPLICATION-MIB::applTable, and the corresponding entry in applTable would contain further information about the server, specifically related to connections from clients. Because of particular complexities associated with implementing this part of the MIB, the connection between rdbmsSrvTable and applTable is unimplemented in the current version of pgsnmpd.
RDBMS-MIB contains two tables to describe limited resources, one for database-specific resources and one for server-specific ones. rdbmsSrvLimitedResourceTable is empty in the current implementation of pgsnmpd, and rdbmsDbLimitedResourceTable contains only one row per database. This is because the only limited resource the authors could think of was transaction ID (xid). Since xid is database-specific, it went in the database limited resource table. Other limited resources, such as disk space, memory, etc. are instrumented elsewhere in the MIB, and weren't copied into pgsnmpd.
rdbmsSrvInfoTable contains a row to instrument the maximum number of incoming connections seen. Each time the cached rdbmsSrvInfoTable values are updated, the number of connections to the database at the time is recorded, compared against the recorded maximum, and kept as the new maximum when appropriate. But this only occurs when the cached data are updated, meaning that the value in this column is not necessarily particularly accurate. Future versions will hopefully correct this problem.
Finally, RDBMS-MIB describes two SNMP traps which RDBMS-MIB agents can optionally implement. pgsnmpd does not implement these.