#!@@PERL@@ # -*- cperl -*- # # Plugin to monitor memcache statistics # # This module has 3 seperate graph datasets: # rates # bytes # counters # # For each of them, symlink the memcached_ script to memcached_FOO where foo is # the datset name. # # Parameters supported: # # config # autoconf # suggest # # Configurable variables # # host Host of the memcache daemon # port Port of the memcache daemon # # Author: Robin H. Johnson # Slightly based on the original version by Joshua Thijssen # # # Magic markers: #%# family=contrib #%# capabilities=autoconf use strict; my $ret = undef; if (! eval "require Cache::Memcached;") { $ret = "Cache::Memcached not found"; } my $HOST = exists $ENV{'host'} ? $ENV{'host'} : "127.0.0.1"; my $PORT = exists $ENV{'port'} ? $ENV{'port'} : 11211; if ( exists $ARGV[0] and $ARGV[0] eq "autoconf" ) { if ($ret) { print "no ($ret)\n"; } else { use Net::Ping; my $p = Net::Ping->new(); $p->port_number($PORT); if ($p->ping($HOST, 1)) { print "yes\n"; exit 0; } print "no (cannot connect to $HOST on port $PORT)\n"; } exit 0; } if (exists $ARGV[0] and $ARGV[0] eq "suggest") { print "bytes\n"; print "counters\n"; print "rates\n"; exit 0; } if($ret) { # refuse to execute "config" or "fetch" due to a missing requirement print "memcached_ plugin fails to run: $ret\n"; exit 1; } # We do everything by this array my %all_vars = ( rates => { master => { graph_title => 'Memcached - Commands', graph_args => '--base 1000', graph_vlabel => '/${graph_period}', graph_category => 'memcache', }, memcache_cache_hits => { label => 'Cache hits', type => 'DERIVE', min => '0', max => '5000', draw => 'LINE2', info => 'Number of cache hits', stat_group => 'misc', stat_name => 'get_hits' }, memcache_cache_misses => { label => 'Cache misses', type => 'DERIVE', min => '0', max => '5000', draw => 'LINE2', info => 'Number of cache misses', stat_group => 'misc', stat_name => 'get_misses' }, memcache_cmd_get => { label => 'GET requests', type => 'DERIVE', min => '0', max => '5000', draw => 'LINE2', info => 'Number of GET commands seen', stat_group => 'misc', stat_name => 'cmd_get' }, memcache_cmd_set => { label => 'SET requests', type => 'DERIVE', min => '0', max => '5000', draw => 'LINE2', info => 'Number of SET commands seen', stat_group => 'misc', stat_name => 'cmd_set' }, memcache_total_items => { label => 'New items*5', type => 'DERIVE', min => '0', max => '5000', draw => 'LINE2', info => 'New items*5', cdef => 'memcache_total_items,5,*', stat_group => 'misc', stat_name => 'total_items' }, memcache_total_connections => { label => 'New connections*100', type => 'DERIVE', min => '0', max => '5000', cdef => 'memcache_total_connections,100,*', draw => 'LINE2', info => 'New connections*100', stat_group => 'misc', stat_name => 'total_connections' }, }, bytes => { master => { graph_title => 'Memcached - Network traffic', graph_args => '--base 1000', graph_vlabel => 'bytes in(-)/out(+) per ${graph_period}', graph_category => 'memcache', }, memcache_bytes_read => { label => 'Bytes read', type => 'COUNTER', draw => 'LINE2', max => '1000000', info => 'Bytes read from network', graph => 'no', stat_group => 'misc', stat_name => 'bytes_read' }, memcache_bytes_written => { label => 'Bytes written', negative => 'memcache_bytes_read', type => 'COUNTER', max => '1000000', draw => 'LINE2', info => 'Bytes written to network', stat_group => 'misc', stat_name => 'bytes_written' }, }, counters => { master => { graph_title => 'Memcached - Current values', graph_args => '--base 1000', #graph_args => '--base 1000 --loga', graph_vlabel => 'Totals', graph_category => 'memcache', graph_scale => 'no', }, memcache_curr_items => { label => 'Current items', type => 'GAUGE', min => '0', draw => 'LINE2', info => 'Number of items in cache', stat_group => 'misc', stat_name => 'curr_items' }, memcache_curr_connections => { label => 'Current connections*100', type => 'GAUGE', min => '0', draw => 'LINE2', cdef => 'memcache_curr_connections,100,*', info => 'Number of connections*100', stat_group => 'misc', stat_name => 'curr_connections' }, memcache_bytes_allocated => { label => 'Bytes allocated (KiB)', type => 'GAUGE', min => '0', draw => 'LINE2', cdef => 'memcache_bytes_allocated,1024,/', info => 'Bytes allocated (KiB)', stat_group => 'misc', stat_name => 'bytes' }, } ); $0 =~ /memcached_(.+)*$/; my $func = $1; exit 2 unless defined $func; my %vars = %{$all_vars{$func}}; # STAT rusage_user 3941.052868 # STAT rusage_system 18436.366246 # STAT connection_structures 1112 # STAT bytes 382985002 # STAT limit_maxbytes 536870912 if ( exists $ARGV[0] and $ARGV[0] eq "config" ) { my %v = %{$vars{'master'}}; foreach my $k ( keys %v ) { print "$k ".$v{$k}."\n" } print 'graph_order '; foreach my $k ( sort(keys %vars) ) { if($k eq 'master') { next; } print $k." "; } print "\n"; foreach my $k ( sort(keys %vars) ) { if($k eq 'master') { next; } my %v = %{$vars{$k}}; foreach my $k2 (keys %v) { if($k2 eq 'stat_group' or $k2 eq 'stat_name') { next; } print "$k.$k2 ".$v{"$k2"}."\n"; } } exit 0; } my $mc = new Cache::Memcached { 'servers' => [ "$HOST:$PORT" ] }; my $stats = $mc->stats ('misc'); foreach my $k ( sort(keys %vars) ) { if($k eq 'master') { next; } my %v = %{$vars{$k}}; if($v{type} eq 'COMPUTE') { next; } my $sg = $v{stat_group}; my $sn = $v{stat_name}; my $value = $stats->{hosts}->{"$HOST:$PORT"}->{$sg}->{$sn}; defined($value) or $value = 'U'; print "$k.value ".$value."\n"; } # vim:syntax=perl ts=4 sw=4: