6 Memcached - A Plugin to monitor Memcached Servers
 
   8 =head1 MUNIN CONFIGURATION
 
  11  env.host 127.0.0.1     *default*
 
  12  env.port 11211         *default*
 
  14 =head2 MUNIN ENVIRONMENT CONFIGURATION EXPLANATION
 
  16  host = host we are going to monitor
 
  17  port = port we are connecting to, in order to gather stats
 
  19 =head1 NODE CONFIGURATION
 
  21 Please make sure you can telnet to your memcache servers and issue the
 
  22  following commands: stats
 
  24 Available Graphs contained in this Plugin
 
  26 bytes => This graphs the current network traffic in and out
 
  28 commands => This graphs the current commands being issued to the memcache machine.
 
  30 conns => This graphs the current, max connections as well as avg conns per sec avg conns per sec is derived from total_conns / uptime.
 
  32 evictions => This graphs the current evictions on the node.
 
  34 items => This graphs the current items and total items in the memcached node.
 
  36 memory => This graphs the current and max memory allocation.
 
  38 The following example holds true for all graphing options in this plugin.
 
  39  Example: ln -s /usr/share/munin/plugins/memcached_ /etc/munin/plugins/memcached_bytes
 
  41 =head1 ACKNOWLEDGEMENTS
 
  43 Thanks to dormando for putting up with me ;)
 
  47 Matt West < https://github.com/mhwest13/Memcached-Munin-Plugin >
 
  56 #%# capabilities=autoconf suggest
 
  63 my $host = $ENV{host} || "127.0.0.1";
 
  64 my $port = $ENV{port} || 11211;
 
  69 # This hash contains the information contained in two memcache commands
 
  70 # stats and stats settings.
 
  72 # So I was trying to figure out how to build this up, and looking at some good examples
 
  73 # I decided to use the format, or for the most part, the format from the mysql_ munin plugin
 
  74 # for Innodb by Kjell-Magne Ãierud, it just spoke ease of flexibility especially with multigraphs
 
  77 # %graphs   is a container for all of the graph definition information. In here is where you'll
 
  78 #           find the configuration information for munin's graphing procedure.
 
  81 #   $graph{graph_name} => {
 
  83 #           # You'll find keys and values stored here for graph manipulation
 
  86 #           # Name: name given to data value
 
  87 #           # Attr: Attribute for given value
 
  88 #           { name => 'Name', (Attr) },
 
  96         args     => '--base 1000 --lower-limit 0',
 
  97         vlabel   => 'Items in Memcached',
 
  98         category => 'memcached',
 
 100         info     => 'This graph shows the number of items in use by memcached',
 
 103         { name => 'curr_items', label => 'Current Items', min => '0' },
 
 105             name  => 'total_items',
 
 106             label => 'New Items',
 
 115         args     => '--base 1024 --lower-limit 0',
 
 116         vlabel   => 'Bytes Used',
 
 117         category => 'memcached',
 
 118         title    => 'Memory Usage',
 
 119         info     => 'This graph shows the memory consumption of memcached',
 
 123             name  => 'limit_maxbytes',
 
 125             label => 'Maximum Bytes Allocated',
 
 131             label => 'Current Bytes Used',
 
 139         args     => '--base 1000',
 
 140         vlabel   => 'bits in (-) / out (+)',
 
 141         title    => 'Network Traffic',
 
 142         category => 'memcached',
 
 144 'This graph shows the network traffic in (-) / out (+) of the machine',
 
 145         order => 'bytes_read bytes_written',
 
 149             name  => 'bytes_read',
 
 151             label => 'Network Traffic coming in (-)',
 
 153             cdef  => 'bytes_read,8,*',
 
 157             name     => 'bytes_written',
 
 159             label    => 'Traffic in (-) / out (+)',
 
 160             negative => 'bytes_read',
 
 161             cdef     => 'bytes_written,8,*',
 
 169         args     => '--base 1000 --lower-limit 0',
 
 170         vlabel   => 'Connections per ${graph_period}',
 
 171         category => 'memcached',
 
 172         title    => 'Connections',
 
 174 'This graph shows the number of connections being handled by memcached',
 
 175         order => 'curr_conns avg_conns',
 
 178         { name => 'curr_conns', label => 'Current Connections', min => '0' },
 
 179         { name => 'avg_conns',  label => 'Avg Connections',     min => '0' },
 
 183 $graphs{commands} = {
 
 185         args     => '--base 1000 --lower-limit 0',
 
 186         vlabel   => 'Commands per ${graph_period}',
 
 187         category => 'memcached',
 
 190           'This graph shows the number of commands being handled by memcached',
 
 197             info  => 'Cumulative number of retrieval reqs',
 
 204             info  => 'Cumulative number of storage reqs',
 
 211             info  => 'Number of keys that were requested and found',
 
 215             name  => 'get_misses',
 
 217             label => 'Get Misses',
 
 218             info  => 'Number of keys there were requested and not found',
 
 224 $graphs{evictions} = {
 
 226         args     => '--base 1000 --lower-limit 0',
 
 227         vlabel   => 'Evictions per ${graph_period}',
 
 228         category => 'memcached',
 
 229         title    => 'Evictions',
 
 230         info     => 'This graph shows the number of evictions per second',
 
 235             label => 'Evictions',
 
 236             info  => 'Cumulative Evictions Across All Slabs',
 
 244 #### Config Check ####
 
 247 if ( defined $ARGV[0] && $ARGV[0] eq 'config' ) {
 
 249     $0 =~ /(?:([^\/]+)_)?memcached_(.+)$/;
 
 250     my $prefix = $1 ? $1 : '';
 
 253     die 'Unknown Plugin Specified: ' . ( $plugin ? $plugin : '' )
 
 254       unless $graphs{$plugin};
 
 256 # We need to fetch the stats before we do any config, cause its needed for multigraph
 
 259     # Now lets go ahead and print out our config.
 
 260     do_config( $prefix, $plugin );
 
 265 #### Autoconf Check ####
 
 268 if ( defined $ARGV[0] && $ARGV[0] eq 'autoconf' ) {
 
 270     # Lets attempt to connect to memcached
 
 273     # Lets check that we did connect to memcached
 
 279         print "no (unable to connect to $connection)\n";
 
 285 #### Suggest Check ####
 
 288 if ( defined $ARGV[0] && $ARGV[0] eq 'suggest' ) {
 
 290     # Lets attempt to connect to memcached
 
 293     # Lets check that we did connect to memcached
 
 296           ( 'bytes', 'conns', 'commands', 'evictions', 'items', 'memory' );
 
 297         foreach my $plugin (@rootplugins) {
 
 303         print "no (unable to connect to $connection)\n";
 
 309 #### Well We aren't running (auto)config/suggest so lets print some stats ####
 
 315 #### Subroutines for printing info gathered from memcached ####
 
 319 #### This subroutine performs the bulk processing for printing statistics.
 
 324     $0 =~ /(?:([^\/]+)_)?memcached_(.+)$/;
 
 325     my $prefix = $1 ? $1 : '';
 
 328     die 'Unknown Plugin Specified: ' . ( $plugin ? $plugin : '' )
 
 329       unless $graphs{$plugin};
 
 331     # Well we need to actually fetch the stats before we do anything to them.
 
 334     # Now lets go ahead and print out our output.
 
 335     print_root_output($plugin);
 
 341 #### This subroutine is for the root non-multigraph graphs which render on the main node page ####
 
 344 sub print_root_output {
 
 347     my $graph = $graphs{$plugin};
 
 349     #print "graph memcached_$plugin\n";
 
 351     if ( $plugin ne 'conns' ) {
 
 352         foreach my $dsrc ( @{ $graph->{datasrc} } ) {
 
 353             my %datasrc = %$dsrc;
 
 354             while ( my ( $key, $value ) = each(%datasrc) ) {
 
 355                 next if ( $key ne 'name' );
 
 356                 my $output = $stats{$value};
 
 357                 print "$dsrc->{name}.value $output\n";
 
 363         foreach my $dsrc ( @{ $graph->{datasrc} } ) {
 
 364             my %datasrc = %$dsrc;
 
 365             while ( my ( $key, $value ) = each(%datasrc) ) {
 
 366                 if ( $value eq 'curr_conns' ) {
 
 367                     $output = $stats{curr_connections};
 
 369                 elsif ( $value eq 'avg_conns' ) {
 
 370                     $output = sprintf( "%02d",
 
 371                         $stats{total_connections} / $stats{uptime} );
 
 376                 print "$dsrc->{name}.value $output\n";
 
 385 #### Subroutines for printing out config information for graphs ####
 
 389 #### This subroutine does the bulk printing the config info per graph ####
 
 393     my ( $prefix, $plugin ) = (@_);
 
 394     print_root_config( $prefix, $plugin );
 
 400 #### This subroutine is for the config info for non multigraph graphs which render on the main node page ####
 
 403 sub print_root_config {
 
 404     my ( $prefix, $plugin ) = (@_);
 
 406     die 'Unknown Plugin Specified: ' . ( $plugin ? $plugin : '' )
 
 407       unless $graphs{$plugin};
 
 409     my $graph = $graphs{$plugin};
 
 411     my %graphconf = %{ $graph->{config} };
 
 413     #print "graph memcached_$plugin\n";
 
 415     while ( my ( $key, $value ) = each(%graphconf) ) {
 
 416         if ( $key eq 'title' ) {
 
 418                 print "graph_$key " . ucfirst($prefix) . " $value\n";
 
 421                 print "graph_$key $value\n";
 
 425             print "graph_$key $value\n";
 
 429     foreach my $dsrc ( @{ $graph->{datasrc} } ) {
 
 430         my %datasrc = %$dsrc;
 
 431         while ( my ( $key, $value ) = each(%datasrc) ) {
 
 432             next if ( $key eq 'name' );
 
 433             print "$dsrc->{name}.$key $value\n";
 
 441 #### This subroutine returns a socket connection ####
 
 447     # check if we want to use sockets instead of tcp
 
 448     my ($sock) = ( $host =~ /unix:\/\/(.+)$/ );
 
 451         $connection = "unix:\/\/$sock";
 
 452         $s = IO::Socket::UNIX->new( Peer => $sock );
 
 455         $connection = "$host:$port";
 
 456         $s          = IO::Socket::INET->new(
 
 468 #### This subroutine actually performs the data fetch for us ####
 
 469 #### These commands do not lock up Memcache at all ####
 
 475     die "Error: Unable to Connect to $connection\n" unless $s;
 
 477     print $s "stats\r\n";
 
 479     while ( my $line = <$s> ) {
 
 480         if ( $line =~ /STAT\s(.+?)\s(\d+)/ ) {
 
 481             my ( $skey, $svalue ) = ( $1, $2 );
 
 482             $stats{$skey} = $svalue;
 
 484         last if $line =~ /^END/;