Skip to content

Instantly share code, notes, and snippets.

@hitxiang
Created August 14, 2012 05:51
Show Gist options
  • Save hitxiang/3346702 to your computer and use it in GitHub Desktop.
Save hitxiang/3346702 to your computer and use it in GitHub Desktop.
Munin plugin which monitors several instances of Memcached
#!/usr/bin/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[ID]_FOO where foo is
# the datset name, and id is number of an instance of memcached.
#
# Parameters supported:
#
# config
# autoconf
#
# Configurable variables
#
# host Host of the memcache daemon
# port Port of the memcache daemon
#
# Author: Robin H. Johnson <[email protected]>
# Author: Adam A. Oleksy <[email protected]>
# Slightly based on the original version by Joshua Thijssen
# <[email protected]>
#
# Included in trunk for 1.4 by Nicolai Langfeldt. Set family to contrib
# and disabled autoconf due to lack of "suggest".
#
# Magic markers:
#%# family=contrib
#%# capabilities=noautoconf
use strict;
my $ret = undef;
if (! eval "require Cache::Memcached;") {
$ret = "Cache::Memcached not found";
}
if ( exists $ARGV[0] and $ARGV[0] eq "autoconf" ) {
if ($ret) {
print "no ($ret)\n";
exit 1;
}
# Todo: we can always connect to a memcache server without any errors so I cannot really
# find a way to detect the presence of a memcache instance. Maybe a forced write/read/delete
# but there should be a better way somewhere...
print "yes\n";
exit 0;
}
if($ret) {
print "no ($ret)\n";
exit 1;
}
$0 =~ /memcached(?:_([^_]+)|)_(.+)\s*$/;
my $id = $1;
my $graph = $2;
exit 2 unless defined $graph;
# We do everything by this array
my %all_vars = (
rates => {
master => {
graph_title => "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 => "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 => "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'
},
}
);
my %vars = %{$all_vars{$graph}};
# 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 ";
if ($id and $k eq 'graph_title') {
print "$id - ";
}
print $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 $HOST = exists $ENV{"host"} ? $ENV{"host"} : "127.0.0.1";
my $PORT = exists $ENV{"port"} ? $ENV{"port"} : 11211;
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:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment