#!/usr/bin/perl -Tw # Plugin to monitor ZEO connected clients, reads, writes and errors/conflicts # # Author: Terry Burton # # Revisions: # # 1.0 2010/07/08 First version # 1.1 2010/07/09 Split load into reads and writes # Reads has logarithmic scale # Adjust some scaling factors # Support for INET connections, the new default # # Invoke using symlinks to zeo_monitor_ in the form zeo_monitor_{clients,reads,writes,errors}_ # # This plugin can be configured manually or by autoconf (provided that the ZEO # monitor runs on the default port 8091.) # # root@munin:~ munin-node-configure --shell # ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_clients_1 # ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_clients_temp # ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_errors_1 # ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_errors_temp # ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_reads_1 # ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_reads_temp # ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_writes_1 # ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_writes_temp # # # Configuration variables: # # zeomonitoraddr - address:port of the zeo monitor server socket (default 127.0.0.1:8091) # zeomonitorsock - path to the zeo monitor server socket # # Note: This plugin will attempt to attach to the network socket given by # zeomonitoraddr unless the path to a Unix domain socket is given with # zeomonitorsock # # Parameters: # # config # autoconf # suggest # # Configuration examples: # # Connect to the monitor server running on TCP/4567 # # [zeo_monitor_*] # user root # env.zeomonitoraddr 127.0.0.1:4567 # # Connect to the monitor server running on a Unix domain socket # # [zeo_monitor_*] # user root # env.zeomonitorsock /var/run/zeo/zeo-monitor.sock # # Magic markers (optional - used by munin-config and installation # scripts): # #%# family=auto #%# capabilities=autoconf suggest use strict; # Need to use eval EXPR here. "-T" is used on the command line, and # munin is not installable in a reasonable way for automated testing. eval 'use Munin::Plugin; 1;' or die 'Please install Munin::Plugin'; use File::Basename; use IO::Socket::UNIX qw(SOCK_STREAM); my $zeomonitoraddr = exists $ENV{'zeomonitoraddr'} ? $ENV{'zeomonitoraddr'} : '127.0.0.1:8091'; ($zeomonitoraddr)=$zeomonitoraddr=~/(.*)/; my $zeomonitorsock = exists $ENV{'zeomonitorsock'} ? $ENV{'zeomonitorsock'} : ''; ($zeomonitorsock)=$zeomonitorsock=~/(.*)/; if (basename($0) !~ /^zeo_monitor_/) { die qq(Please ensure that the name of the script and it's symlinks starts with "zeo_monitor_"\n); } ############ # autoconf # ############ if (defined $ARGV[0] && $ARGV[0] eq 'autoconf') { # Capture any croaks on the way eval { parse_zeo_monitor(); }; if ( !$@ ) { print "yes\n"; exit 0; } chomp $@; print "no ($@)\n"; exit 0; } ########### # suggest # ########### if (defined $ARGV[0] and $ARGV[0] eq 'suggest') { my @storage_names; eval { @storage_names=parse_zeo_monitor(); }; exit 0 if ( $@ ); print "clients_$_\nreads_$_\nwrites_$_\nerrors_$_\n" foreach @storage_names; exit 0; } # From now on we require the mode and storage name to be given (my $mode,my $storage_name)=$0=~/zeo_monitor_(.+)_(.+)$/; die qq(Symlink to this script by appending a mode and storage name such as "zeo_monitor_load_temp"\n) unless defined $storage_name; ########## # config # ########## if ( $ARGV[0] and $ARGV[0] eq "config") { print <<"EOF"; graph_title ZEO $mode for storage $storage_name graph_args --base 1000 --lower-limit 0 graph_vlabel events per \${graph_period} graph_category appserver graph_info ZEO performance monitoring EOF if ($mode eq 'clients') { print <new(Type=>SOCK_STREAM,Peer=>$zeomonitorsock) or die("Can't connect to socket: $!\n"); } else { $socket=IO::Socket::INET->new(Proto=>"tcp",PeerAddr=>$zeomonitoraddr) or die("Can't connect to port: $!\n"); } my $response=join('',<$socket>); close $socket; # If no storage name is given then return list of all storage names if (!defined $storage_name) { return map {/: (.*)/} (grep /^Storage: /, split(/\n/,$response)); } # Otherwise, read the stats for the given storage name (my $stats)=$response=~/ ( Storage:\ $storage_name\n .*? \n ) \n /sx; my %name_var=( 'Clients' => 'clients', 'Commits' => 'commits', 'Aborts' => 'aborts', 'Loads' => 'loads', 'Stores' => 'stores', 'Conflicts' => 'conflicts', 'Conflicts resolved' => 'conflictsres', ); my %stats=(); foreach (split /\n/, $stats) { (my $name,my $value)=split ': ',$_,2; my $var=$name_var{$name}; next unless $var; $stats{$var}=$value; } return %stats; }