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/;