mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-25 02:18:08 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
cdda2d6bf2
65 changed files with 3666 additions and 159 deletions
378
plugins/asterisk/asterisk
Executable file
378
plugins/asterisk/asterisk
Executable file
|
@ -0,0 +1,378 @@
|
|||
#!/usr/bin/perl -w
|
||||
# -*- cperl -*-
|
||||
|
||||
=head1 NAME
|
||||
|
||||
asterisk - Multigraph-capable plugin to monitor Asterisk
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
This plugin will produce multiple graphs showing:
|
||||
|
||||
- total number of active channels (replaces asterisk_channels),
|
||||
together with breakdown of specific channel types (replaces
|
||||
asterisk_channelstypes);
|
||||
|
||||
- the number of messages in all voicemail boxes (replaces
|
||||
asterisk_voicemail);
|
||||
|
||||
- the number of active MeetMe conferences and users connected to them
|
||||
(replace asterisk_meetme and asterisk_meetmeusers, respectively);
|
||||
|
||||
- the number of active channels for a given codec, for both SIP and
|
||||
IAX2 channels (replaces asterisk_sipchannels and asterisk_codecs).
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
The following configuration parameters are used by this plugin
|
||||
|
||||
[asterisk]
|
||||
env.host - hostname to connect to
|
||||
env.port - port number to connect to
|
||||
env.username - username used for authentication
|
||||
env.secret - secret used for authentication
|
||||
env.channels - The channel types to look for
|
||||
env.codecsx - List of codec IDs (hexadecimal values)
|
||||
env.codecs - List of codecs names, matching codecsx order
|
||||
|
||||
The "username" and "secret" parameters are mandatory, and have no
|
||||
defaults.
|
||||
|
||||
=head2 DEFAULT CONFIGURATION
|
||||
|
||||
[asterisk]
|
||||
env.host 127.0.0.1
|
||||
env.port 5038
|
||||
env.channels Zap IAX2 SIP
|
||||
env.codecsx 0x2 0x4 0x8
|
||||
env.codecs gsm ulaw alaw
|
||||
|
||||
=head2 WILDCARD CONFIGURATION
|
||||
|
||||
It's possible to use the plugin in a virtual-node capacity, in which
|
||||
case the host configuration will default to the hostname following the
|
||||
underscore:
|
||||
|
||||
[asterisk_someserver]
|
||||
env.host someserver
|
||||
env.port 5038
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Copyright (C) 2005-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
|
||||
Copyright (C) 2012 Diego Elio Pettenò <flameeyes@flameeyes.eu>
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv2
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Munin::Plugin;
|
||||
use IO::Socket;
|
||||
|
||||
sub asterisk_command {
|
||||
my ($socket, $command) = @_;
|
||||
my $line, my $reply;
|
||||
|
||||
$socket->print("Action: command\nCommand: $command\n\n");
|
||||
|
||||
# Response: (Error|Follows|???)
|
||||
$line = $socket->getline;
|
||||
if ($line ne "Response: Follows\r\n") {
|
||||
while ( $line = $socket->getline and $line ne "\r\n" ) {}
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Privilege: Command
|
||||
$line = $socket->getline;
|
||||
|
||||
# Until we get the --END COMMAND-- marker, it's the command's output.
|
||||
while ( $line = $socket->getline and $line ne "--END COMMAND--\r\n" ) {
|
||||
$reply .= $line;
|
||||
}
|
||||
|
||||
# And then wait for the empty line that says we're done
|
||||
while ( $line = $socket->getline and $line ne "\r\n" ) {}
|
||||
|
||||
return $reply;
|
||||
}
|
||||
|
||||
$0 =~ /asterisk(?:_(.+))$/;
|
||||
my $hostname = $1;
|
||||
|
||||
my $peeraddr = $ENV{'host'} || $hostname || '127.0.0.1';
|
||||
my $peerport = $ENV{'port'} || '5038';
|
||||
|
||||
my $username = $ENV{'username'};
|
||||
my $secret = $ENV{'secret'};
|
||||
|
||||
my @CHANNELS = exists $ENV{'channels'} ? split ' ',$ENV{'channels'} : qw(Zap IAX2 SIP);
|
||||
my @CODECS = exists $ENV{'codecs'} ? split ' ',$ENV{'codecs'} : qw(gsm ulaw alaw);
|
||||
my @CODECSX = exists $ENV{'codecsx'} ? split ' ',$ENV{'codecsx'} : qw(0x2 0x4 0x8);
|
||||
|
||||
my $line, my $error;
|
||||
my $socket = new IO::Socket::INET(PeerAddr => $peeraddr,
|
||||
PeerPort => $peerport,
|
||||
Proto => 'tcp')
|
||||
or $error = "Could not create socket: $!";
|
||||
|
||||
if ( $socket ) {
|
||||
# This will consume the "Asterisk Call Manager" welcome line.
|
||||
$socket->getline;
|
||||
|
||||
$socket->print("Action: login\nUsername: $username\nSecret: $secret\nEvents: off\n\n");
|
||||
my $response_status = $socket->getline;
|
||||
|
||||
if ( $response_status ne "Response: Success\r\n" ) {
|
||||
my $response_message = $socket->getline;
|
||||
$response_message =~ s/Message: (.*)\r\n/$1/;
|
||||
$error = "Asterisk authentication error: " . $response_message;
|
||||
}
|
||||
|
||||
while ( $line = $socket->getline and $line ne "\r\n" ) {}
|
||||
}
|
||||
|
||||
if ( $ARGV[0] and $ARGV[0] eq 'autoconf' ) {
|
||||
if ( $error ) {
|
||||
print "no ($error)\n";
|
||||
} else {
|
||||
print "yes\n";
|
||||
}
|
||||
|
||||
exit 0;
|
||||
} elsif ( $ARGV[0] and $ARGV[0] eq 'config' ) {
|
||||
print "host_name $hostname" if $hostname;
|
||||
|
||||
print <<END;
|
||||
|
||||
multigraph asterisk_channels
|
||||
graph_title Asterisk active channels
|
||||
graph_args --base 1000 -l 0
|
||||
graph_vlabel channels
|
||||
graph_category asterisk
|
||||
total.label channels
|
||||
END
|
||||
|
||||
foreach my $channel (@CHANNELS) {
|
||||
print <<END;
|
||||
$channel.draw AREASTACK
|
||||
$channel.label $channel channels
|
||||
END
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
multigraph asterisk_voicemail
|
||||
graph_title Asterisk voicemail messages
|
||||
graph_args --base 1000 -l 0
|
||||
graph_vlabel messages
|
||||
graph_category asterisk
|
||||
messages.label Total messages
|
||||
END
|
||||
|
||||
print <<END;
|
||||
|
||||
multigraph asterisk_meetme
|
||||
graph_title Asterisk meetme statistics
|
||||
graph_args --base 1000 -l 0
|
||||
graph_category asterisk
|
||||
users.label Connected users
|
||||
conferences.label Active conferences
|
||||
END
|
||||
|
||||
print <<END;
|
||||
|
||||
multigraph asterisk_codecs
|
||||
graphs_title Asterisk channels per codec
|
||||
graph_args --base 1000 -l 0
|
||||
graph_vlabel channels
|
||||
graph_category asterisk
|
||||
END
|
||||
|
||||
foreach my $codec (@CODECS) {
|
||||
print <<END;
|
||||
$codec.draw AREASTACK
|
||||
$codec.label $codec channels
|
||||
END
|
||||
}
|
||||
|
||||
print <<END;
|
||||
other.draw AREASTACK
|
||||
other.label Other known codecs
|
||||
unknwon.draw AREASTACK
|
||||
unknown.label Unknown codec
|
||||
END
|
||||
|
||||
unless ( ($ENV{MUNIN_CAP_DIRTYCONFIG} || 0) == 1 ) {
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
# if we arrive here and we don't have a socket, it's time to exit.
|
||||
die $error if $error;
|
||||
|
||||
my $channels_response = asterisk_command($socket, "core show channels");
|
||||
#Channel Location State Application(Data)
|
||||
#Zap/pseudo-198641660 s@frompstn:1 Rsrvd (None)
|
||||
#Zap/1-1 4@frompstn:1 Up MeetMe(5500)
|
||||
#2 active channels
|
||||
#1 active call
|
||||
|
||||
my $voicemail_response = asterisk_command($socket, "voicemail show users");
|
||||
#Context Mbox User Zone NewMsg
|
||||
#default 1234 Example Mailbox 1
|
||||
#other 1234 Company2 User 0
|
||||
#2 voicemail users configured.
|
||||
|
||||
my $meetme_response = asterisk_command($socket, "meetme list");
|
||||
#Conf Num Parties Marked Activity Creation
|
||||
#5500 0001 N/A 00:00:03 Static
|
||||
#* Total number of MeetMe users: 1
|
||||
|
||||
my $sipchannels_response = asterisk_command($socket, "sip show channels");
|
||||
#Peer User/ANR Call ID Seq (Tx/Rx) Format
|
||||
#192.168.1.135 yann 6902112b3e0 00101/00002 g729
|
||||
#1 active SIP channel(s)
|
||||
|
||||
my $iaxchannels_response = asterisk_command($socket, "iax2 show channels");
|
||||
#Channel Peer Username ID (Lo/Rem) Seq (Tx/Rx) Lag Jitter JitBuf Format
|
||||
#IAX2/rodolphe@rodolp 10.8.53.6 rodolphe 00003/01287 00006/00004 00000ms 0148ms 0000ms gsm
|
||||
#1 active IAX channel(s)
|
||||
|
||||
# After all the data is fetched we can proceed to process it, the
|
||||
# connection can be closed as we don't need any more data.
|
||||
$socket->close();
|
||||
|
||||
my $active_channels = 'U';
|
||||
$active_channels = $1 if $channels_response =~ /\n([0-9]+) active channels/;
|
||||
|
||||
print <<END;
|
||||
|
||||
multigraph asterisk_channels
|
||||
total.value $active_channels
|
||||
END
|
||||
|
||||
my @channels_list = split(/\r\n/, $channels_response) if $channels_response;
|
||||
foreach my $channel (@CHANNELS) {
|
||||
print "$channel.value ";
|
||||
print $channels_response ? scalar(grep(/^$channel\//, @channels_list)) : "U";
|
||||
print "\n";
|
||||
}
|
||||
|
||||
print "\nmultigraph asterisk_voicemail\n";
|
||||
if ( !$voicemail_response or $voicemail_response =~ /no voicemail users/ ) {
|
||||
print "total.value U\n";
|
||||
} else {
|
||||
my $messages = 0;
|
||||
foreach my $line (split(/\r\n/, $voicemail_response)) {
|
||||
next unless $line =~ / ([0-9]+)$/;
|
||||
$messages += $1;
|
||||
}
|
||||
|
||||
print "total.value $messages\n";
|
||||
}
|
||||
|
||||
print "\nmultigraph asterisk_meetme\n";
|
||||
if ( !$meetme_response ) {
|
||||
print <<END;
|
||||
users.value U
|
||||
conferences.value U
|
||||
END
|
||||
} else {
|
||||
if ( $meetme_response =~ /No active/ ) {
|
||||
print <<END;
|
||||
users.value 0
|
||||
conferences.value 0
|
||||
END
|
||||
} else {
|
||||
my @meetme_list = split(/\r\n/, $meetme_response);
|
||||
|
||||
my $users = pop(@meetme_list);
|
||||
$users =~ s/^Total number of MeetMe users: ([0-9]+)$/$1/;
|
||||
|
||||
print "users.value $users\n";
|
||||
print "conferences.value " . (scalar(@meetme_list)-1) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "\nmultigraph asterisk_codecs\n";
|
||||
if ( !$sipchannels_response and !$iaxchannels_response ) {
|
||||
foreach my $codec (@CODECS) {
|
||||
print "$codec.value U\n";
|
||||
}
|
||||
print <<END;
|
||||
other.value U
|
||||
unknown.valeu U
|
||||
END
|
||||
} else {
|
||||
my @results;
|
||||
my ($i, $start, $unknown, $other)=(0,0,0,0);
|
||||
foreach my $codec (@CODECS) {
|
||||
$results[$i] = 0;
|
||||
$i++;
|
||||
}
|
||||
|
||||
# split the channels' listing and drop header and footnotes
|
||||
my @sipchannels = $sipchannels_response ? split(/\r\n/, $sipchannels_response) : ();
|
||||
pop(@sipchannels); shift(@sipchannels);
|
||||
my @iaxchannels = $iaxchannels_response ? split(/\r\n/, $iaxchannels_response) : ();
|
||||
pop(@iaxchannels); shift(@iaxchannels);
|
||||
|
||||
foreach my $sipchan (@sipchannels) {
|
||||
my $found = 0;
|
||||
my @fields = split ' ', $sipchan;
|
||||
if ($fields[4] eq '0x0') {
|
||||
$unknown += 1;
|
||||
next;
|
||||
}
|
||||
foreach my $codec (@CODECSX) {
|
||||
if ($fields[4] eq "$codec") {
|
||||
$results[$i] = $results[$i] + 1;
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
if (! $found) {
|
||||
$other += 1;
|
||||
print STDERR "CODEC: SIP other format $fields[4]\n" if $Munin::Plugin::DEBUG;
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $iaxchan (@iaxchannels) {
|
||||
my $found = 0;
|
||||
my @fields = split ' ', $iaxchan;
|
||||
|
||||
if ($fields[8] eq '0x0') {
|
||||
$unknown += 1;
|
||||
next;
|
||||
}
|
||||
foreach my $codec (@CODECSX) {
|
||||
if ($fields[8] eq "$codec") {
|
||||
$results[$i] = $results[$i] + 1;
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
if (! $found) {
|
||||
$other += 1;
|
||||
print STDERR "CODEC: IAX2 other format: $fields[8]\n" if $Munin::Plugin::DEBUG;
|
||||
}
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
foreach my $codec (@CODECS) {
|
||||
print "$codec.value $results[$i]\n";
|
||||
$i++;
|
||||
}
|
||||
print "other.value $other\n";
|
||||
print "unknown.value $unknown\n";
|
||||
}
|
37
plugins/db2/db2_cnx
Executable file
37
plugins/db2/db2_cnx
Executable file
|
@ -0,0 +1,37 @@
|
|||
#! /bin/sh
|
||||
# (c) 2012 - Steve Schnepp - LGPL
|
||||
|
||||
# XXX - coded hastily
|
||||
|
||||
# Source the DB2 profile
|
||||
. /home/db2inst1/sqllib/db2profile
|
||||
|
||||
echo "graph_title Number of connections"
|
||||
echo "graph_category DB2"
|
||||
echo "graph_args -l 0"
|
||||
|
||||
db2 list application | tail +5 | awk ' /^[A-Z]/ { print $1 }' | sort | uniq -c > $HOME/run/$(basename $0).txt
|
||||
|
||||
# Get users list
|
||||
touch $HOME/run/$(basename $0).users
|
||||
awk '{ print $2 }' $HOME/run/$(basename $0).txt | cat $HOME/run/$(basename $0).users - | sort -ru > $HOME/run/$(basename $0).users.tmp
|
||||
mv $HOME/run/$(basename $0).users.tmp $HOME/run/$(basename $0).users
|
||||
|
||||
# Emit config
|
||||
if [ "$1" = "config" ]
|
||||
then
|
||||
awk ' { print $1 ".label " $1 "\n" $1 ".draw AREASTACK" }' $HOME/run/$(basename $0).users
|
||||
fi
|
||||
|
||||
# Emit values
|
||||
for i in $( cat $HOME/run/$(basename $0).users )
|
||||
do
|
||||
TMPLINE=$(awk -v i=$i '($2 == i) { print }' $HOME/run/$(basename $0).txt)
|
||||
if [ -z "$TMPLINE" ]
|
||||
then
|
||||
echo "$i.value 0"
|
||||
else
|
||||
echo "$TMPLINE" | awk ' { print $2 ".value " $1 }'
|
||||
|
||||
fi
|
||||
done
|
|
@ -180,7 +180,7 @@ case $name in
|
|||
totalMemGpu=`echo "$totalMemGpus" | sed -n $(( $nGpusCounter + 1 ))p`
|
||||
usedMemGpu=`echo "$usedMemGpus" | sed -n $(( $nGpusCounter + 1 ))p`
|
||||
percentMemUsed=$(( $usedMemGpu * 100 / $totalMemGpu ))
|
||||
valueGpus="${valueGpus}${percentMemUsed}\n"
|
||||
valueGpus="${valueGpus}${percentMemUsed}"
|
||||
: $(( nGpusCounter = $nGpusCounter + 1 ))
|
||||
done
|
||||
;;
|
||||
|
|
|
@ -10,7 +10,12 @@
|
|||
=head1 CONFIGURATION
|
||||
|
||||
[http_request_time]
|
||||
env.url http://127.0.0.1/1 http://127.0.0.1/2 http://127.0.0.1/3
|
||||
env.url1 http://127.0.0.1/1
|
||||
env.url2 http://127.0.0.1/2
|
||||
env.url3 http://www.example.com
|
||||
env.url3_name some_munin_internal_name
|
||||
env.url3_label Some random page on our website
|
||||
env.url3_proxy http://firewall:3128
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
|
@ -41,7 +46,6 @@ sub clean {
|
|||
return $surl;
|
||||
};
|
||||
|
||||
|
||||
if (! eval "require LWP::UserAgent;")
|
||||
{
|
||||
$ret = "LWP::UserAgent not found";
|
||||
|
@ -50,12 +54,19 @@ if (! eval "require LWP::UserAgent;")
|
|||
}
|
||||
}
|
||||
|
||||
my $URL = $ENV{'url'}?$ENV{'url'}:"http://127.0.0.1/";
|
||||
my %URLS;
|
||||
foreach $_ (split(/ /,$URL)){
|
||||
$URLS{$_}={
|
||||
url=>$_,
|
||||
surl=>clean($_),
|
||||
|
||||
for (my $i = 1; $ENV{"url$i"}; $i++)
|
||||
{
|
||||
my $url = $ENV{"url$i"};
|
||||
my $proxy = $ENV{"url${i}_proxy"};
|
||||
my $name = $ENV{"url${i}_name"} || clean($url);
|
||||
my $label = $ENV{"url${i}_label"} || $url;
|
||||
|
||||
$URLS{$name}={
|
||||
url=>$url,
|
||||
proxy=>$proxy,
|
||||
label=>$label,
|
||||
time=>'U'
|
||||
};
|
||||
}
|
||||
|
@ -94,50 +105,67 @@ if ( defined $ARGV[0] and $ARGV[0] eq "config" )
|
|||
print "graph_category other\n";
|
||||
|
||||
my @go;
|
||||
foreach my $url (values %URLS) {
|
||||
print "$$url{'surl'}.label $$url{'url'}\n";
|
||||
print "$$url{'surl'}.info The response time of a single request\n";
|
||||
print "$$url{'surl'}.min 0\n";
|
||||
print "$$url{'surl'}.draw LINE1\n";
|
||||
push(@go,$$url{'surl'});
|
||||
foreach my $name (keys %URLS) {
|
||||
my $url = $URLS{$name};
|
||||
print "$name.label $$url{'label'}\n";
|
||||
print "$name.info The response time of a single request\n";
|
||||
print "$name.min 0\n";
|
||||
print "$name.draw LINE1\n";
|
||||
push(@go, $name);
|
||||
}
|
||||
|
||||
# multigraphs
|
||||
|
||||
foreach my $url (values %URLS) {
|
||||
print "\nmultigraph http_request_time.$$url{'surl'}\n";
|
||||
foreach my $name (keys %URLS) {
|
||||
my $url = $URLS{$name};
|
||||
print "\nmultigraph http_request_time.$name\n";
|
||||
print "graph_title $$url{'url'}\n";
|
||||
print "graph_args --base 1000\n";
|
||||
print "graph_vlabel response time in ms\n";
|
||||
print "graph_category other\n";
|
||||
print "$$url{'surl'}.label $$url{'url'}\n";
|
||||
print "$$url{'surl'}.info The response time of a single request\n";
|
||||
print "$$url{'surl'}.min 0\n";
|
||||
print "$$url{'surl'}.draw LINE1\n";
|
||||
print "$name.label $$url{'label'}\n";
|
||||
print "$name.info The response time of a single request\n";
|
||||
print "$name.min 0\n";
|
||||
print "$name.draw LINE1\n";
|
||||
}
|
||||
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $ua = LWP::UserAgent->new(timeout => 15);
|
||||
foreach my $name (keys %URLS) {
|
||||
my $url = $URLS{$name};
|
||||
|
||||
foreach my $url (values %URLS) {
|
||||
my $t1=[gettimeofday];
|
||||
if ($url->{proxy}) {
|
||||
$ua->proxy(['http', 'ftp'], $url->{proxy});
|
||||
}
|
||||
else {
|
||||
$ua->proxy(['http', 'ftp'], undef);
|
||||
}
|
||||
|
||||
# warm up
|
||||
my $response = $ua->request(HTTP::Request->new('GET',$$url{'url'}));
|
||||
|
||||
# timed run
|
||||
my $t1=[gettimeofday];
|
||||
$response = $ua->request(HTTP::Request->new('GET',$$url{'url'}));
|
||||
my $t2=[gettimeofday];
|
||||
|
||||
if ($response->is_success) {
|
||||
$$url{'time'}=sprintf("%d",tv_interval($t1,$t2)*1000);
|
||||
};
|
||||
};
|
||||
|
||||
print("multigraph http_request_time\n");
|
||||
foreach my $url (values %URLS) {
|
||||
print("$$url{'surl'}.value $$url{'time'}\n");
|
||||
}
|
||||
foreach my $url (values %URLS) {
|
||||
print("\nmultigraph http_request_time.$$url{'surl'}\n");
|
||||
print("$$url{'surl'}.value $$url{'time'}\n");
|
||||
foreach my $name (keys %URLS) {
|
||||
my $url = $URLS{$name};
|
||||
print("$name.value $$url{'time'}\n");
|
||||
}
|
||||
|
||||
foreach my $name (keys %URLS) {
|
||||
my $url = $URLS{$name};
|
||||
print("\nmultigraph http_request_time.$name\n");
|
||||
print("$name.value $$url{'time'}\n");
|
||||
}
|
||||
|
||||
# vim:syntax=perl
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
#
|
||||
# Plugin to show amount of smtp-connections per hour
|
||||
#
|
||||
# Contributed by Håkon Nessjøen <lunatic@cpan.org>
|
||||
# Contributed by Håkon Nessjøen <lunatic@cpan.org>
|
||||
#
|
||||
# Modified by Massimiliano Cianelli <massimiliano@cianelli.eu>
|
||||
# 2013-02-02 - Added support for Greylist and simscan Virus\Spam detect
|
||||
# Added LOGPATH env var
|
||||
#
|
||||
# Magic markers - optional - used by installation scripts and
|
||||
# munin-config:
|
||||
|
@ -10,6 +14,9 @@
|
|||
#%# family=manual
|
||||
#%# capabilities=autoconf
|
||||
|
||||
# get: env.logpath
|
||||
LOGPATH=${logpath:-/var/log/qmail/qmail-smtpd/}
|
||||
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
echo yes
|
||||
exit 0
|
||||
|
@ -17,26 +24,41 @@ fi
|
|||
|
||||
if [ "$1" = "config" ]; then
|
||||
|
||||
echo 'graph_title Qmail SMTP connections'
|
||||
echo 'graph_args --base 1000 -l 0 '
|
||||
echo 'graph_vlabel connections/hour'
|
||||
echo 'graph_category Mail'
|
||||
echo 'graph_order rbl accepted total'
|
||||
echo 'rbl.label RBL rejected connections'
|
||||
echo 'rbl.min 0'
|
||||
echo 'rbl.draw AREA'
|
||||
echo 'accepted.label Accepted connections'
|
||||
echo 'accepted.min 0'
|
||||
echo 'accepted.draw STACK'
|
||||
echo 'total.label Total connections'
|
||||
echo 'total.min 0'
|
||||
echo 'total.draw LINE1'
|
||||
echo 'graph_title Qmail SMTP connections'
|
||||
echo 'graph_args --base 1000 -l 0 '
|
||||
echo 'graph_vlabel connections/hour'
|
||||
echo 'graph_category mail'
|
||||
echo 'graph_order rbl greylisted accepted simscan_spam simscan_virus total'
|
||||
echo 'rbl.label RBL rejected connections'
|
||||
echo 'rbl.min 0'
|
||||
echo 'rbl.draw AREA'
|
||||
echo 'greylisted.label Greylisted connections'
|
||||
echo 'greylisted.min 0'
|
||||
echo 'greylisted.draw STACK'
|
||||
echo 'accepted.label Accepted connections'
|
||||
echo 'accepted.min 0'
|
||||
echo 'accepted.draw STACK'
|
||||
echo 'simscan_spam.label Rejected SPAM'
|
||||
echo 'simscan_spam.min 0'
|
||||
echo 'simscan_spam.draw STACK'
|
||||
echo 'simscan_virus.label Rejected VIRUS'
|
||||
echo 'simscan_virus.min 0'
|
||||
echo 'simscan_virus.draw STACK'
|
||||
echo 'total.label Total connections'
|
||||
echo 'total.min 0'
|
||||
echo 'total.draw LINE1'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
rbl=`cat /var/log/qmail/smtpd/@* /var/log/qmail/smtpd/current | grep -c rblsmtp`
|
||||
accepted=`cat /var/log/qmail/smtpd/@* /var/log/qmail/smtpd/current | grep -c 'tcpserver: ok'`
|
||||
rbl=`cat $LOGPATH/@* $LOGPATH/current | grep -c rblsmtp`
|
||||
accepted=`cat $LOGPATH/@* $LOGPATH/current | grep -c 'tcpserver: ok'`
|
||||
greylisted=`cat $LOGPATH/@* $LOGPATH/current | grep -ce "jgreylist\[[[:digit:]]\+\]: .\+\: GREY"`
|
||||
simscan_spam=`cat $LOGPATH/@* $LOGPATH/current | grep -ce "simscan:\[[[:digit:]]\+\]:SPAM"`
|
||||
simscan_virus=`cat $LOGPATH/@* $LOGPATH/current | grep -ce "simscan:\[[[:digit:]]\+\]:VIRUS"`
|
||||
|
||||
echo -n "rbl.value " && ( echo $rbl || echo U )
|
||||
echo -n "accepted.value " && ( echo $accepted || echo U )
|
||||
echo "total.value $[$rbl + $accepted]"
|
||||
echo -n "greylisted.value " && ( echo $greylisted || echo U )
|
||||
echo -n "simscan_spam.value " && ( echo $simscan_spam || echo U )
|
||||
echo -n "simscan_virus.value " && ( echo $simscan_virus || echo U )
|
||||
echo "total.value $(expr $rbl + $accepted + $greylisted)"
|
||||
|
|
80
plugins/mysql/mysql_size_ondisk
Executable file
80
plugins/mysql/mysql_size_ondisk
Executable file
|
@ -0,0 +1,80 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
INFO=\
|
||||
"mysql_size_ondisk - Munin plugin that reports the size of the files and
|
||||
directories in /var/lib/mysql, biggest to smallest.
|
||||
To correctly count InnoDB tables you should have innodb_file_per_table enabled
|
||||
in MySQL (good practise anyway), otherwise all InnoDB tables will be counted into
|
||||
ibdataX.
|
||||
This plugin must be run as the user mysql, to do that append the following
|
||||
to your /etc/munin/plugins/plugin-conf.d/munin-node:
|
||||
|
||||
[mysql_size_ondisk]
|
||||
user mysql
|
||||
|
||||
This plugin gives you similar information as mysql_size_all. A difference
|
||||
is that mysql_size_ondisk is much faster (0.4 seconds vs 14 seconds, on a server
|
||||
with 170 databases, 26 GB total). Also note that mysql_size_all gives you the net
|
||||
data size, mysql_size_ondisk gives you the gross storage space used, which may be
|
||||
much more than your actual data."
|
||||
#
|
||||
# License: GPLv2 or later
|
||||
#
|
||||
# v1.0, 27.01.2012 Jakob Unterwurzacher <j.unterwurzacher@web-tech.at>
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
set -eu
|
||||
|
||||
DIR=/var/lib/mysql
|
||||
|
||||
function clean {
|
||||
# First character must not be a number
|
||||
a=${1/#[0-9]/_}
|
||||
# Other characters must be alphanumeric
|
||||
b=${a//[^a-zA-Z0-9]/_}
|
||||
echo $b
|
||||
}
|
||||
|
||||
if [ "${1:-}" = "autoconf" ]
|
||||
then
|
||||
if du -sb $DIR &> /dev/null
|
||||
then
|
||||
echo "yes"
|
||||
exit 0
|
||||
else
|
||||
echo "no"
|
||||
exit 1
|
||||
fi
|
||||
elif [ "${1:-}" = "config" ]
|
||||
then
|
||||
echo "graph_title MySQL on-disk database size"
|
||||
echo "graph_category mysql"
|
||||
# graph_info cannot have newlines - replace by <br> which will be rendered to newlines in
|
||||
# the web interface.
|
||||
echo "graph_info ${INFO//$'\n'/<br>}"
|
||||
echo "graph_args --base 1024 --lower-limit 0"
|
||||
echo "graph_vlabel Bytes"
|
||||
cd $DIR
|
||||
du -sb * | sort -nr | while read s i
|
||||
do
|
||||
i=`clean $i`
|
||||
echo "$i.label $i"
|
||||
echo "$i.type GAUGE"
|
||||
echo "$i.draw AREASTACK"
|
||||
done
|
||||
exit 0
|
||||
elif [ "${1:-}" = "" ]
|
||||
then
|
||||
cd $DIR
|
||||
du -sb * | sort -nr | while read s i
|
||||
do
|
||||
i=`clean $i`
|
||||
echo "$i.value $s"
|
||||
done
|
||||
exit 0
|
||||
else
|
||||
echo "Unknown argument"
|
||||
exit 1
|
||||
fi
|
59
plugins/network/if1sec_
Executable file
59
plugins/network/if1sec_
Executable file
|
@ -0,0 +1,59 @@
|
|||
#! /bin/sh
|
||||
|
||||
pluginfull="$0" # full name of plugin
|
||||
plugin="${0##*/}" # name of plugin
|
||||
pidfile="$MUNIN_PLUGSTATE/munin.$plugin.pid"
|
||||
cache="$MUNIN_PLUGSTATE/munin.$plugin.value"
|
||||
|
||||
IFACE="${0##*/if1sec_}" # interface
|
||||
|
||||
if [ ! -r "/sys/class/net/$IFACE/statistics/tx_bytes" ]
|
||||
then
|
||||
echo "# Unknown Interface : $IFACE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" = "acquire" ]
|
||||
then
|
||||
(
|
||||
while sleep 1
|
||||
do
|
||||
echo $(
|
||||
date +%s
|
||||
cat /sys/class/net/$IFACE/statistics/tx_bytes
|
||||
cat /sys/class/net/$IFACE/statistics/rx_bytes
|
||||
)
|
||||
done | awk "{
|
||||
print \"${IFACE}_tx.value \" \$1 \":\" \$2;
|
||||
print \"${IFACE}_rx.value \" \$1 \":\" \$3;
|
||||
system(\"\");
|
||||
}" >> $cache
|
||||
) &
|
||||
echo $! > $pidfile
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
if [ "$1" = "config" ]
|
||||
then
|
||||
cat <<EOF
|
||||
graph_title Interface 1sec stats for ${IFACE}
|
||||
graph_category 1sec::network
|
||||
graph_data_size custom 1d, 10s for 1w, 1m for 1t, 5m for 1y
|
||||
graph_vlabel Bytes
|
||||
update_rate 1
|
||||
${IFACE}_tx.label ${IFACE} TX bytes
|
||||
${IFACE}_tx.type DERIVE
|
||||
${IFACE}_tx.min 0
|
||||
${IFACE}_rx.label ${IFACE} RX bytes
|
||||
${IFACE}_rx.type DERIVE
|
||||
${IFACE}_rx.min 0
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# values
|
||||
cat ${cache}
|
||||
> ${cache}
|
||||
|
||||
exit 0
|
0
plugins/network/netatalk
Normal file → Executable file
0
plugins/network/netatalk
Normal file → Executable file
|
@ -164,6 +164,12 @@ for (my $host_i = 0; $host_i < @host_addrs; ++$host_i) {
|
|||
my $h_norm_name = clean_fieldname($h_cur_name);
|
||||
if ($config_mode) {
|
||||
print "$h_norm_name.min 0\n$h_norm_name.label $h_cur_name\n$h_norm_name.draw LINE2\n";
|
||||
my ( $warning, $critical ) =
|
||||
get_thresholds($h_norm_name);
|
||||
printf "%s.warning %s\n", $h_norm_name, $warning
|
||||
if $warning;
|
||||
printf "%s.critical %s\n", $h_norm_name, $critical
|
||||
if $critical;
|
||||
} else {
|
||||
my $pid = $fork ? fork() : -1;
|
||||
if ($pid <= 0) {
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
# tc - Override default program
|
||||
# ignore_queue<n> - Queue with handle <n> not be plotted
|
||||
# label_name<n> - Queue with handle <n> as defined label
|
||||
# update_rate - Custom update_rate, to be used with async
|
||||
# graph_data_size - Custom graph_data_size, to be used with async & custom update_rate
|
||||
#
|
||||
# Magic markers:
|
||||
#%# family=manual
|
||||
|
@ -100,6 +102,8 @@ if ( exists $ARGV[0] and $ARGV[0] eq 'config' ) {
|
|||
print "graph_vlabel bits per \${graph_period}\n";
|
||||
print "graph_category network\n";
|
||||
print "graph_info This graph shows the QoS queue of the $IFACE network interface.\n";
|
||||
print "update_rate $ENV{update_rate}\n" if $ENV{update_rate};
|
||||
print "graph_data_size $ENV{graph_data_size}\n" if $ENV{graph_data_size};
|
||||
print "graph_order ";
|
||||
foreach my $key (sort by_handle keys %queues) {
|
||||
$haschild = 0;
|
||||
|
|
|
@ -22,6 +22,8 @@ If trouble reading files, use:
|
|||
|
||||
=item 2012.09.20: Initial version by Arturo Borrero Gonzalez <aborrero@cica.es>
|
||||
|
||||
=item 2013.01.12: Added percentage graphing by Michiel Holtkamp <michiel@supermind.nl>
|
||||
|
||||
=back
|
||||
|
||||
=head1 LICENSE
|
||||
|
@ -39,6 +41,7 @@ GPLv2
|
|||
if [ "$1" == "config" ]
|
||||
then
|
||||
cat <<'EOF'
|
||||
multigraph traffic
|
||||
graph_title Throughput by IP protocol
|
||||
graph_vlabel bits per ${graph_period}
|
||||
graph_category network
|
||||
|
@ -55,6 +58,32 @@ total.label Total bps
|
|||
total.min 0
|
||||
total.type DERIVE
|
||||
total.draw LINE1
|
||||
EOF
|
||||
|
||||
# Adapted from http://munin-monitoring.org/wiki/PercentGraphHowto
|
||||
cat <<'EOF'
|
||||
multigraph traffic_percent
|
||||
graph_scale no
|
||||
graph_title Throughput of IP protocols by percentage
|
||||
graph_vlabel Percentage
|
||||
graph_order IPv4=traffic.IPv4 IPv6=traffic.IPv6 total=traffic.total IPv4_percent=traffic.total IPv6_percent=traffic.total total_percent=traffic.total
|
||||
graph_category network
|
||||
graph_args --upper-limit 100 -l 0 -r
|
||||
IPv4.label no
|
||||
IPv6.label no
|
||||
total.label no
|
||||
total_percent.label no
|
||||
IPv4.graph no
|
||||
IPv6.graph no
|
||||
total.graph no
|
||||
total_percent.graph no
|
||||
total_percent.cdef total,0.0000001,+
|
||||
IPv4_percent.label IPv4
|
||||
IPv4_percent.cdef IPv4,total_percent,/,100,*
|
||||
IPv4_percent.draw AREASTACK
|
||||
IPv6_percent.label IPv6
|
||||
IPv6_percent.cdef IPv6,total_percent,/,100,*
|
||||
IPv6_percent.draw AREASTACK
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
|
128
plugins/network/traffic_ipt
Executable file
128
plugins/network/traffic_ipt
Executable file
|
@ -0,0 +1,128 @@
|
|||
#!/bin/bash
|
||||
# -*- bash -*-
|
||||
|
||||
: << =cut
|
||||
|
||||
=head1 NAME
|
||||
|
||||
traffic - Plugin to monitor the traffic (throughput) by IP protocols.
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
To make this plugin work, you need to add rules to your firewall.
|
||||
They are empty rules, we only use them to count traffic, not do anything
|
||||
with them. To make this plugin work correctly, these rules have to
|
||||
in the beginning of the chain(s), or else traffic that matches rules
|
||||
above will not be counted (you can use this to your advantage of course).
|
||||
|
||||
The rules can be added with:
|
||||
iptables -I INPUT
|
||||
iptables -I OUTPUT
|
||||
ip6tables -I INPUT
|
||||
ip6tables -I OUTPUT
|
||||
|
||||
If trouble reading output, use:
|
||||
|
||||
[traffic_ipt]
|
||||
user root
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over
|
||||
|
||||
=item 2012.09.20: Initial version by Arturo Borrero Gonzalez <aborrero@cica.es>
|
||||
|
||||
=item 2013.01.12: Added percentage graphing by Michiel Holtkamp <michiel@supermind.nl>
|
||||
|
||||
=item 2013.02.03: Converted to use iptables/ip6tables by Michiel Holtkamp <michiel@supermind.nl>
|
||||
|
||||
=back
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv2
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
if [ "$1" == "config" ]
|
||||
then
|
||||
cat <<'EOF'
|
||||
multigraph traffic_ipt
|
||||
graph_title Throughput by IP protocol
|
||||
graph_vlabel bits per ${graph_period}
|
||||
graph_category network
|
||||
graph_args --base 1000 --upper-limit 100 -l 0
|
||||
IPv4.label IPv4 bps
|
||||
IPv4.min 0
|
||||
IPv4.type DERIVE
|
||||
IPv4.draw AREA
|
||||
IPv6.label IPv6 bps
|
||||
IPv6.min 0
|
||||
IPv6.type DERIVE
|
||||
IPv6.draw STACK
|
||||
total.label Total bps
|
||||
total.min 0
|
||||
total.type DERIVE
|
||||
total.draw LINE1
|
||||
EOF
|
||||
|
||||
# Adapted from http://munin-monitoring.org/wiki/PercentGraphHowto
|
||||
cat <<'EOF'
|
||||
multigraph traffic_ipt_percent
|
||||
graph_scale no
|
||||
graph_title Throughput of IP protocols by percentage
|
||||
graph_vlabel Percentage
|
||||
graph_order IPv4=traffic_ipt.IPv4 IPv6=traffic_ipt.IPv6 total=traffic_ipt.total IPv4_percent=traffic_ipt.total IPv6_percent=traffic_ipt.total total_percent=traffic_ipt.total
|
||||
graph_category network
|
||||
graph_args --upper-limit 100 -l 0 -r
|
||||
IPv4.label no
|
||||
IPv6.label no
|
||||
total.label no
|
||||
total_percent.label no
|
||||
IPv4.graph no
|
||||
IPv6.graph no
|
||||
total.graph no
|
||||
total_percent.graph no
|
||||
total_percent.cdef total,0.0000001,+
|
||||
IPv4_percent.label IPv4
|
||||
IPv4_percent.cdef IPv4,total_percent,/,100,*
|
||||
IPv4_percent.draw AREASTACK
|
||||
IPv6_percent.label IPv6
|
||||
IPv6_percent.cdef IPv6,total_percent,/,100,*
|
||||
IPv6_percent.draw AREASTACK
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
ipv4=0
|
||||
ipv6=0
|
||||
|
||||
IPv4_bytes=$(iptables -L -n -v -x | egrep '^\W+[0-9]+\W+[0-9]+\W+all\W+--\W+\*\W+\*\W+0.0.0.0/0\W+0.0.0.0/0\W+$' | while read pkts bytes rest; do echo $bytes; done)
|
||||
if [ -z "$IPv4_bytes" ];
|
||||
then
|
||||
echo "W: Unable to read rule from iptables, please add rules" >&2
|
||||
else
|
||||
ipv4=$(echo $IPv4_bytes | sed -e 's/ / + /' | bc -l)
|
||||
fi
|
||||
|
||||
IPv6_bytes=$(ip6tables -L -n -v -x | egrep '^\W+[0-9]+\W+[0-9]+\W+all\W+\*\W+\*\W+::/0\W+::/0\W+$' | while read pkts bytes rest; do echo $bytes; done)
|
||||
if [ -z "$IPv6_bytes" ];
|
||||
then
|
||||
echo "W: Unable to read rule from ip6tables, please add rules" >&2
|
||||
else
|
||||
ipv6=$(echo $IPv6_bytes | sed -e 's/ / + /' | bc -l)
|
||||
fi
|
||||
|
||||
echo "IPv4.value $ipv4"
|
||||
echo "IPv6.value $ipv6"
|
||||
echo "total.value $( echo $ipv4 + $ipv6 | bc )"
|
||||
|
||||
exit 0
|
||||
|
|
@ -56,6 +56,7 @@ def main():
|
|||
'transactions': ("Transactions", "Transactions",
|
||||
('confirmed', 'waiting')),
|
||||
'block_age': ("Last Block Age", "Seconds"),
|
||||
'difficulty': ("Difficulty", ""),
|
||||
}
|
||||
labels = request_labels[request_var]
|
||||
if len(labels) < 3:
|
||||
|
|
48
plugins/qpid/qpid_bytedepth
Executable file
48
plugins/qpid/qpid_bytedepth
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Plugin to monitor Apache Qpid
|
||||
# - graphs the number of outstanding bytes on queue(s) specified in config
|
||||
#
|
||||
# Parameters understood:
|
||||
#
|
||||
# queues (required) - space separated list of queues to display (regex allowed)
|
||||
#
|
||||
# Made by Jimmy Jones (jimmyjones2 AT gmx DOT co DOT uk)
|
||||
#
|
||||
# Licence: GPLv2
|
||||
#
|
||||
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
from qmf.console import Session
|
||||
|
||||
if not "queues" in os.environ:
|
||||
print >> sys.stderr, "Missing env.queues in config"
|
||||
sys.exit(-1)
|
||||
|
||||
output_queue = []
|
||||
sess = Session()
|
||||
broker = sess.addBroker()
|
||||
queues = sess.getObjects(_class="queue", _package="org.apache.qpid.broker")
|
||||
for q in queues:
|
||||
for match in os.environ["queues"].split(" "):
|
||||
if re.match(match, q.name):
|
||||
output_queue.append(re.sub('[^a-zA-Z0-9_]', '_', q.name))
|
||||
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "config":
|
||||
print "graph_category Qpid";
|
||||
print "graph_title Queue byte depth";
|
||||
print "graph_vlabel bytes"
|
||||
for queue in output_queue:
|
||||
print "%s.label %s" % (queue, queue)
|
||||
print "%s.min 0" % queue
|
||||
print "%s.type GAUGE" % queue
|
||||
else:
|
||||
for q in queues:
|
||||
qname = re.sub('[^a-zA-Z0-9_]', '_', q.name)
|
||||
if qname in output_queue:
|
||||
print "%s.value %u" % (qname, q.byteDepth)
|
||||
|
||||
sess.delBroker(broker)
|
||||
|
48
plugins/qpid/qpid_discardsring
Executable file
48
plugins/qpid/qpid_discardsring
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Plugin to monitor Apache Qpid
|
||||
# - graphs the number of messages discarded from queue(s) specified in config
|
||||
#
|
||||
# Parameters understood:
|
||||
#
|
||||
# queues (required) - space separated list of queues to display (regex allowed)
|
||||
#
|
||||
# Made by Jimmy Jones (jimmyjones2 AT gmx DOT co DOT uk)
|
||||
#
|
||||
# Licence: GPLv2
|
||||
#
|
||||
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
from qmf.console import Session
|
||||
|
||||
if not "queues" in os.environ:
|
||||
print >> sys.stderr, "Missing env.queues in config"
|
||||
sys.exit(-1)
|
||||
|
||||
output_queue = []
|
||||
sess = Session()
|
||||
broker = sess.addBroker()
|
||||
queues = sess.getObjects(_class="queue", _package="org.apache.qpid.broker")
|
||||
for q in queues:
|
||||
for match in os.environ["queues"].split(" "):
|
||||
if re.match(match, q.name):
|
||||
output_queue.append(re.sub('[^a-zA-Z0-9_]', '_', q.name))
|
||||
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "config":
|
||||
print "graph_category Qpid";
|
||||
print "graph_title Ring queue discard rate";
|
||||
print "graph_vlabel messages/second";
|
||||
for queue in output_queue:
|
||||
print "%s.label %s" % (queue, queue)
|
||||
print "%s.min 0" % queue
|
||||
print "%s.type COUNTER" % queue
|
||||
else:
|
||||
for q in queues:
|
||||
qname = re.sub('[^a-zA-Z0-9_]', '_', q.name)
|
||||
if qname in output_queue:
|
||||
print "%s.value %u" % (qname, q.discardsRing)
|
||||
|
||||
sess.delBroker(broker)
|
||||
|
48
plugins/qpid/qpid_enqueuebytes
Executable file
48
plugins/qpid/qpid_enqueuebytes
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Plugin to monitor Apache Qpid
|
||||
# - graph ingest rate (bytes/sec) of queue(s) specified in config
|
||||
#
|
||||
# Parameters understood:
|
||||
#
|
||||
# queues (required) - space separated list of queues to display (regex allowed)
|
||||
#
|
||||
# Made by Jimmy Jones (jimmyjones2 AT gmx DOT co DOT uk)
|
||||
#
|
||||
# Licence: GPLv2
|
||||
#
|
||||
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
from qmf.console import Session
|
||||
|
||||
if not "queues" in os.environ:
|
||||
print >> sys.stderr, "Missing env.queues in config"
|
||||
sys.exit(-1)
|
||||
|
||||
output_queue = []
|
||||
sess = Session()
|
||||
broker = sess.addBroker()
|
||||
queues = sess.getObjects(_class="queue", _package="org.apache.qpid.broker")
|
||||
for q in queues:
|
||||
for match in os.environ["queues"].split(" "):
|
||||
if re.match(match, q.name):
|
||||
output_queue.append(re.sub('[^a-zA-Z0-9_]', '_', q.name))
|
||||
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "config":
|
||||
print "graph_category Qpid";
|
||||
print "graph_title Enqueue data rate";
|
||||
print "graph_vlabel bytes/second"
|
||||
for queue in output_queue:
|
||||
print "%s.label %s" % (queue, queue)
|
||||
print "%s.min 0" % queue
|
||||
print "%s.type COUNTER" % queue
|
||||
else:
|
||||
for q in queues:
|
||||
qname = re.sub('[^a-zA-Z0-9_]', '_', q.name)
|
||||
if qname in output_queue:
|
||||
print "%s.value %u" % (qname, q.byteTotalEnqueues)
|
||||
|
||||
sess.delBroker(broker)
|
||||
|
48
plugins/qpid/qpid_enqueuecount
Executable file
48
plugins/qpid/qpid_enqueuecount
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Plugin to monitor Apache Qpid
|
||||
# - graphs ingest rate (messages/sec) of queue(s) specified in config
|
||||
#
|
||||
# Parameters understood:
|
||||
#
|
||||
# queues (required) - space separated list of queues to display (regex allowed)
|
||||
#
|
||||
# Made by Jimmy Jones (jimmyjones2 AT gmx DOT co DOT uk)
|
||||
#
|
||||
# Licence: GPLv2
|
||||
#
|
||||
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
from qmf.console import Session
|
||||
|
||||
if not "queues" in os.environ:
|
||||
print >> sys.stderr, "Missing env.queues in config"
|
||||
sys.exit(-1)
|
||||
|
||||
output_queue = []
|
||||
sess = Session()
|
||||
broker = sess.addBroker()
|
||||
queues = sess.getObjects(_class="queue", _package="org.apache.qpid.broker")
|
||||
for q in queues:
|
||||
for match in os.environ["queues"].split(" "):
|
||||
if re.match(match, q.name):
|
||||
output_queue.append(re.sub('[^a-zA-Z0-9_]', '_', q.name))
|
||||
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "config":
|
||||
print "graph_category Qpid";
|
||||
print "graph_title Enqueue message rate";
|
||||
print "graph_vlabel messages/second"
|
||||
for queue in output_queue:
|
||||
print "%s.label %s" % (queue, queue)
|
||||
print "%s.min 0" % queue
|
||||
print "%s.type COUNTER" % queue
|
||||
else:
|
||||
for q in queues:
|
||||
qname = re.sub('[^a-zA-Z0-9_]', '_', q.name)
|
||||
if qname in output_queue:
|
||||
print "%s.value %u" % (qname, q.msgTotalEnqueues)
|
||||
|
||||
sess.delBroker(broker)
|
||||
|
48
plugins/qpid/qpid_msgdepth
Executable file
48
plugins/qpid/qpid_msgdepth
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Plugin to monitor Apache Qpid
|
||||
# - graphs the number of outstanding messages on queue(s) specified in config
|
||||
#
|
||||
# Parameters understood:
|
||||
#
|
||||
# queues (required) - space separated list of queues to display (regex allowed)
|
||||
#
|
||||
# Made by Jimmy Jones (jimmyjones2 AT gmx DOT co DOT uk)
|
||||
#
|
||||
# Licence: GPLv2
|
||||
#
|
||||
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
from qmf.console import Session
|
||||
|
||||
if not "queues" in os.environ:
|
||||
print >> sys.stderr, "Missing env.queues in config"
|
||||
sys.exit(-1)
|
||||
|
||||
output_queue = []
|
||||
sess = Session()
|
||||
broker = sess.addBroker()
|
||||
queues = sess.getObjects(_class="queue", _package="org.apache.qpid.broker")
|
||||
for q in queues:
|
||||
for match in os.environ["queues"].split(" "):
|
||||
if re.match(match, q.name):
|
||||
output_queue.append(re.sub('[^a-zA-Z0-9_]', '_', q.name))
|
||||
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "config":
|
||||
print "graph_category Qpid";
|
||||
print "graph_title Queue message depth";
|
||||
print "graph_vlabel messages"
|
||||
for queue in output_queue:
|
||||
print "%s.label %s" % (queue, queue)
|
||||
print "%s.min 0" % queue
|
||||
print "%s.type GAUGE" % queue
|
||||
else:
|
||||
for q in queues:
|
||||
qname = re.sub('[^a-zA-Z0-9_]', '_', q.name)
|
||||
if qname in output_queue:
|
||||
print "%s.value %u" % (qname, q.msgDepth)
|
||||
|
||||
sess.delBroker(broker)
|
||||
|
|
@ -27,6 +27,11 @@ file:
|
|||
env.user monitor
|
||||
env.pass passw0rd
|
||||
|
||||
To create an account just for monitoring the ESXi, add a user to the host,
|
||||
make it a member of the 'root' group, and give it the 'No access' role.
|
||||
That will allow the account to connect via WBEM, but not via any of the
|
||||
management tools.
|
||||
|
||||
In the event that not all sensor types are desired, the plugin can be limited
|
||||
to a subset of the types available:
|
||||
|
||||
|
|
|
@ -17,10 +17,29 @@ When used for the local host, the plugin should be linked as
|
|||
non-wildcard plugin, i.e., 'freeipmi', whereas when used to monitor a
|
||||
foreign host it should be, e.g., 'freeipmi_192.168.0.253'.
|
||||
|
||||
=head1 DEPENDENCIES
|
||||
|
||||
The plugin requires FreeIPMI 1.1.5 or later to fetch the information.
|
||||
Limits set on thresholds are available when using FreeIPMI 1.2.0 or
|
||||
later.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Diego Elio Pettenò <flameeyes@flameeyes.eu>.
|
||||
|
||||
With help and suggestions of:
|
||||
|
||||
Bart ten Brinke <info@retrosync.com>
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv2
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv2
|
||||
|
@ -42,12 +61,15 @@ my $IPMISENSORS = $ENV{'ipmisensors'} || 'ipmi-sensors';
|
|||
$0 =~ /freeipmi(?:_(.+))$/;
|
||||
my $hostname = $1;
|
||||
|
||||
$IPMISENSORS .= " --quiet-cache --comma-separated-output --no-header-output --ignore-not-available-sensors --sensor-types=Temperature,Fan,Current,Voltage --output-sensor-thresholds";
|
||||
my $help_output = `$IPMISENSORS --help`;
|
||||
|
||||
$IPMISENSORS .= " --output-sensor-thresholds" if $help_output =~ /--output-sensor-thresholds/;
|
||||
$IPMISENSORS .= " --quiet-cache --comma-separated-output --no-header-output --ignore-not-available-sensors --sensor-types=Temperature,Fan,Current,Voltage";
|
||||
$IPMISENSORS .= " --hostname=$hostname" if defined($hostname);
|
||||
$IPMISENSORS .= " --username=$ENV{IPMI_USERNAME}" if defined($ENV{IPMI_USERNAME});
|
||||
$IPMISENSORS .= " --password=$ENV{IPMI_PASSWORD}" if defined($ENV{IPMI_PASSWORD});
|
||||
|
||||
my $output=`$IPMISENSORS --output-sensor-thresholds 2>/dev/null`;
|
||||
my $output=`$IPMISENSORS 2>/dev/null`;
|
||||
my $retval=$?;
|
||||
|
||||
if ( defined $ARGV[0] and $ARGV[0] eq 'autoconf' ) {
|
||||
|
@ -109,11 +131,11 @@ foreach my $line (@data) {
|
|||
value => $dataline[3],
|
||||
label => $dataline[1]
|
||||
);
|
||||
$sensor{lwarn} = $dataline[7] ne "N/A" ? $dataline[7] : '';
|
||||
$sensor{hwarn} = $dataline[8] ne "N/A" ? $dataline[8] : '';
|
||||
$sensor{lwarn} = (defined($dataline[7]) and $dataline[7] ne "N/A") ? $dataline[7] : '';
|
||||
$sensor{hwarn} = (defined($dataline[8]) and $dataline[8] ne "N/A") ? $dataline[8] : '';
|
||||
|
||||
$sensor{lcrit} = $dataline[6] ne "N/A" ? $dataline[6] : '';
|
||||
$sensor{hcrit} = $dataline[9] ne "N/A" ? $dataline[9] : '';
|
||||
$sensor{lcrit} = (defined($dataline[6]) and $dataline[6] ne "N/A") ? $dataline[6] : '';
|
||||
$sensor{hcrit} = (defined($dataline[9]) and $dataline[9] ne "N/A") ? $dataline[9] : '';
|
||||
|
||||
my $type;
|
||||
if ( $dataline[2] eq "Temperature" ) {
|
||||
|
@ -158,7 +180,7 @@ END
|
|||
}
|
||||
}
|
||||
|
||||
unless ( $ENV{MUNIN_CAP_DIRTYCONFIG} == 1 ) {
|
||||
unless ( ($ENV{MUNIN_CAP_DIRTYCONFIG} || 0) == 1 ) {
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ END
|
|||
}
|
||||
}
|
||||
|
||||
unless ( $ENV{MUNIN_CAP_DIRTYCONFIG} == 1 ) {
|
||||
unless ( ($ENV{MUNIN_CAP_DIRTYCONFIG} || 0) == 1 ) {
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
|
69
plugins/sickbeard/sickbeard_episodes
Executable file
69
plugins/sickbeard/sickbeard_episodes
Executable file
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# Munin plugins for Sick-Beard
|
||||
#
|
||||
# Copyright (C) 2012 - Blauwbek
|
||||
# Copyright (C) 2012 - Thiago
|
||||
#
|
||||
# Sick-Beard : http://sickbeard.com/
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Requires: JSON::Any
|
||||
# LWP::UserAgent
|
||||
#
|
||||
# Configuration example
|
||||
# [sickbeard*]
|
||||
# env.host http://host:port/
|
||||
# env.api apikey
|
||||
#
|
||||
|
||||
use strict;
|
||||
use JSON::Any;
|
||||
use LWP::UserAgent;
|
||||
|
||||
#defines
|
||||
my $HOST = exists $ENV{'host'} ? $ENV{'host'} : "http://localhost:8081/";
|
||||
my $API = exists $ENV{'api'} ? $ENV{'api'} : "";
|
||||
my $URL = $HOST."/api/".$API."/?cmd=shows.stats";
|
||||
my $sURL = sprintf $URL;
|
||||
|
||||
#config output
|
||||
if(defined $ARGV[0] && $ARGV[0] eq 'config')
|
||||
{
|
||||
print <<EOC
|
||||
graph_title Episodes
|
||||
graph_vlabel Episodes
|
||||
graph_category Sick-Beard
|
||||
down.label Downloaded
|
||||
total.label Total
|
||||
EOC
|
||||
;
|
||||
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $get = LWP::UserAgent->new;
|
||||
my $req = $get->get($sURL);
|
||||
my $json = JSON::Any->jsonToObj($req->content());
|
||||
|
||||
if ($json->{result} eq 'success') {
|
||||
print "down.value $json->{data}->{ep_downloaded}\n";
|
||||
print "total.value $json->{data}->{ep_total}\n";
|
||||
exit 0;
|
||||
} else {
|
||||
print "$json->{message}\n";
|
||||
exit 1;
|
||||
}
|
||||
|
69
plugins/sickbeard/sickbeard_shows
Executable file
69
plugins/sickbeard/sickbeard_shows
Executable file
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# Munin plugins for Sick-Beard
|
||||
#
|
||||
# Copyright (C) 2012 - Blauwbek
|
||||
# Copyright (C) 2012 - Thiago
|
||||
#
|
||||
# Sick-Beard : http://sickbeard.com/
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Requires: JSON::Any
|
||||
# LWP::UserAgent
|
||||
#
|
||||
# Configuration example
|
||||
# [sickbeard*]
|
||||
# env.host http://host:port/
|
||||
# env.api apikey
|
||||
#
|
||||
|
||||
use strict;
|
||||
use JSON::Any;
|
||||
use LWP::UserAgent;
|
||||
|
||||
#defines
|
||||
my $HOST = exists $ENV{'host'} ? $ENV{'host'} : "http://localhost:8081/";
|
||||
my $API = exists $ENV{'api'} ? $ENV{'api'} : "";
|
||||
my $URL = $HOST."/api/".$API."/?cmd=shows.stats";
|
||||
my $sURL = sprintf $URL;
|
||||
|
||||
#config output
|
||||
if(defined $ARGV[0] && $ARGV[0] eq 'config')
|
||||
{
|
||||
print <<EOC
|
||||
graph_title Shows
|
||||
graph_vlabel Shows
|
||||
graph_category Sick-Beard
|
||||
active.label Active
|
||||
total.label Total
|
||||
EOC
|
||||
;
|
||||
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $get = LWP::UserAgent->new;
|
||||
my $req = $get->get($sURL);
|
||||
my $json = JSON::Any->jsonToObj($req->content());
|
||||
|
||||
if ($json->{result} eq 'success') {
|
||||
print "active.value $json->{data}->{shows_active}\n";
|
||||
print "total.value $json->{data}->{shows_total}\n";
|
||||
exit 0;
|
||||
} else {
|
||||
print "$json->{message}\n";
|
||||
exit 1;
|
||||
}
|
||||
|
106
plugins/system/cpu_by_process
Executable file
106
plugins/system/cpu_by_process
Executable file
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# Copyright 2012 Chris Wilson
|
||||
# Copyright 2006 Holger Levsen
|
||||
#
|
||||
# This plugin monitors ALL processes on a system. No exceptions. It can
|
||||
# produce very big graphs! But if you want to know where your CPU time
|
||||
# is going without knowing what to monitor in advance, this can help;
|
||||
# or in addition to one of the more specific CPU plugins to monitor
|
||||
# just Apache or MySQL, for example.
|
||||
#
|
||||
# It's not obvious what the graph heights actually mean, even to me.
|
||||
# Each counter is a DERIVE (difference since the last counter reading)
|
||||
# of the CPU time usage (in seconds) accounted to each process, summed
|
||||
# by the process name, so all Apache and all MySQL processes are grouped
|
||||
# together. Processes with no CPU usage at all are ignored. Processes
|
||||
# that die may not appear on the graph, and anyway their last chunk of
|
||||
# CPU usage before they died is lost. You could modify this plugin to
|
||||
# read SAR/psacct records if you care about that.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; version 2 dated June,
|
||||
# 1991.
|
||||
|
||||
#scriptname=`basename $0`
|
||||
#vsname=`echo $scriptname | perl -ne '/^vserver_proc_VM_(.*)/ and print $1'`
|
||||
|
||||
#if [ "$1" = "suggest" ]; then
|
||||
# ls -1 /etc/vservers
|
||||
# exit 0
|
||||
#elif [ -z "$vsname" ]; then
|
||||
# echo "Must be used with a vserver name; try '$0 suggest'" >&2
|
||||
# exit 2
|
||||
#fi
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $cmd = "ps -eo time,comm h";
|
||||
open PS, "$cmd|" or die "Failed to run ps command: $cmd: $!";
|
||||
|
||||
# my $header_line = <PS>;
|
||||
my %total_cpu_by_process;
|
||||
|
||||
while (<PS>)
|
||||
{
|
||||
my @fields = split;
|
||||
my $cputime = $fields[0];
|
||||
my $process = $fields[1];
|
||||
|
||||
# remove any / and everything after it from the process name,
|
||||
# e.g. kworker/0:2 -> kworker
|
||||
$process =~ s|/.*||;
|
||||
|
||||
# remove any . at the end of the name (why does this appear?)
|
||||
# $process =~ s|\.$||;
|
||||
|
||||
# change any symbol that's not allowed in a munin variable name to _
|
||||
$process =~ tr|a-zA-Z0-9|_|c;
|
||||
|
||||
my @times = split /:/, $cputime;
|
||||
$cputime = (($times[0] * 60) + $times[1]) * 60 + $times[2];
|
||||
$total_cpu_by_process{$process} += $cputime;
|
||||
}
|
||||
|
||||
foreach my $process (keys %total_cpu_by_process)
|
||||
{
|
||||
# remove all processes with 0 cpu time
|
||||
if (not $total_cpu_by_process{$process})
|
||||
{
|
||||
delete $total_cpu_by_process{$process};
|
||||
}
|
||||
}
|
||||
|
||||
close(PS);
|
||||
|
||||
if (@ARGV and $ARGV[1] eq "config")
|
||||
{
|
||||
print <<END;
|
||||
graph_title CPU time by Process
|
||||
graph_args --base 1000
|
||||
graph_vlabel seconds
|
||||
graph_category system
|
||||
graph_info Shows CPU time used by each process name
|
||||
END
|
||||
|
||||
my $stack = 0;
|
||||
sub draw() { return $stack++ ? "STACK" : "AREA" }
|
||||
print map
|
||||
{
|
||||
"$_.label $_\n" .
|
||||
"$_.min 0\n" .
|
||||
"$_.type DERIVE\n" .
|
||||
"$_.draw " . draw() . "\n"
|
||||
} sort keys %total_cpu_by_process;
|
||||
}
|
||||
else
|
||||
{
|
||||
print map
|
||||
{
|
||||
"$_.value $total_cpu_by_process{$_}\n"
|
||||
} sort keys %total_cpu_by_process;
|
||||
}
|
||||
|
||||
exit(0);
|
0
plugins/system/membyuser
Normal file → Executable file
0
plugins/system/membyuser
Normal file → Executable file
0
plugins/system/memory_by_process
Normal file → Executable file
0
plugins/system/memory_by_process
Normal file → Executable file
|
@ -25,8 +25,8 @@ run_watchdog() { # should also trap kill and term signals
|
|||
|
||||
run_acquire() {
|
||||
echo "$$" > $pidfile
|
||||
mpstat -P ALL $interval |
|
||||
awk -v cpus=$cpus '$2>=0&&$2<10 {print $2, systime(), (100-$11)/cpus}' >> $cache
|
||||
LANG=C mpstat -P ALL $interval |
|
||||
awk -v cpus=$cpus '$2>=0&&$2<99 {print $2, systime(), (100-$11)/cpus; system("");}' >> $cache
|
||||
rm -f $pidfile $cache
|
||||
}
|
||||
|
||||
|
|
105
plugins/system/pagefaults_by_process
Executable file
105
plugins/system/pagefaults_by_process
Executable file
|
@ -0,0 +1,105 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# Copyright 2012 Chris Wilson
|
||||
# Copyright 2006 Holger Levsen
|
||||
#
|
||||
# This plugin monitors ALL processes on a system. No exceptions. It can
|
||||
# produce very big graphs! But if you want to know which processes are
|
||||
# killing your system by page faulting, without knowing what to monitor
|
||||
# in advance, this can help; or in addition to one of the more specific
|
||||
# plugins to monitor just Apache or MySQL, for example.
|
||||
#
|
||||
# Each counter is a DERIVE (difference since the last counter reading)
|
||||
# of the number of major page faults, usually 4k each, read in by a
|
||||
# process. Memory mapped files probably contribute to this. The process
|
||||
# cannot continue until the page fault is served, so this is a
|
||||
# high-priority read that usually indicates memory starvation.
|
||||
# Processes with no page faults at all are ignored. Processes
|
||||
# that die may not appear on the graph, and anyway their last chunk of
|
||||
# CPU usage before they died is lost. You could modify this plugin to
|
||||
# read SAR/psacct records if you care about that.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; version 2 dated June,
|
||||
# 1991.
|
||||
|
||||
#scriptname=`basename $0`
|
||||
#vsname=`echo $scriptname | perl -ne '/^vserver_proc_VM_(.*)/ and print $1'`
|
||||
|
||||
#if [ "$1" = "suggest" ]; then
|
||||
# ls -1 /etc/vservers
|
||||
# exit 0
|
||||
#elif [ -z "$vsname" ]; then
|
||||
# echo "Must be used with a vserver name; try '$0 suggest'" >&2
|
||||
# exit 2
|
||||
#fi
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $cmd = "ps -eo maj_flt,comm h";
|
||||
open PS, "$cmd|" or die "Failed to run ps command: $cmd: $!";
|
||||
|
||||
# my $header_line = <PS>;
|
||||
my %total_by_process;
|
||||
|
||||
while (<PS>)
|
||||
{
|
||||
my @fields = split;
|
||||
my $value = $fields[0];
|
||||
my $process = $fields[1];
|
||||
|
||||
# remove any / and everything after it from the process name,
|
||||
# e.g. kworker/0:2 -> kworker
|
||||
$process =~ s|/.*||;
|
||||
|
||||
# remove any . at the end of the name (why does this appear?)
|
||||
# $process =~ s|\.$||;
|
||||
|
||||
# change any symbol that's not allowed in a munin variable name to _
|
||||
$process =~ tr|a-zA-Z0-9|_|c;
|
||||
|
||||
$total_by_process{$process} += $value;
|
||||
}
|
||||
|
||||
foreach my $process (keys %total_by_process)
|
||||
{
|
||||
# remove all processes with 0 faults
|
||||
if (not $total_by_process{$process})
|
||||
{
|
||||
delete $total_by_process{$process};
|
||||
}
|
||||
}
|
||||
|
||||
close(PS);
|
||||
|
||||
if (@ARGV and $ARGV[1] eq "config")
|
||||
{
|
||||
print <<END;
|
||||
graph_title Page faults by Process
|
||||
graph_args --base 1000
|
||||
graph_vlabel seconds
|
||||
graph_category system
|
||||
graph_info Shows number of major page faults caused by each process name
|
||||
END
|
||||
|
||||
my $stack = 0;
|
||||
sub draw() { return $stack++ ? "STACK" : "AREA" }
|
||||
print map
|
||||
{
|
||||
"$_.label $_\n" .
|
||||
"$_.min 0\n" .
|
||||
"$_.type DERIVE\n" .
|
||||
"$_.draw " . draw() . "\n"
|
||||
} sort keys %total_by_process;
|
||||
}
|
||||
else
|
||||
{
|
||||
print map
|
||||
{
|
||||
"$_.value $total_by_process{$_}\n"
|
||||
} sort keys %total_by_process;
|
||||
}
|
||||
|
||||
exit(0);
|
119
plugins/system/total_by_process_
Executable file
119
plugins/system/total_by_process_
Executable file
|
@ -0,0 +1,119 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# Copyright 2012 Chris Wilson
|
||||
# Copyright 2006 Holger Levsen
|
||||
#
|
||||
# This plugin monitors ALL processes on a system. No exceptions. It can
|
||||
# produce very big graphs! But if you want to know which processes are
|
||||
# killing your system by page faulting, without knowing what to monitor
|
||||
# in advance, this can help; or in addition to one of the more specific
|
||||
# plugins to monitor just Apache or MySQL, for example.
|
||||
#
|
||||
# Each counter is a DERIVE (difference since the last counter reading)
|
||||
# of the number of major page faults, usually 4k each, read in by a
|
||||
# process. Memory mapped files probably contribute to this. The process
|
||||
# cannot continue until the page fault is served, so this is a
|
||||
# high-priority read that usually indicates memory starvation.
|
||||
# Processes with no page faults at all are ignored. Processes
|
||||
# that die may not appear on the graph, and anyway their last chunk of
|
||||
# CPU usage before they died is lost. You could modify this plugin to
|
||||
# read SAR/psacct records if you care about that.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; version 2 dated June,
|
||||
# 1991.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $scriptname = $0;
|
||||
$scriptname =~ s|.*/||;
|
||||
my $fieldname = ($scriptname =~ /^total_by_process_(.*)_(.*)/) ? $1 : undef;
|
||||
my $fieldtype = ($scriptname =~ /^total_by_process_(.*)_(.*)/) ? $2 : undef;
|
||||
|
||||
if (@ARGV and $ARGV[1] eq "suggest")
|
||||
{
|
||||
system("ps L | cut -d' ' -f1");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!$fieldname)
|
||||
{
|
||||
print STDERR "Must be used with a PS format specifier name; try '$0 suggest'";
|
||||
exit(2);
|
||||
}
|
||||
|
||||
unless ($fieldtype =~ /^(GAUGE|DERIVE)$/)
|
||||
{
|
||||
print STDERR "Unknown field type $fieldtype: should be GAUGE or DERIVE";
|
||||
exit(2);
|
||||
}
|
||||
|
||||
my $cmd = "ps -eo $fieldname,comm h";
|
||||
open PS, "$cmd|" or die "Failed to run ps command: $cmd: $!";
|
||||
|
||||
# my $header_line = <PS>;
|
||||
my %total_by_process;
|
||||
|
||||
while (<PS>)
|
||||
{
|
||||
my @fields = split;
|
||||
my $value = $fields[0];
|
||||
my $process = $fields[1];
|
||||
|
||||
# remove any / and everything after it from the process name,
|
||||
# e.g. kworker/0:2 -> kworker
|
||||
$process =~ s|/.*||;
|
||||
|
||||
# remove any . at the end of the name (why does this appear?)
|
||||
# $process =~ s|\.$||;
|
||||
|
||||
# change any symbol that's not allowed in a munin variable name to _
|
||||
$process =~ tr|a-zA-Z0-9|_|c;
|
||||
|
||||
$total_by_process{$process} += $value;
|
||||
}
|
||||
|
||||
foreach my $process (keys %total_by_process)
|
||||
{
|
||||
# remove all processes with 0 faults
|
||||
if (not $total_by_process{$process})
|
||||
{
|
||||
delete $total_by_process{$process};
|
||||
}
|
||||
}
|
||||
|
||||
close(PS);
|
||||
|
||||
if (@ARGV and $ARGV[1] == "config")
|
||||
{
|
||||
print <<END;
|
||||
graph_title $fieldname by Process
|
||||
graph_category system
|
||||
graph_info Shows total of $fieldname (reported by ps) for each process name
|
||||
graph_vlabel $fieldname (from ps)
|
||||
END
|
||||
|
||||
# graph_args --base 1000
|
||||
# graph_vlabel seconds
|
||||
|
||||
my $stack = 0;
|
||||
sub draw() { return $stack++ ? "STACK" : "AREA" }
|
||||
print map
|
||||
{
|
||||
"$_.label $_\n" .
|
||||
"$_.min 0\n" .
|
||||
"$_.type $fieldtype\n" .
|
||||
"$_.draw " . draw() . "\n"
|
||||
} sort keys %total_by_process;
|
||||
}
|
||||
else
|
||||
{
|
||||
print map
|
||||
{
|
||||
"$_.value $total_by_process{$_}\n"
|
||||
} sort keys %total_by_process;
|
||||
}
|
||||
|
||||
exit(0);
|
|
@ -1,19 +1,21 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This plugin shows Solaris zone memory usage.
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
PRSTAT=/usr/bin/prstat
|
||||
PRSTAT_OPTS="-Z 1 1"
|
||||
PRSTAT_OPTS="-Z -n 1,99 1 1"
|
||||
|
||||
if [ "$1" = 'autoconf' ]; then
|
||||
if [ -f $PRSTAT ]; then
|
||||
zones=`/usr/sbin/zoneadm list | wc -l`
|
||||
if [ $zones -gt 1 ]; then
|
||||
echo yes
|
||||
else
|
||||
echo yes
|
||||
fi
|
||||
zones=`/usr/sbin/zoneadm list | wc -l`
|
||||
if [ $zones -gt 1 ]; then
|
||||
echo yes
|
||||
else
|
||||
echo yes
|
||||
fi
|
||||
exit 0
|
||||
else
|
||||
echo no
|
||||
|
@ -24,18 +26,18 @@ fi
|
|||
if [ "$1" = 'config' ]; then
|
||||
echo 'graph_title zone memory usage'
|
||||
echo 'graph_args --upper-limit 100'
|
||||
echo 'graph_category system'
|
||||
stack=AREA
|
||||
echo 'graph_category system'
|
||||
stack=AREA
|
||||
$PRSTAT $PRSTAT_OPTS | sed '1,/^ZONEID/d' | grep -v '^Total' | while read i; do
|
||||
oIFS="$IFS"
|
||||
IFS='
|
||||
oIFS="$IFS"
|
||||
IFS='
|
||||
'
|
||||
set -$- $i
|
||||
name=$1
|
||||
label=$8
|
||||
set -$- $i
|
||||
name=$1
|
||||
label=$8
|
||||
printf "$name.label $label\n$name.draw $stack\n$name.warn 95\n"
|
||||
IFS="$oIFS"
|
||||
stack=STACK
|
||||
IFS="$oIFS"
|
||||
stack=STACK
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
@ -48,12 +50,12 @@ fi
|
|||
# Total: 207 processes, 709 lwps, load averages: 0.05, 0.06, 0.11$
|
||||
|
||||
$PRSTAT $PRSTAT_OPTS | sed '1,/^ZONEID/d' | grep -v '^Total' | while read i; do
|
||||
oIFS="$IFS"
|
||||
IFS='%
|
||||
oIFS="$IFS"
|
||||
IFS='%
|
||||
'
|
||||
set -$- $i
|
||||
name=$1
|
||||
value=$5
|
||||
printf "$name.value $value\n"
|
||||
IFS="$oIFS"
|
||||
set -$- $i
|
||||
name=$1
|
||||
value=$5
|
||||
printf "$name.value $value\n"
|
||||
IFS="$oIFS"
|
||||
done
|
||||
|
|
|
@ -21,7 +21,7 @@ $0 =~ /vdr_(.+)*$/;
|
|||
my $host = $1 || "localhost";;
|
||||
|
||||
#print "Name: $0\nHost: $host\n";
|
||||
my $SVDRPSENDPL="/usr/bin/svdrpsend.pl -d $host";
|
||||
my $SVDRPSENDPL="/usr/bin/svdrpsend -d $host";
|
||||
|
||||
sub ermittelnTimer;
|
||||
sub ermittelnAufnahmen;
|
||||
|
|
|
@ -19,6 +19,9 @@ configuration:
|
|||
|
||||
[xen-multi]
|
||||
user root
|
||||
env.xenskip "<space separated module list>"
|
||||
|
||||
Modules: cput, cpup, mem, disk, net
|
||||
|
||||
Then restart munin-node and you're done.
|
||||
|
||||
|
@ -34,10 +37,14 @@ NOTE: xentop always reports 0 for dom0's disk IOs and network traffic, but
|
|||
both graphs show its entry all the same, so each domain can keep its own color
|
||||
along the different graphs.
|
||||
|
||||
=head2 CPU usage
|
||||
=head2 CPU time
|
||||
|
||||
This graph shows a percentage of the CPU time used by each domain.
|
||||
|
||||
=head2 CPU usage
|
||||
|
||||
This graph shows a percentage of the CPU percentage used by each domain.
|
||||
|
||||
=head2 Memory usage
|
||||
|
||||
This graph shows the amount of memory (in bytes) used by each domain.
|
||||
|
@ -66,6 +73,7 @@ Michael Renner for the C<diskstats> plugin which I borrowed some code from.
|
|||
=head1 AUTHOR
|
||||
|
||||
Raphael HALIMI <raphael.halimi@gmail.com>
|
||||
Modified by Krisztian IVANCSO <github-ivan@ivancso.net>
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
|
@ -76,6 +84,8 @@ GPLv2
|
|||
use strict;
|
||||
use Munin::Plugin;
|
||||
|
||||
my $XEN_SKIP = $ENV{xenskip} || "";
|
||||
|
||||
# autoconf - quite simple
|
||||
if ($ARGV[0] eq "autoconf") {
|
||||
if (`which xentop`) {
|
||||
|
@ -101,7 +111,7 @@ if ($ARGV[0] eq "autoconf") {
|
|||
|
||||
sub trim_label {
|
||||
my ($type, $label) = @_; my $data_characters;
|
||||
my ($graph_width, $graph_border_width, $padding_characters, $pixels_per_character) = (400,97,10,6);
|
||||
my ($graph_width, $graph_border_width, $padding_characters, $pixels_per_character) = (497,3,5,6);
|
||||
if ($type eq 'pos') {$data_characters = 32;} elsif ($type eq 'neg') {$data_characters = 64;} else {return $label;}
|
||||
|
||||
my $available_characters = abs(($graph_width+$graph_border_width)/$pixels_per_character)-$padding_characters-$data_characters;
|
||||
|
@ -117,9 +127,9 @@ sub trim_label {
|
|||
}
|
||||
|
||||
# Global variables
|
||||
my (%domains,$domain,$munindomain,$cpusecs,$memk,$nettxk,$netrxk,$vbdrd,$vbdwr);
|
||||
my (%domains,$domain,@domainlist,$munindomain,$cpusecs,$cpupercent,$memk,$nettxk,$netrxk,$vbdrd,$vbdwr);
|
||||
|
||||
open (XENTOP,"xentop -b -f -i1 |") or die "Could not execute xentop, $!";
|
||||
open (XENTOP,"xentop -b -f -i2 |") or die "Could not execute xentop, $!";
|
||||
|
||||
# Now we build a hash of hashes to store information
|
||||
while (<XENTOP>) {
|
||||
|
@ -129,7 +139,7 @@ while (<XENTOP>) {
|
|||
next if /^NAME/;
|
||||
|
||||
# We define only what we need
|
||||
($domain,undef,$cpusecs,undef,$memk,undef,undef,undef,undef,undef,$nettxk,$netrxk,undef,undef,$vbdrd,$vbdwr,undef,undef,undef) = split(/\s+/);
|
||||
($domain,undef,$cpusecs,$cpupercent,$memk,undef,undef,undef,undef,undef,$nettxk,$netrxk,undef,undef,$vbdrd,$vbdwr,undef,undef,undef) = split(/\s+/);
|
||||
|
||||
# We have to store the sanitised domain name in a separate variable
|
||||
$domains{$domain}{'munindomain'} = clean_fieldname($domain);
|
||||
|
@ -137,6 +147,7 @@ while (<XENTOP>) {
|
|||
# We need the remaining data only for a normal run
|
||||
if ($ARGV[0] eq "") {
|
||||
$domains{$domain}{'cpusecs'} = $cpusecs;
|
||||
$domains{$domain}{'cpupercent'} = $cpupercent;
|
||||
$domains{$domain}{'mem'} = $memk;
|
||||
$domains{$domain}{'nettx'} = $nettxk;
|
||||
$domains{$domain}{'netrx'} = $netrxk;
|
||||
|
@ -145,71 +156,94 @@ while (<XENTOP>) {
|
|||
}
|
||||
}
|
||||
|
||||
@domainlist = sort(keys(%domains));
|
||||
|
||||
#
|
||||
# config - quite simple, too
|
||||
#
|
||||
|
||||
if ($ARGV[0] eq "config") {
|
||||
print "multigraph xen_cpu_time\n";
|
||||
print "graph_title Xen domains CPU time\n";
|
||||
print "graph_args --base 1000 -l 0\n";
|
||||
print "graph_vlabel %\n";
|
||||
print "graph_scale no\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows CPU time for each Xen domain.\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.label ".trim_label('pos',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.type DERIVE\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.cdef $domains{$domain}{'munindomain'}_cpu_time,100,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.min 0\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.draw AREASTACK\n";
|
||||
if ($XEN_SKIP !~ /cput/) {
|
||||
print "multigraph xen_cpu_time\n";
|
||||
print "graph_title Xen domains CPU time\n";
|
||||
print "graph_args --base 1000 -l 0\n";
|
||||
print "graph_vlabel cpu seconds\n";
|
||||
print "graph_scale no\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows CPU time for each Xen domain.\n";
|
||||
for $domain (@domainlist) {
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.label ".trim_label('pos',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.type DERIVE\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.cdef $domains{$domain}{'munindomain'}_cpu_time,100,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.min 0\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.draw AREASTACK\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_mem\n";
|
||||
print "graph_title Xen domains memory usage\n";
|
||||
print "graph_args --base 1024 -l 0\n";
|
||||
print "graph_vlabel bytes\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows memory usage for each Xen domain.\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_mem.label ".trim_label('pos',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_mem.cdef $domains{$domain}{'munindomain'}_mem,1024,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_mem.draw AREASTACK\n";
|
||||
if ($XEN_SKIP !~ /cpup/) {
|
||||
print "\nmultigraph xen_cpu\n";
|
||||
print "graph_title Xen domains CPU utilization\n";
|
||||
print "graph_args --base 1000 -l 0 --upper-limit 100\n";
|
||||
print "graph_vlabel %\n";
|
||||
print "graph_scale no\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows CPU utilization for each Xen domain.\n";
|
||||
for $domain (@domainlist) {
|
||||
print "$domains{$domain}{'munindomain'}_cpu.label ".trim_label('pos',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_cpu.draw AREASTACK\n"
|
||||
}
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_net\n";
|
||||
print "graph_title Xen domains network traffic\n";
|
||||
print "graph_args --base 1000\n";
|
||||
print "graph_vlabel bits per \${graph_period} in (-) / out (+)\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows network traffic for each Xen domain.\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_netrx.label none\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.cdef $domains{$domain}{'munindomain'}_netrx,8192,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.graph no\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.label ".trim_label('neg',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.cdef $domains{$domain}{'munindomain'}_nettx,8192,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.draw AREASTACK\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.negative $domains{$domain}{'munindomain'}_netrx\n";
|
||||
if ($XEN_SKIP !~ /mem/) {
|
||||
print "\nmultigraph xen_mem\n";
|
||||
print "graph_title Xen domains memory usage\n";
|
||||
print "graph_args --base 1024 -l 0\n";
|
||||
print "graph_vlabel bytes\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows memory usage for each Xen domain.\n";
|
||||
for $domain (@domainlist) {
|
||||
print "$domains{$domain}{'munindomain'}_mem.label ".trim_label('pos',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_mem.cdef $domains{$domain}{'munindomain'}_mem,1024,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_mem.draw AREASTACK\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_disk\n";
|
||||
print "graph_title Xen domains disk IOs\n";
|
||||
print "graph_args --base 1000\n";
|
||||
print "graph_vlabel IOs per \${graph_period} read (-) / write (+)\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows disk IOs for each Xen domain.\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.label none\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.graph no\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.label ".trim_label('neg',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.draw AREASTACK\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.negative $domains{$domain}{'munindomain'}_vbdrd\n";
|
||||
if ($XEN_SKIP !~ /net/) {
|
||||
print "\nmultigraph xen_net\n";
|
||||
print "graph_title Xen domains network traffic\n";
|
||||
print "graph_args --base 1000\n";
|
||||
print "graph_vlabel bits per \${graph_period} in (-) / out (+)\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows network traffic for each Xen domain.\n";
|
||||
for $domain (@domainlist) {
|
||||
print "$domains{$domain}{'munindomain'}_netrx.label none\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.cdef $domains{$domain}{'munindomain'}_netrx,8192,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.graph no\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.label ".trim_label('neg',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.cdef $domains{$domain}{'munindomain'}_nettx,8192,*\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.draw AREASTACK\n";
|
||||
print "$domains{$domain}{'munindomain'}_nettx.negative $domains{$domain}{'munindomain'}_netrx\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($XEN_SKIP !~ /disk/) {
|
||||
print "\nmultigraph xen_disk\n";
|
||||
print "graph_title Xen domains disk IOs\n";
|
||||
print "graph_args --base 1000\n";
|
||||
print "graph_vlabel IOs per \${graph_period} read (-) / write (+)\n";
|
||||
print "graph_category xen\n";
|
||||
print "graph_info This graph shows disk IOs for each Xen domain.\n";
|
||||
for $domain (@domainlist) {
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.label none\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.graph no\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.label ".trim_label('neg',$domain)."\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.type COUNTER\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.draw AREASTACK\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.negative $domains{$domain}{'munindomain'}_vbdrd\n";
|
||||
}
|
||||
}
|
||||
|
||||
exit 0;
|
||||
|
@ -220,24 +254,40 @@ if ($ARGV[0] eq "config") {
|
|||
# Normal run
|
||||
#
|
||||
|
||||
print "multigraph xen_cpu_time\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.value $domains{$domain}{'cpusecs'}\n";
|
||||
if ($XEN_SKIP !~ /cput/) {
|
||||
print "multigraph xen_cpu_time\n";
|
||||
for $domain (@domainlist) {
|
||||
print "$domains{$domain}{'munindomain'}_cpu_time.value $domains{$domain}{'cpusecs'}\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_mem\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_mem.value $domains{$domain}{'mem'}\n";
|
||||
if ($XEN_SKIP !~ /cpup/) {
|
||||
print "\nmultigraph xen_cpu\n";
|
||||
for $domain (@domainlist) {
|
||||
print "$domains{$domain}{'munindomain'}_cpu.value $domains{$domain}{'cpupercent'}\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_net\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_nettx.value $domains{$domain}{'nettx'}\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.value $domains{$domain}{'netrx'}\n";
|
||||
if ($XEN_SKIP !~ /mem/) {
|
||||
print "\nmultigraph xen_mem\n";
|
||||
for $domain (@domainlist) {
|
||||
print "$domains{$domain}{'munindomain'}_mem.value $domains{$domain}{'mem'}\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "\nmultigraph xen_disk\n";
|
||||
for $domain (sort(keys(%domains))) {
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.value $domains{$domain}{'vbdrd'}\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.value $domains{$domain}{'vbdwr'}\n";
|
||||
if ($XEN_SKIP !~ /net/) {
|
||||
print "\nmultigraph xen_net\n";
|
||||
for $domain (@domainlist) {
|
||||
print "$domains{$domain}{'munindomain'}_nettx.value $domains{$domain}{'nettx'}\n";
|
||||
print "$domains{$domain}{'munindomain'}_netrx.value $domains{$domain}{'netrx'}\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($XEN_SKIP !~ /disk/) {
|
||||
print "\nmultigraph xen_disk\n";
|
||||
for $domain (@domainlist) {
|
||||
print "$domains{$domain}{'munindomain'}_vbdrd.value $domains{$domain}{'vbdrd'}\n";
|
||||
print "$domains{$domain}{'munindomain'}_vbdwr.value $domains{$domain}{'vbdwr'}\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python2
|
||||
#!/usr/bin/python
|
||||
"""
|
||||
Plugin to monitor Wowza streaming servers.
|
||||
|
||||
|
@ -83,14 +83,14 @@ tree.parse(f)
|
|||
f.close()
|
||||
|
||||
vhosts = []
|
||||
for vh in tree.iter("VHost"):
|
||||
for vh in tree.findall("VHost"):
|
||||
if vh.find("Name").text not in vhost_exclude:
|
||||
applications = []
|
||||
for app in vh.iter("Application"):
|
||||
for app in vh.findall("Application"):
|
||||
if app.find("Name").text not in app_exclude:
|
||||
if app.find("Status").text == "loaded":
|
||||
clients = []
|
||||
for client in app.iter("Client"):
|
||||
for client in app.findall("Client"):
|
||||
if client.find("IpAddress").text not in client_exclude:
|
||||
clients.append({"ClientId": client.find("ClientId").text,
|
||||
"FlashVersion": client.find("FlashVersion").text,
|
||||
|
@ -289,7 +289,7 @@ elif plugin_name == "wowza_vhost_uptime":
|
|||
elif plugin_name == "wowza_app_listeners":
|
||||
for vh in vhosts:
|
||||
for app in vh["Applications"]:
|
||||
print (vh["Name"].strip("/").replace(".","_").replace("-","_"),"_",app["Name"].strip("/").replace(".","_").replace("-","_"),".value ",app["TimeRunning"],sep='')
|
||||
print (vh["Name"].strip("/").replace(".","_").replace("-","_"),"_",app["Name"].strip("/").replace(".","_").replace("-","_"),".value ",app["ConnectionsCurrent"],sep='')
|
||||
|
||||
elif plugin_name == "wowza_app_duration":
|
||||
alldurations = {}
|
||||
|
|
117
plugins/xastir/xastir
Executable file
117
plugins/xastir/xastir
Executable file
|
@ -0,0 +1,117 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2012 Robert Kilian <robertkilian@ostechnologies.net>
|
||||
##
|
||||
## This file is part of the Xastir plugin for Munin.
|
||||
##
|
||||
## Xastir-Munin is free software; you can redistribute it and/or
|
||||
## modify it under the terms of the GNU General Public
|
||||
## License as published by the Free Software Foundation;
|
||||
## either version 3 of the License, or (at your option) any
|
||||
## later version.
|
||||
##
|
||||
## Xastir-Munin is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied
|
||||
## warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
## PURPOSE. See the GNU General Public License for more
|
||||
## details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public
|
||||
## License along with Xastir-Munin; see the file COPYING. If not,
|
||||
## see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
## Version 0.1 -- 07.26.12
|
||||
##
|
||||
|
||||
## Be sure to correctly edit the STATION_CALL, XASTIRDIR, and LOGDIR variables
|
||||
##
|
||||
## STATION_CALL: The callsign used by Xastir (include suffix if one is in use)
|
||||
## XASTIRDIR: The directory where Xastir's data, config, etc files are found. Typically ~/.xastir
|
||||
## LOGDIR: Logs are typically stored in ~/.xastir/logs. Ensure that permissions are set appropriately to allow the munin user to read these logs
|
||||
|
||||
# Location of active instance of Xastir
|
||||
XASTIRDIR="/home/USERNAME/.xastir"
|
||||
|
||||
# Grab the station's callsign from Xastir config
|
||||
# this currently does not derive the station call correctly when called by the server, but works using munin-run...
|
||||
#STATION_CALL=`grep ^STATION_CALLSIGN:.* $XASTIRDIR/config/xastir.cnf | awk -F":" '{print $2}'`
|
||||
STATION_CALL=""
|
||||
|
||||
# Location of Xastir's logs (this can be a symlink to where Xastir actually writes the logs)
|
||||
LOGDIR="/var/log/xastir/logs"
|
||||
|
||||
|
||||
case $1 in
|
||||
config)
|
||||
cat <<'EOM'
|
||||
|
||||
graph_title Xastir Packet Stats
|
||||
graph_vlabel Packets
|
||||
graph_category ham_radio
|
||||
graph_scale no
|
||||
graph_printf %.0lf
|
||||
|
||||
igatetonet.label IGate - RF to Net
|
||||
igatetonet.type COUNTER
|
||||
igatetonet.min 0
|
||||
igatetonet.max 500
|
||||
igatetonet.LINE1
|
||||
|
||||
message.label Message RX
|
||||
message.type COUNTER
|
||||
message.min 0
|
||||
message.max 500
|
||||
message.draw LINE1
|
||||
|
||||
messagetx.label Message TX
|
||||
messagetx.type COUNTER
|
||||
messagetx.min 0
|
||||
messagetx.max 500
|
||||
messagetx.draw LINE1
|
||||
|
||||
net.label Net RX
|
||||
net.type COUNTER
|
||||
net.min 0
|
||||
net.max 500
|
||||
net.draw LINE1
|
||||
|
||||
nettx.label Net TX
|
||||
nettx.type COUNTER
|
||||
nettx.min 0
|
||||
nettx.max 500
|
||||
nettx.draw LINE1
|
||||
|
||||
tnc.label TNC RX
|
||||
tnc.type COUNTER
|
||||
tnc.min 0
|
||||
tnc.max 500
|
||||
tnc.draw LINE1
|
||||
|
||||
tnctx.label TNC TX
|
||||
tnctx.type COUNTER
|
||||
tnctx.min 0
|
||||
tnctx.max 500
|
||||
tnctx.draw LINE1
|
||||
|
||||
EOM
|
||||
exit 0;;
|
||||
esac
|
||||
|
||||
# Parse logs for various values
|
||||
IGATETONET=`cat $LOGDIR/igate.log | grep -e '^IGATE RF' | wc -l`
|
||||
MESSAGE=`cat $LOGDIR/message.log | grep -v '^\#' | grep -v ^$STATION_CALL | wc -l`
|
||||
MESSAGETX=`cat $LOGDIR/message.log | grep -v '^\#' | grep ^$STATION_CALL | wc -l`
|
||||
NET=`cat $LOGDIR/net.log | grep -v '^\#' | grep -v ^$STATION_CALL | wc -l`
|
||||
NETTX=`cat $LOGDIR/net.log | grep -v '^\#' | grep ^$STATION_CALL | wc -l`
|
||||
TNC=`cat $LOGDIR/tnc.log | grep -v '^\#' | grep -v ^$STATION_CALL | wc -l`
|
||||
TNCTX=`cat $LOGDIR/tnc.log | grep -v '^\#' | grep ^$STATION_CALL | wc -l`
|
||||
|
||||
# Display values
|
||||
echo "igatetonet.value $IGATETONET"
|
||||
echo "message.value $MESSAGE"
|
||||
echo "messagetx.value $MESSAGETX"
|
||||
echo "net.value $NET"
|
||||
echo "nettx.value $NETTX"
|
||||
echo "tnc.value $TNC"
|
||||
echo "tnctx.value $TNCTX"
|
||||
|
|
@ -109,8 +109,10 @@ else
|
|||
fi
|
||||
|
||||
L2_ACCESSES_TOTAL=`echo "$L2_HITS+$L2_MISSES" | $BC`
|
||||
L2_HIT_RATIO_PERC=`echo "scale=2 ; (100*$L2_HITS/$L2_ACCESSES_TOTAL)" | $BC`
|
||||
L2_MISS_RATIO_PERC=`echo "scale=2 ; (100*$L2_MISSES/$L2_ACCESSES_TOTAL)" | $BC`
|
||||
if [ $L2_ACCESSES_TOTAL -gt 0 ]; then
|
||||
L2_HIT_RATIO_PERC=`echo "scale=2 ; (100*$L2_HITS/$L2_ACCESSES_TOTAL)" | $BC`
|
||||
L2_MISS_RATIO_PERC=`echo "scale=2 ; (100*$L2_MISSES/$L2_ACCESSES_TOTAL)" | $BC`
|
||||
fi
|
||||
|
||||
efficiency() {
|
||||
if [ "$1" = "config" ]; then
|
||||
|
|
285
plugins/zfs/zfs_usage_
Executable file
285
plugins/zfs/zfs_usage_
Executable file
|
@ -0,0 +1,285 @@
|
|||
#!/usr/local/bin/perl
|
||||
# -*- perl
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
zfs_usage_ - Script to monitor zfs pool usage
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
Create one symlink per zpool for exampe zfs_usage_system
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
2012, Claudius Herder
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf suggest
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv2
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Munin::Plugin;
|
||||
need_multigraph();
|
||||
|
||||
my $filesystems;
|
||||
my $zpool;
|
||||
my $zpoolexec="/sbin/zpool";
|
||||
my $zfsexec="/sbin/zfs";
|
||||
|
||||
my $properties = {
|
||||
available => "Read-only property that identifies the amount of disk"
|
||||
." space available to a file system and all its children,"
|
||||
." assuming no other activity in the pool. Because disk"
|
||||
." space is shared within a pool, available space can be"
|
||||
." limited by various factors including physical pool size,"
|
||||
." quotas, reservations, and other datasets within the"
|
||||
." pool.",
|
||||
|
||||
quota => "Limits the amount of disk space a file system and its"
|
||||
." descendents can consume. This property enforces a"
|
||||
." hard limit on the amount of disk space used, including"
|
||||
." all space consumed by descendents, such as file systems"
|
||||
." and snapshots. Setting a quota on a descendent of a file"
|
||||
." system that already has a quota does not override the"
|
||||
." ancestor's quota, but rather imposes an additional"
|
||||
." limit. Quotas cannot be set on volumes, as the volsize"
|
||||
." property acts as an implicit quota.",
|
||||
|
||||
referenced => "Read-only property that identifies the amount of data"
|
||||
." accessible by a dataset, which might or might not be"
|
||||
." shared with other datasets in the pool."
|
||||
." When a snapshot or clone is created, it initially"
|
||||
." references the same amount of disk space as the file"
|
||||
." system or snapshot it was created from, because its"
|
||||
." contents are identical.",
|
||||
|
||||
refquota => "Sets the amount of disk space that a dataset can"
|
||||
." consume. This property enforces a hard limit on the"
|
||||
." amount of space used. This hard limit does not include"
|
||||
." disk space used by descendents, such as snapshots and"
|
||||
." clones.",
|
||||
|
||||
refreservation => "Sets the minimum amount of disk space that is"
|
||||
." guaranteed to a dataset, not including descendents,"
|
||||
." such as snapshots and clones. When the amount of disk"
|
||||
." space used is below this value, the dataset is treated as if"
|
||||
." it were taking up the amount of space specified by"
|
||||
." refreservation. The refreservation reservation is"
|
||||
." accounted for in the parent dataset's disk space used,"
|
||||
." and counts against the parent dataset's quotas and"
|
||||
." reservations."
|
||||
." If refreservation is set, a snapshot is only allowed if"
|
||||
." enough free pool space is available outside of this"
|
||||
." reservation to accommodate the current number of"
|
||||
." referenced bytes in the dataset.",
|
||||
|
||||
reservation => "Sets the minimum amount of disk space guaranteed to"
|
||||
." a file system and its descendents. When the amount of"
|
||||
." disk space used is below this value, the file system is"
|
||||
." treated as if it were using the amount of space specified"
|
||||
." by its reservation. Reservations are accounted for in the"
|
||||
." parent file system's disk space used, and count against"
|
||||
." the parent file system's quotas and reservations.",
|
||||
|
||||
type => "Read-only property that identifies the dataset type as"
|
||||
." filesystem (file system or clone), volume, or"
|
||||
." snapshot.",
|
||||
|
||||
used => "Read-only property that identifies the amount of disk"
|
||||
." space consumed by a dataset and all its descendents.",
|
||||
|
||||
usedbychildren => "Read-only property that identifies the amount of disk"
|
||||
." space that is used by children of this dataset, which"
|
||||
." would be freed if all the dataset's children were"
|
||||
." destroyed. The property abbreviation is usedchild.",
|
||||
|
||||
usedbydataset => "Read-only property that identifies the amount of disk"
|
||||
." space that is used by a dataset itself, which would be"
|
||||
." freed if the dataset was destroyed, after first destroying"
|
||||
." any snapshots and removing any refreservation"
|
||||
." reservations. The property abbreviation is usedds.",
|
||||
|
||||
usedbyrefreservation=> "Read-only property that identifies the amount of disk"
|
||||
." space that is used by a refreservation set on a dataset,"
|
||||
." which would be freed if the refreservation was"
|
||||
." removed.",
|
||||
|
||||
usedbysnapshots => "Read-only property that identifies the amount of disk"
|
||||
." space that is consumed by snapshots of a dataset. In"
|
||||
." particular, it is the amount of disk space that would be"
|
||||
." freed if all of this dataset's snapshots were destroyed."
|
||||
." Note that this value is not simply the sum of the"
|
||||
." snapshots' used properties, because space can be"
|
||||
." shared by multiple snapshots.",
|
||||
volsize => "For volumes, specifies the logical size of the volume.",
|
||||
};
|
||||
|
||||
my @order = (
|
||||
"usedbydataset",
|
||||
"usedbysnapshots",
|
||||
"usedbyrefreservation",
|
||||
"usedbychildren",
|
||||
"available",
|
||||
"quota",
|
||||
"refquota",
|
||||
"referenced",
|
||||
"reservation",
|
||||
"refreservation",
|
||||
"used",
|
||||
"volsize",
|
||||
);
|
||||
|
||||
sub do_collect {
|
||||
my $fslist=(`$zfsexec list -H -r -o name $zpool`);
|
||||
|
||||
my @params = join(',',( keys %{$properties} ));
|
||||
|
||||
my $fsget="$zfsexec get -H -p @params";
|
||||
|
||||
foreach my $fsname (split(/\n/,$fslist)) {
|
||||
foreach my $line (split(/\n/, `$fsget $fsname` )) {
|
||||
my ($name, $key, $value, undef ) = (split(/\t/,$line));
|
||||
($name =~ s/\//_/g);
|
||||
$filesystems->{$name}->{$key}=$value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub do_config_fs {
|
||||
my ($fs) = @_;
|
||||
my $fs_slash = ($fs);
|
||||
($fs_slash =~ s/_/\//g);
|
||||
|
||||
if ( $fs ne $zpool ) {
|
||||
print "multigraph zfs_usage_$zpool.$fs\n";
|
||||
print "graph_title ZFS usage for $filesystems->{$fs}->{type} $fs_slash\n";
|
||||
print "graph_info This graph shows used bytes of $filesystems->{$fs}->{type} $fs_slash\n";
|
||||
} else {
|
||||
print "multigraph zfs_usage_$zpool\n";
|
||||
print "graph_title ZFS usage for zpool $zpool\n";
|
||||
print "graph_info This graph shows used bytes of zpool $zpool\n";
|
||||
}
|
||||
print "graph_args --base 1024 --lower-limit 0 --rigid\n";
|
||||
print "graph_vlabel bytes \n";
|
||||
print "graph_category zfs\n";
|
||||
print "graph_order @order\n";
|
||||
|
||||
foreach my $key ( keys %{$filesystems->{$fs}}) {
|
||||
if ( $key ne "type" ) {
|
||||
if ( $filesystems->{$fs}->{type} eq "volume" && $key =~ /quota/ ) {
|
||||
}
|
||||
elsif ($filesystems->{$fs}->{type} eq "filesystem" && $key eq "volsize") {
|
||||
}
|
||||
else {
|
||||
print "$key.label $key\n";
|
||||
print "$key.min 0\n";
|
||||
print "$key.type GAUGE\n";
|
||||
print "$key.info $properties->{$key}\n";
|
||||
if ( $key =~ /quota|referenced|^(ref)*reservation|^used$|volsize/ ) {
|
||||
print "$key.draw LINE3\n";
|
||||
}
|
||||
else {
|
||||
print "$key.draw AREASTACK\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub do_fetch_fs {
|
||||
my ($fs) = @_;
|
||||
|
||||
if ( $fs ne $zpool ) {
|
||||
print "multigraph zfs_usage_$zpool.$fs\n";
|
||||
} else {
|
||||
print "multigraph zfs_usage_$zpool\n";
|
||||
}
|
||||
|
||||
foreach my $key ( keys %{$filesystems->{$fs}}) {
|
||||
if ( $key ne "type" ) {
|
||||
if ( $filesystems->{$fs}->{type} eq "volume" && $key =~ /quota/ ) {
|
||||
}
|
||||
elsif ($filesystems->{$fs}->{type} eq "filesystem" && $key eq "volsize") {
|
||||
}
|
||||
else {
|
||||
print "$key.value $filesystems->{$fs}->{$key}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub do_config {
|
||||
foreach my $fs ( sort keys %{$filesystems}) {
|
||||
do_config_fs($fs);
|
||||
}
|
||||
}
|
||||
|
||||
sub do_autoconf {
|
||||
if (`which $zpoolexec 2>/dev/null` =~ m{^/}) {
|
||||
print "yes\n";
|
||||
} else {
|
||||
print "no ($zpoolexec could not be found)\n";
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
|
||||
sub do_suggest {
|
||||
my $poollist=(`zpool list -H -o name`);
|
||||
print "$poollist";
|
||||
}
|
||||
|
||||
sub do_fetch {
|
||||
foreach my $fs ( sort keys %{$filesystems}) {
|
||||
do_fetch_fs($fs);
|
||||
}
|
||||
}
|
||||
|
||||
sub do_setpool {
|
||||
if ( $0 =~ /zfs_usage_$/) {
|
||||
die ("Can't run without a symlinked name\n")
|
||||
}
|
||||
elsif ($0 =~ /zfs_usage_(.+)*$/) {
|
||||
$zpool = $1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($ARGV[0]) {
|
||||
if ($ARGV[0] eq "config") {
|
||||
do_setpool();
|
||||
do_collect();
|
||||
do_config();
|
||||
exit 0;
|
||||
}
|
||||
elsif ($ARGV[0] eq "autoconf") {
|
||||
do_autoconf();
|
||||
exit 0;
|
||||
}
|
||||
elsif ($ARGV[0] eq "suggest") {
|
||||
do_suggest();
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
do_setpool();
|
||||
do_collect();
|
||||
do_fetch();
|
||||
}
|
||||
|
||||
exit 0;
|
||||
|
||||
__END__
|
Loading…
Add table
Add a link
Reference in a new issue