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