Repository
Munin (contrib)
Last change
2021-04-05
Graph Categories
Capabilities
Keywords
Language
Perl
License
GPL-2.0-only
Authors

pgbouncer_

Name

pgbouncer_ is a plugin to get the pool and stat values for a single pgbouncer pool name

Application

perl and DBD::Pg is required, and pgbouncer must been installed with a correct setup access for a stat account

Configuration

the plugin that will be run needs to have the pool name after the plugin base name. alternatively, pool name can be specified in config file as env.pgbouncer_pool option, separating plugin name from pool name.

Plugin Configuration

eg: pgbouncer_foo will run for the pool named foo.

see SHOW POOLS database list for the pool name

Munin Plugin Config File

in the plugin config file under the [pgbouncer] name the access information ca be set.

eg: [pgbouncer*] env.pgbouncer_pass barfoo

more extended would be: [pgbouncer*] env.pgbouncer_pass barfoo env.pgbouncer_user bar env.pgbouncer_port 6542 env.pgbouncer_host localhost

another example, where different pgbouncers (and so munin plugins) connecting to same db: [pgbouncer_weblogin] env.pgbouncer_pass barfoo env.pgbouncer_user bar env.pgbouncer_port 6542 env.pgbouncer_host localhost env.pgbouncer_pool dbname

[pgbouncer_webmain]
  env.pgbouncer_pass barfoo
  env.pgbouncer_user bar
  env.pgbouncer_port 6543
  env.pgbouncer_host localhost
  env.pgbouncer_pool dbname

The database name is always pgbouncer

Output

The plugin will output 5 graphs in the group pgbouncer

Average Bytes Received/Sent

This graph will show the average bytes sent and received by the pgbouncer for this pool

Average Connections

This graph will show the average amount of connections to the pgbouncer for this pool

Average Query Time

This graph shows the average query time as processed by the pgbouncer for this pool in microseconds. The data will be shorted by standard SI. eg, m = milli, k = kilo.

So 4.61K is 4610 milliseconds

Client Connections

This graph shows the active and waiting client connections to pgbouncer for this pool

Server Connections

This graph shows the server connections to pgbouncer for this pool. The following data sets are shown: active, idle, used, tested, login

Max Wait

how long the oldest client the queue has waited, should be always 0

Acknowledgements

Original idea derived from a simple python script by Dimitri Fontaine

See Also

See further info on stats and pools on the pgbouncer homepage: http://pgbouncer.projects.postgresql.org/doc/usage.html#_show_commands

Version

1.0

Author

Clemens Schwaighofer gullevek@gullevek.org

License

GPLv2

#!/usr/bin/perl -w

# re-write of python version of pgbouncer stats
# data from stats, pools (client, server)

use strict;
use Munin::Plugin;
use DBD::Pg;

# check that multigraph is available
need_multigraph();
# get the script name
my $plugin_name = $Munin::Plugin::me;
# set the DB connection vars
my $db_user = $ENV{'pgbouncer_user'}  || 'postgres';
my $db_port = $ENV{'pgbouncer_port'}  || '6432';
my $db_host = $ENV{'pgbouncer_host'}  || 'localhost';
my $db_pass = $ENV{'pgbouncer_pass'}  || '';
my $db_pool = $ENV{'pgbouncer_pool'}  || '';
my $db_name = 'pgbouncer';
my @data = ();
# get the DB (pool) name we want to fetch
$plugin_name =~ /pgbouncer_(.*)$/;
my $plugin_suffix = $1;
#if pool name is specified explicitly in config file
#use plugin name together with pool name in graph title:
my $pool_name = ($db_pool) ? $db_pool : $plugin_suffix;
my $plugin_title = ($db_pool) ? $plugin_suffix." ".$pool_name : $pool_name;

# bail if no name
if (!$pool_name)
{
	print "Cannot get pool name\n";
	exit 1;
}

# command line arguments for autconf and config
if (defined($ARGV[0]))
{
	# autoconf, nothing to do
	if ($ARGV[0] eq 'autoconf')
	{
		my $dbh = DBI->connect("DBI:Pg:dbname=$db_name;host=$db_host;port=$db_port", $db_user, $db_pass);
		if (!$dbh)
		{
			print "no\n";
		}
		else
		{
			print "yes\n";
		}
		$dbh->disconnect();
		exit 0;
	}

	if ($ARGV[0] eq 'config')
	{
		# create the basic RRD
		# stats: average connections

		print "multigraph ".$plugin_name."_stats_avg_req\n";
		print "graph_title PgBouncer $plugin_title average connections\n";
		print "graph_args --base 1000\n"; # numbers not bytes
		print "graph_vlabel Average connections\n";
		print "graph_scale no\n"; # so we do not print "micro, milli, kilo, etc"
    		print "graph_category db\n";
		print $pool_name."_avg_req.type GAUGE\n";
		print $pool_name."_avg_req.label Avg Req\n";
		print $pool_name."_avg_req.min 0\n";
		print $pool_name."_avg_req.draw LINE2\n";
		# stats: average time for query
		print "multigraph ".$plugin_name."_stats_avg_query\n";
		print "graph_title PgBouncer $plugin_title average query time\n";
		print "graph_args --base 1000\n"; # numbers not bytes
		print "graph_vlabel Average time per query (microseconds)\n";
    		print "graph_category db\n";
		print $pool_name."_avg_query.type GAUGE\n";
		print $pool_name."_avg_query.label Avg Time\n";
		print $pool_name."_avg_query.min 0\n";
		print $pool_name."_avg_query.draw LINE2\n";
		# stats: in/out bytes
		print "multigraph ".$plugin_name."_stats_bytesinout\n";
		print "graph_title PgBouncer $plugin_title average bytes received/sent\n";
		print "graph_args --base 1024\n"; # numbers in bytes
		print "graph_vlabel Average bytes received (-)/sent (+)\n";
    		print "graph_category db\n";
		# bytes received
		print $pool_name."_avg_recv.type GAUGE\n";
		print $pool_name."_avg_recv.label Avg received\n";
		print $pool_name."_avg_recv.min 0\n";
		print $pool_name."_avg_recv.draw LINE1\n";
		print $pool_name."_avg_recv.graph no\n";
		# bytes sent
		print $pool_name."_avg_sent.type GAUGE\n";
		print $pool_name."_avg_sent.label Avg rcvd/sent\n";
		print $pool_name."_avg_sent.min 0\n";
		print $pool_name."_avg_sent.draw LINE1\n";
		print $pool_name."_avg_sent.negative ".$pool_name."_avg_recv\n";
		# pools: server (sv_)
		print "multigraph ".$plugin_name."_pools_server\n";
		print "graph_title PgBouncer $plugin_title servers\n";
		print "graph_category db\n";
		print "graph_args --base 1000\n"; # numbers not bytes
		print "graph_vlabel Server connections\n";
		print "graph_scale no\n";
		# active connections
		print $pool_name."_server_active.label active\n";
		print $pool_name."_server_active.min 0\n";
		print $pool_name."_server_active.type GAUGE\n";
		print $pool_name."_server_active.draw AREA\n";
		# idle connections
		print $pool_name."_server_idle.label idle\n";
		print $pool_name."_server_idle.min 0\n";
		print $pool_name."_server_idle.type GAUGE\n";
		print $pool_name."_server_idle.draw STACK\n";
		# used connections
		print $pool_name."_server_used.label used\n";
		print $pool_name."_server_used.min 0\n";
		print $pool_name."_server_used.type GAUGE\n";
		print $pool_name."_server_used.draw STACK\n";
		# tested connections
		print $pool_name."_server_tested.label tested\n";
		print $pool_name."_server_tested.min 0\n";
		print $pool_name."_server_tested.type GAUGE\n";
		print $pool_name."_server_tested.draw STACK\n";
		# logged in connections
		print $pool_name."_server_login.label login\n";
		print $pool_name."_server_login.min 0\n";
		print $pool_name."_server_login.type GAUGE\n";
		print $pool_name."_server_login.draw STACK\n";
		# pools: client (cl_)
		print "multigraph ".$plugin_name."_pools_client\n";
		print "graph_title PgBouncer $plugin_title clients\n";
		print "graph_category db\n";
		print "graph_args --base 1000\n"; # numbers not bytes
		print "graph_vlabel Client connections\n";
		print "graph_scale no\n";
		# active client connections
		print $pool_name."_client_active.label active\n";
		print $pool_name."_client_active.min 0\n";
		print $pool_name."_client_active.type GAUGE\n";
		print $pool_name."_client_active.draw AREA\n";
		# waiting client connections
		print $pool_name."_client_waiting.label waiting\n";
		print $pool_name."_client_waiting.min 0\n";
		print $pool_name."_client_waiting.type GAUGE\n";
		print $pool_name."_client_waiting.draw STACK\n";
		# pools: maxwait (longest waiting connection, should be 0)
		print "multigraph ".$plugin_name."_pools_maxwait\n";
		print "graph_title PgBouncer $plugin_title maximum waiting time\n";
		print "graph_args --base 1000\n"; # numbers not bytes
		print "graph_vlabel Maximum wait time (seconds)\n";
    		print "graph_category db\n";
		print $pool_name."_maxwait.type GAUGE\n";
		print $pool_name."_maxwait.label Wait Time\n";
		print $pool_name."_maxwait.min 0\n";
		print $pool_name."_maxwait.draw LINE2\n";
		print $pool_name."_maxwait.warning 1\n"; # warn if not 0
		print $pool_name."_maxwait.critical 10\n"; # go critical if 10 seconds waiting
		# END graph
		exit 0;
	}
}

