5 Memcached - A Plugin to monitor Memcached Servers
 
   7 =head1 MUNIN CONFIGURATION
 
  10  env.host 127.0.0.1     *default*
 
  11  env.port 11211         *default*
 
  13 =head2 MUNIN ENVIRONMENT CONFIGURATION EXPLANATION
 
  15  host = host we are going to monitor
 
  16  port = port we are connecting to, in order to gather stats
 
  18 =head1 NODE CONFIGURATION
 
  20 Please make sure you can telnet to your memcache servers and issue the
 
  21  following commands: stats
 
  23 Available Graphs contained in this Plugin
 
  25 bytes => This graphs the current network traffic in and out
 
  27 commands => This graphs the current commands being issued to the memcache machine.
 
  29 conns => This graphs the current, max connections as well as avg conns per sec avg conns per sec is derived from total_conns / uptime.
 
  31 evictions => This graphs the current evictions on the node.
 
  33 items => This graphs the current items and total items in the memcached node.
 
  35 memory => This graphs the current and max memory allocation. 
 
  37 The following example holds true for all graphing options in this plugin.
 
  38  Example: ln -s /usr/share/munin/plugins/memcached_ /etc/munin/plugins/memcached_bytes
 
  40 =head1 ACKNOWLEDGEMENTS
 
  42 The core of this plugin is based on the mysql_ plugin maintained by Kjell-Magne Ãierud
 
  44 Thanks to dormando as well for putting up with me ;)
 
  48 Matt West < https://code.google.com/p/memcached-munin-plugin/ >
 
  57     #%# capabilities=autoconf suggest
 
  64 my $host = $ENV{host} || "127.0.0.1";
 
  65 my $port = $ENV{port} || 11211;
 
  68 # This hash contains the information contained in two memcache commands
 
  69 # stats and stats settings.
 
  71 # So I was trying to figure out how to build this up, and looking at some good examples
 
  72 # I decided to use the format, or for the most part, the format from the mysql_ munin plugin
 
  73 # for Innodb by Kjell-Magne Ãierud, it just spoke ease of flexibility especially with multigraphs
 
  76 # %graphs   is a container for all of the graph definition information. In here is where you'll
 
  77 #           find the configuration information for munin's graphing procedure.
 
  80 #   $graph{graph_name} => {
 
  82 #           # You'll find keys and values stored here for graph manipulation
 
  85 #           # Name: name given to data value
 
  86 #           # Attr: Attribute for given value
 
  87 #           { name => 'Name', (Attr) },
 
  95         args => '--base 1000 --lower-limit 0',
 
  96         vlabel => 'Items in Memcached',
 
  97         category => 'memcached',
 
  99         info => 'This graph shows the number of items in use by memcached',
 
 102         { name => 'curr_items', label => 'Current Items', min => '0' },
 
 103         { name => 'total_items', label => 'New Items', min => '0', type => 'DERIVE' },
 
 109         args => '--base 1024 --lower-limit 0',
 
 110         vlabel => 'Bytes Used',
 
 111         category => 'memcached',
 
 112         title => 'Memory Usage',
 
 113         info => 'This graph shows the memory consumption of memcached',
 
 116         { name => 'limit_maxbytes', draw => 'AREA', label => 'Maximum Bytes Allocated', min => '0' },
 
 117         { name => 'bytes', draw => 'AREA', label => 'Current Bytes Used', min => '0' },
 
 123         args => '--base 1000',
 
 124         vlabel => 'bits in (-) / out (+)',
 
 125         title => 'Network Traffic',
 
 126         category => 'memcached',
 
 127         info => 'This graph shows the network traffic in (-) / out (+) of the machine',
 
 128         order => 'bytes_read bytes_written',
 
 131         { name => 'bytes_read', type => 'DERIVE', label => 'Network Traffic coming in (-)', graph => 'no', cdef => 'bytes_read,8,*', min => '0' },
 
 132         { name => 'bytes_written', type => 'DERIVE', label => 'Traffic in (-) / out (+)', negative => 'bytes_read', cdef => 'bytes_written,8,*', min => '0' },
 
 138         args => '--base 1000 --lower-limit 0',
 
 139         vlabel => 'Connections per ${graph_period}',
 
 140         category => 'memcached',
 
 141         title => 'Connections',
 
 142         info => 'This graph shows the number of connections being handled by memcached',
 
 143         order => 'curr_conns avg_conns',
 
 146         { name => 'curr_conns', label => 'Current Connections', min => '0' },
 
 147         { name => 'avg_conns' , label => 'Avg Connections', min => '0' },
 
 151 $graphs{commands} = {
 
 153         args => '--base 1000 --lower-limit 0',
 
 154         vlabel => 'Commands per ${graph_period}',
 
 155         category => 'memcached',
 
 157         info => 'This graph shows the number of commands being handled by memcached',
 
 160         { name => 'cmd_get', type => 'DERIVE', label => 'Gets', info => 'Cumulative number of retrieval reqs', min => '0' },
 
 161         { name => 'cmd_set', type => 'DERIVE', label => 'Sets', info => 'Cumulative number of storage reqs', min => '0' },
 
 162         { name => 'get_hits', type => 'DERIVE', label => 'Get Hits', info => 'Number of keys that were requested and found', min => '0' },
 
 163         { name => 'get_misses', type => 'DERIVE', label => 'Get Misses', info => 'Number of keys there were requested and not found', min => '0' },
 
 167 $graphs{evictions} = {
 
 169         args => '--base 1000 --lower-limit 0',
 
 170         vlabel => 'Evictions per ${graph_period}',
 
 171         category => 'memcached',
 
 172         title => 'Evictions',
 
 173         info => 'This graph shows the number of evictions per second',
 
 176         { name => 'evictions', label => 'Evictions', info => 'Cumulative Evictions Across All Slabs', type => 'DERIVE', min => '0' },
 
 181 #### Config Check ####
 
 184 if (defined $ARGV[0] && $ARGV[0] eq 'config') {
 
 186     $0 =~ /memcached_(.+)*/;
 
 189     die 'Unknown Plugin Specified: ' . ($plugin ? $plugin : '') unless $graphs{$plugin};
 
 191     # We need to fetch the stats before we do any config, cause its needed for multigraph
 
 194     # Now lets go ahead and print out our config.
 
 200 #### Autoconf Check ####
 
 203 if (defined $ARGV[0] && $ARGV[0] eq 'autoconf') {
 
 205     my $s = IO::Socket::INET->new(
 
 215         print "no (unable to connect to $host\[:$port\])\n";
 
 221 #### Suggest Check ####
 
 224 if (defined $ARGV[0] && $ARGV[0] eq 'suggest') {
 
 226     my $s = IO::Socket::INET->new(
 
 233         my @rootplugins = ('bytes','conns','commands','evictions','items','memory');
 
 234         foreach my $plugin (@rootplugins) {
 
 239         print "no (unable to connect to $host\[:$port\])\n";
 
 245 #### Well We aren't running (auto)config/suggest so lets print some stats ####
 
 251 #### Subroutines for printing info gathered from memcached ####
 
 255 #### This subroutine performs the bulk processing for printing statistics.
 
 260     $0 =~ /memcached_(.+)*/;
 
 263     die 'Unknown Plugin Specified: ' . ($plugin ? $plugin : '') unless $graphs{$plugin};
 
 265     # Well we need to actually fetch the stats before we do anything to them.
 
 268     # Now lets go ahead and print out our output.
 
 269     print_root_output($plugin);
 
 275 #### This subroutine is for the root non-multigraph graphs which render on the main node page ####
 
 278 sub print_root_output {
 
 281     my $graph = $graphs{$plugin};
 
 283     #print "graph memcached_$plugin\n";
 
 285     if ($plugin ne 'conns') {
 
 286         foreach my $dsrc (@{$graph->{datasrc}}) {
 
 287             my %datasrc = %$dsrc;
 
 288             while ( my ($key, $value) = each(%datasrc)) {
 
 289                 next if ($key ne 'name');
 
 290                 my $output = $stats{$value};
 
 291                 print "$dsrc->{name}.value $output\n";
 
 296         foreach my $dsrc (@{$graph->{datasrc}}) {
 
 297             my %datasrc = %$dsrc;
 
 298             while ( my ($key, $value) = each(%datasrc)) {
 
 299                 if ($value eq 'curr_conns') {
 
 300                     $output = $stats{curr_connections};
 
 301                 } elsif ($value eq 'avg_conns') {
 
 302                     $output = sprintf("%02d", $stats{total_connections} / $stats{uptime});
 
 306                 print "$dsrc->{name}.value $output\n";
 
 315 #### Subroutines for printing out config information for graphs ####
 
 319 #### This subroutine does the bulk printing the config info per graph ####
 
 324     print_root_config($plugin);
 
 330 #### This subroutine is for the config info for non multigraph graphs which render on the main node page ####
 
 333 sub print_root_config {
 
 336     die 'Unknown Plugin Specified: ' . ($plugin ? $plugin : '') unless $graphs{$plugin};
 
 338     my $graph = $graphs{$plugin};
 
 340     my %graphconf = %{$graph->{config}};
 
 342     #print "graph memcached_$plugin\n";
 
 344     while ( my ($key, $value) = each(%graphconf)) {
 
 345         print "graph_$key $value\n";
 
 348     foreach my $dsrc (@{$graph->{datasrc}}) {
 
 349         my %datasrc = %$dsrc;
 
 350         while ( my ($key, $value) = each(%datasrc)) {
 
 351             next if ($key eq 'name');
 
 352             print "$dsrc->{name}.$key $value\n";
 
 360 #### This subroutine actually performs the data fetch for us ####
 
 361 #### These commands do not lock up Memcache at all ####
 
 365     my $s = IO::Socket::INET->new(
 
 371     die "Error: Unable to Connect to $host\[:$port\]\n" unless $s;
 
 373     print $s "stats\r\n";
 
 375     while (my $line = <$s>) {
 
 376         if ($line =~ /STAT\s(.+?)\s(\d+)/) {
 
 377             my ($skey,$svalue) = ($1,$2);
 
 378             $stats{$skey} = $svalue;
 
 380         last if $line =~ /^END/;