root / plugins / zope / zeo_monitor_ @ ed77c82d
Historique | Voir | Annoter | Télécharger (6,6 ko)
| 1 |
#!/usr/bin/perl -Tw |
|---|---|
| 2 |
|
| 3 |
# Plugin to monitor ZEO connected clients, reads, writes and errors/conflicts |
| 4 |
# |
| 5 |
# Author: Terry Burton <tez@terryburton.co.uk> |
| 6 |
# |
| 7 |
# Revisions: |
| 8 |
# |
| 9 |
# 1.0 2010/07/08 First version |
| 10 |
# 1.1 2010/07/09 Split load into reads and writes |
| 11 |
# Reads has logarithmic scale |
| 12 |
# Adjust some scaling factors |
| 13 |
# Support for INET connections, the new default |
| 14 |
# |
| 15 |
# Invoke using symlinks to zeo_monitor_ in the form zeo_monitor_{clients,reads,writes,errors}_<storage_name>
|
| 16 |
# |
| 17 |
# This plugin can be configured manually or by autoconf (provided that the ZEO |
| 18 |
# monitor runs on the default port 8091.) |
| 19 |
# |
| 20 |
# root@munin:~ munin-node-configure --shell |
| 21 |
# ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_clients_1 |
| 22 |
# ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_clients_temp |
| 23 |
# ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_errors_1 |
| 24 |
# ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_errors_temp |
| 25 |
# ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_reads_1 |
| 26 |
# ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_reads_temp |
| 27 |
# ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_writes_1 |
| 28 |
# ln -s /usr/share/munin/plugins/zeo_monitor_ /etc/munin/plugins/zeo_monitor_writes_temp |
| 29 |
# |
| 30 |
# |
| 31 |
# Configuration variables: |
| 32 |
# |
| 33 |
# zeomonitoraddr - address:port of the zeo monitor server socket (default 127.0.0.1:8091) |
| 34 |
# zeomonitorsock - path to the zeo monitor server socket |
| 35 |
# |
| 36 |
# Note: This plugin will attempt to attach to the network socket given by |
| 37 |
# zeomonitoraddr unless the path to a Unix domain socket is given with |
| 38 |
# zeomonitorsock |
| 39 |
# |
| 40 |
# Parameters: |
| 41 |
# |
| 42 |
# config |
| 43 |
# autoconf |
| 44 |
# suggest |
| 45 |
# |
| 46 |
# Configuration examples: |
| 47 |
# |
| 48 |
# Connect to the monitor server running on TCP/4567 |
| 49 |
# |
| 50 |
# [zeo_monitor_*] |
| 51 |
# user root |
| 52 |
# env.zeomonitoraddr 127.0.0.1:4567 |
| 53 |
# |
| 54 |
# Connect to the monitor server running on a Unix domain socket |
| 55 |
# |
| 56 |
# [zeo_monitor_*] |
| 57 |
# user root |
| 58 |
# env.zeomonitorsock /var/run/zeo/zeo-monitor.sock |
| 59 |
# |
| 60 |
# Magic markers (optional - used by munin-config and installation |
| 61 |
# scripts): |
| 62 |
# |
| 63 |
#%# family=auto |
| 64 |
#%# capabilities=autoconf suggest |
| 65 |
|
| 66 |
use strict; |
| 67 |
|
| 68 |
# Need to use eval EXPR here. "-T" is used on the command line, and |
| 69 |
# munin is not installable in a reasonable way for automated testing. |
| 70 |
eval 'use Munin::Plugin; 1;' or die 'Please install Munin::Plugin'; |
| 71 |
|
| 72 |
use File::Basename; |
| 73 |
use IO::Socket::UNIX qw(SOCK_STREAM); |
| 74 |
|
| 75 |
my $zeomonitoraddr = exists $ENV{'zeomonitoraddr'} ? $ENV{'zeomonitoraddr'} : '127.0.0.1:8091';
|
| 76 |
($zeomonitoraddr)=$zeomonitoraddr=~/(.*)/; |
| 77 |
my $zeomonitorsock = exists $ENV{'zeomonitorsock'} ? $ENV{'zeomonitorsock'} : '';
|
| 78 |
($zeomonitorsock)=$zeomonitorsock=~/(.*)/; |
| 79 |
|
| 80 |
if (basename($0) !~ /^zeo_monitor_/) {
|
| 81 |
die qq(Please ensure that the name of the script and it's symlinks starts with "zeo_monitor_"\n); |
| 82 |
} |
| 83 |
|
| 84 |
|
| 85 |
############ |
| 86 |
# autoconf # |
| 87 |
############ |
| 88 |
|
| 89 |
if (defined $ARGV[0] && $ARGV[0] eq 'autoconf') {
|
| 90 |
|
| 91 |
# Capture any croaks on the way |
| 92 |
|
| 93 |
eval { parse_zeo_monitor(); };
|
| 94 |
|
| 95 |
if ( !$@ ) {
|
| 96 |
print "yes\n"; |
| 97 |
exit 0; |
| 98 |
} |
| 99 |
|
| 100 |
chomp $@; |
| 101 |
print "no ($@)\n"; |
| 102 |
exit 0; |
| 103 |
|
| 104 |
} |
| 105 |
|
| 106 |
|
| 107 |
########### |
| 108 |
# suggest # |
| 109 |
########### |
| 110 |
|
| 111 |
if (defined $ARGV[0] and $ARGV[0] eq 'suggest') {
|
| 112 |
|
| 113 |
my @storage_names; |
| 114 |
|
| 115 |
eval { @storage_names=parse_zeo_monitor(); };
|
| 116 |
exit 0 if ( $@ ); |
| 117 |
|
| 118 |
print "clients_$_\nreads_$_\nwrites_$_\nerrors_$_\n" foreach @storage_names; |
| 119 |
exit 0; |
| 120 |
|
| 121 |
} |
| 122 |
|
| 123 |
|
| 124 |
# From now on we require the mode and storage name to be given |
| 125 |
(my $mode,my $storage_name)=$0=~/zeo_monitor_(.+)_(.+)$/; |
| 126 |
die qq(Symlink to this script by appending a mode and storage name such as "zeo_monitor_load_temp"\n) unless defined $storage_name; |
| 127 |
|
| 128 |
|
| 129 |
########## |
| 130 |
# config # |
| 131 |
########## |
| 132 |
|
| 133 |
if ( $ARGV[0] and $ARGV[0] eq "config") {
|
| 134 |
|
| 135 |
print <<"EOF"; |
| 136 |
graph_title ZEO $mode for storage $storage_name |
| 137 |
graph_args --base 1000 --lower-limit 0 |
| 138 |
graph_vlabel events per \${graph_period}
|
| 139 |
graph_category appserver |
| 140 |
graph_info ZEO performance monitoring |
| 141 |
EOF |
| 142 |
|
| 143 |
if ($mode eq 'clients') {
|
| 144 |
print <<EOF; |
| 145 |
clients.label Clients |
| 146 |
clients.type GAUGE |
| 147 |
EOF |
| 148 |
} |
| 149 |
|
| 150 |
if ($mode eq 'reads') {
|
| 151 |
print <<EOF; |
| 152 |
graph_args --logarithmic --lower-limit 1 |
| 153 |
loads.label Loads |
| 154 |
loads.type DERIVE |
| 155 |
loads.min 0 |
| 156 |
EOF |
| 157 |
} |
| 158 |
|
| 159 |
if ($mode eq 'writes') {
|
| 160 |
print <<EOF; |
| 161 |
commits.label Commits (x10) |
| 162 |
commits.type DERIVE |
| 163 |
commits.min 0 |
| 164 |
commits.cdef commits,10,* |
| 165 |
stores.label Stores |
| 166 |
stores.type DERIVE |
| 167 |
stores.min 0 |
| 168 |
EOF |
| 169 |
} |
| 170 |
|
| 171 |
if ($mode eq 'errors') {
|
| 172 |
print <<EOF; |
| 173 |
aborts.label Aborts (x10) |
| 174 |
aborts.type DERIVE |
| 175 |
aborts.min 0 |
| 176 |
aborts.cdef aborts,10,* |
| 177 |
conflicts.label Conflicts (x10) |
| 178 |
conflicts.type DERIVE |
| 179 |
conflicts.min 0 |
| 180 |
conflicts.cdef conflicts,10,* |
| 181 |
conflictsres.label Conflicts Resolved |
| 182 |
conflictsres.type DERIVE |
| 183 |
conflictsres.min 0 |
| 184 |
EOF |
| 185 |
} |
| 186 |
|
| 187 |
exit 0; |
| 188 |
|
| 189 |
} |
| 190 |
|
| 191 |
|
| 192 |
######## |
| 193 |
# main # |
| 194 |
######## |
| 195 |
|
| 196 |
my %stats=parse_zeo_monitor($storage_name); |
| 197 |
|
| 198 |
if ($mode eq 'clients') {
|
| 199 |
print <<"EOF"; |
| 200 |
clients.value $stats{clients}
|
| 201 |
EOF |
| 202 |
} |
| 203 |
|
| 204 |
if ($mode eq 'reads') {
|
| 205 |
print <<"EOF"; |
| 206 |
loads.value $stats{loads}
|
| 207 |
EOF |
| 208 |
} |
| 209 |
|
| 210 |
if ($mode eq 'writes') {
|
| 211 |
print <<"EOF"; |
| 212 |
commits.value $stats{commits}
|
| 213 |
stores.value $stats{stores}
|
| 214 |
EOF |
| 215 |
} |
| 216 |
|
| 217 |
if ($mode eq 'errors') {
|
| 218 |
print <<"EOF"; |
| 219 |
aborts.value $stats{aborts}
|
| 220 |
conflicts.value $stats{conflicts}
|
| 221 |
conflictsres.value $stats{conflictsres}
|
| 222 |
EOF |
| 223 |
} |
| 224 |
|
| 225 |
exit 0; |
| 226 |
|
| 227 |
|
| 228 |
#### |
| 229 |
|
| 230 |
# Read the zeo-monitor socket and parse the result. If a storage name is given |
| 231 |
# then return the stats for it. Otherwise return a list of available storage |
| 232 |
# names. |
| 233 |
|
| 234 |
sub parse_zeo_monitor {
|
| 235 |
|
| 236 |
my $storage_name=shift; |
| 237 |
|
| 238 |
my $socket; |
| 239 |
if ($zeomonitorsock ne '') {
|
| 240 |
$socket=IO::Socket::UNIX->new(Type=>SOCK_STREAM,Peer=>$zeomonitorsock) or die("Can't connect to socket: $!\n");
|
| 241 |
} else {
|
| 242 |
$socket=IO::Socket::INET->new(Proto=>"tcp",PeerAddr=>$zeomonitoraddr) or die("Can't connect to port: $!\n");
|
| 243 |
} |
| 244 |
my $response=join('',<$socket>);
|
| 245 |
close $socket; |
| 246 |
|
| 247 |
# If no storage name is given then return list of all storage names |
| 248 |
if (!defined $storage_name) {
|
| 249 |
return map {/: (.*)/} (grep /^Storage: /, split(/\n/,$response));
|
| 250 |
} |
| 251 |
|
| 252 |
# Otherwise, read the stats for the given storage name |
| 253 |
(my $stats)=$response=~/ |
| 254 |
( |
| 255 |
Storage:\ $storage_name\n |
| 256 |
.*? |
| 257 |
\n |
| 258 |
) |
| 259 |
\n |
| 260 |
/sx; |
| 261 |
|
| 262 |
my %name_var=( |
| 263 |
'Clients' => 'clients', |
| 264 |
'Commits' => 'commits', |
| 265 |
'Aborts' => 'aborts', |
| 266 |
'Loads' => 'loads', |
| 267 |
'Stores' => 'stores', |
| 268 |
'Conflicts' => 'conflicts', |
| 269 |
'Conflicts resolved' => 'conflictsres', |
| 270 |
); |
| 271 |
|
| 272 |
my %stats=(); |
| 273 |
foreach (split /\n/, $stats) {
|
| 274 |
(my $name,my $value)=split ': ',$_,2; |
| 275 |
my $var=$name_var{$name};
|
| 276 |
next unless $var; |
| 277 |
$stats{$var}=$value;
|
| 278 |
} |
| 279 |
|
| 280 |
return %stats; |
| 281 |
|
| 282 |
} |
| 283 |
|