# connect to data
my $dbh = DBI->connect("DBI:Pg:dbname=$db_name;host=$db_host;port=$db_port", $db_user, $db_pass)
	 or die ("Cannot connect to database");
# go through each set and get the data
foreach my $get ('pools', 'stats')
{
	# prep and execute the show query
	my $pre = $dbh->prepare("SHOW $get")
		or die ("Cannot prepare query");
	$pre->execute()
		or die ("Cannot execute statement");
	while (@data = $pre->fetchrow)
	{
		# first defines the pool
		if ($data[0] eq $pool_name)
		{
			# print values for the stats: average request, average query time, bytes in/out
			if ($get eq 'stats')
			{
				print "multigraph ".$plugin_name."_".$get."_avg_req\n";
				print $pool_name."_avg_req.value ".$data[5]."\n";
				print "multigraph ".$plugin_name."_".$get."_avg_query\n";
				print $pool_name."_avg_query.value ".$data[8]."\n";
				print "multigraph ".$plugin_name."_".$get."_bytesinout\n";
				print $pool_name."_avg_recv.value ".$data[6]."\n";
				print $pool_name."_avg_sent.value ".$data[7]."\n";
			}
			# print data for the pools: server, client
			if ($get eq 'pools')
			{
				print "multigraph ".$plugin_name."_".$get."_server\n";
				print $pool_name."_server_active.value ".$data[4]."\n";
				print $pool_name."_server_idle.value ".$data[5]."\n";
				print $pool_name."_server_used.value ".$data[6]."\n";
				print $pool_name."_server_tested.value ".$data[7]."\n";
				print $pool_name."_server_login.value ".$data[8]."\n";
				print "multigraph ".$plugin_name."_".$get."_client\n";
				print $pool_name."_client_active.value ".$data[2]."\n";
				print $pool_name."_client_waiting.value ".$data[3]."\n";
				print "multigraph ".$plugin_name."_".$get."_maxwait\n";
				print $pool_name."_maxwait.value ".$data[9]."\n";
			}
		}
	}
}
# close connection
$dbh->disconnect();

exit 0;

__END__

=head1 NAME

pgbouncer_ is a plugin to get the pool and stat values for a single pgbouncer pool name

=head1 APPLICATION

perl and DBD::Pg is required, and pgbouncer must been installed with a correct setup access for a stat account

=head1 CONFIGURATION

the plugin that will be run needs to have the pool name after the plugin base name.
alternatively, pool name can be specified in config file as env.pgbouncer_pool option, separating plugin name from pool name.

=head2 plugin configuration

eg: pgbouncer_foo will run for the pool named foo.

see SHOW POOLS database list for the pool name

=head2 munin plugin config file

in the plugin config file under the [pgbouncer] name the access information ca be set.

eg:
  [pgbouncer*]
    env.pgbouncer_pass barfoo

more extended would be:
  [pgbouncer*]
    env.pgbouncer_pass barfoo
    env.pgbouncer_user bar
    env.pgbouncer_port 6542
    env.pgbouncer_host localhost

another example, where different pgbouncers (and so munin plugins) connecting to same db:
   [pgbouncer_weblogin]
     env.pgbouncer_pass barfoo
     env.pgbouncer_user bar
     env.pgbouncer_port 6542
     env.pgbouncer_host localhost
     env.pgbouncer_pool dbname

   [pgbouncer_webmain]
     env.pgbouncer_pass barfoo
     env.pgbouncer_user bar
     env.pgbouncer_port 6543
     env.pgbouncer_host localhost
     env.pgbouncer_pool dbname

The database name is always pgbouncer

=head1 OUTPUT

The plugin will output 5 graphs in the group pgbouncer

=head2 Average bytes received/sent

This graph will show the average bytes sent and received by the pgbouncer for this pool

=head2 Average connections

This graph will show the average amount of connections to the pgbouncer for this pool

=head2 Average query time

This graph shows the average query time as processed by the pgbouncer for this pool in microseconds. The data will be shorted by standard SI. eg, m = milli, k = kilo.

So 4.61K is 4610 milliseconds

=head2 Client connections

This graph shows the active and waiting client connections to pgbouncer for this pool

=head2 Server connections

This graph shows the server connections to pgbouncer for this pool. The following data sets are shown: active, idle, used, tested, login

=head2 Max wait

how long the oldest client the queue has waited, should be always 0

=head1 ACKNOWLEDGEMENTS

Original idea derived from a simple python script by Dimitri Fontaine

=head1 SEE ALSO

See further info on stats and pools on the pgbouncer homepage:
  http://pgbouncer.projects.postgresql.org/doc/usage.html#_show_commands

=head1 VERSION

1.0

=head1 AUTHOR

Clemens Schwaighofer <gullevek@gullevek.org>

=head1 LICENSE

GPLv2


=cut