1
0
Fork 0
mirror of https://github.com/munin-monitoring/contrib.git synced 2025-07-25 10:28:36 +00:00

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Samuel Smith 2016-08-08 21:52:51 -05:00
commit 56aa139205
63 changed files with 3233 additions and 380 deletions

42
plugins/apache/apache_average_time_last_n_requests Executable file → Normal file
View file

@ -1,6 +1,6 @@
#!/usr/bin/perl -w
# $Id$
# Author: Nicolas Mendoza <nicolasm@opera.com> - 2008-06-18
# Raphaël Droz <raphael.droz@gmail.com> - 2016-01-08
#
# Monitors the average time requests matching a custom regexp takes
# For instance monitor time execution of files in http://example.com/foo/bar,
@ -16,12 +16,37 @@
# For instance:
# LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %T %v"
# Check http://httpd.apache.org/docs/2.2/mod/mod_log_config.html#formats for more info
#
# Configurable variables
# fieldno - Override the default field number
# linecount - How many last request to consider
# Multiples instances for specific log files could be created by suffixing a configuration group.
# Eg: ln -s apache_average_time_last_n_requests apache_average_time_last_n_requests_vhost1
# Then:
# [apache_average_time_last_n_requests]
# logfile_vhost1 /var/log/apache/vhost1.log
#
#%# family=auto
use strict;
my $LAST_N_REQUESTS = 100000; # calculate based on this amount of requests
my $ACCESS_LOG_PATTERN = '/var/log/apache2/access.log.*'; # log pattern, if many it will take the last one.
my $TIME_FIELD_INDEX = -2; # second last field
$0 =~ /apache_average_time_last_n_requests_(.+)*$/;
my $name = $1;
my $LAST_N_REQUESTS = exists $ENV{'linecount'} ? $ENV{'linecount'} : 100000; # calculate based on this amount of requests
my $TIME_FIELD_INDEX = exists $ENV{'fieldno'} ? $ENV{'fieldno'} : -2; # second last field
my $ACCESS_LOG_PATTERN;
# log pattern, if globbing is used, it will take the last one.
if (! $name) {
$ACCESS_LOG_PATTERN = exists $ENV{'logfile'} ? $ENV{'logfile'} : '/var/log/apache2/access.log.*';
}
elsif (exists $ENV{'logfile_' . $name}) {
$ACCESS_LOG_PATTERN = $ENV{'logfile_' . $name};
}
else {
$ACCESS_LOG_PATTERN = '/var/log/apache2/access.log.*';
}
my $config =<< "CONFIG"
graph_title Apache average seconds last $LAST_N_REQUESTS requests
@ -61,12 +86,12 @@ my $types = {
my ($fields) = @_;
my $script;
($script = $fields->[6]) =~ s/\?.*\z //mx;
return $script =~ m{ \.(png|jpe?g|jpg|gif|tiff|ilbm|tga) \z }mx;
return $script =~ m{ \.(png|jpe?g|gif|tiff|ilbm|tga) \z }mx;
},
},
};
if (defined(@ARGV) && ($ARGV[0] eq 'config')) {
if (@ARGV && $ARGV[0] eq 'config') {
print $config;
@ -84,16 +109,21 @@ chomp $config_file;
my @lines = `tail -n $LAST_N_REQUESTS "$config_file"`;
FOO: {
foreach my $line (@lines) {
foreach my $type (keys %{$types}) {
my @fields = split /\s+/, $line;
if ($types->{$type}->{'matches'}(\@fields)) {
if ($fields[$TIME_FIELD_INDEX] !~ m/^[0-9]+$/) {
last FOO;
}
$types->{$type}->{'sum'} += $fields[$TIME_FIELD_INDEX];
$types->{$type}->{'lines'}++;
}
}
}
}
foreach my $type (keys %{$types}) {
my $value = $types->{$type}->{'lines'} ? $types->{$type}->{'sum'} / $types->{$type}->{'lines'} : 'U';
printf "%s.value %s\n", ($type, $value);

View file

@ -0,0 +1,123 @@
#!/bin/bash
: << =cut
=head1 NAME
Munin plugin to monitor apache mod_cache_disk usage.
=head1 CONFIGURATION
[apache_cache_disk_count]
user www-data
env.cache_path /var/cache/apache2/mod_cache_disk
env.strings css js
env.label_cs CSS
env.colour_css FFFF00
env.label_js JS
env.colour_js FF0000
=head1 AUTHOR
Raphaël Droz <raphael.droz+floss@gmail.com>
=head1 LICENSE
GPLv2
=head1 MAGICK MARKERS
#%# family=auto
#%# capabilities=autoconf
=cut
. $MUNIN_LIBDIR/plugins/plugin.sh
my_cache_path="${cache_path:-/var/cache/apache2/mod_cache_disk}"
declare -a fieldnames labels colours
getenvdata() {
let during_autoconf=0
[[ $1 == -v ]] && during_autoconf=1
arg=( "${strings:-}" )
for i in ${arg[*]}; do
if [[ ! $i =~ ^[a-zA-Z0-9]+$ ]]; then
(( $during_autoconf )) && echo "no ($i isn't a valid fixed-string)"
ok=0
continue
fi
label=label_$i
if [[ -z "${!label}" ]]; then
(( $during_autoconf )) && echo "no ($i isn't given a label)"
ok=0
continue
fi
colour=colour_$i
if [[ -z "${!colour}" ]]; then
(( $during_autoconf )) && echo "no ($i isn't given a colour)"
ok=0
continue
fi
fieldnames+=($i)
labels+=("${!label}")
colours+=("${!colour}")
done
}
if [[ $1 == autoconf ]]; then
let ok=1
[[ -z $strings ]] && echo "no strings to monitor defined" && ok=0
! type -P htcacheclean &>/dev/null && echo "can't find htcacheclean" && ok=0
! test -d "$my_cache_path" && echo "cache_path \"$cache_path\" is not readable" && ok=0
getenvdata -v
(( ${#fieldnames[*]} == 0 )) && echo "no (no valid strings)" && ok=0
(( $ok == 1 )) && echo yes
exit 0
fi
getenvdata
if [[ $1 == config ]]; then
cat <<EOF
graph_title Apache mod_cache_disk usage
graph_title Number of entries in mod_cache_disk Apache cache
graph_args --base 1000 -l 0
graph_vlabel Y
graph_category Apache
graph_order ${fieldnames[*]} total
total.draw LINE1
total.label all
total.type GAUGE
total.min 0
EOF
let i=0
while (( $i < ${#fieldnames[*]} )); do
string=${fieldnames[$i]}
label="${labels[$i]}"
colour="${colours[$i]}"
cat <<EOF
${string}.draw AREASTACK
${string}.label ${label}
${string}.colour ${colour}
EOF
((i++))
done
exit 0
fi
total=$(htcacheclean -a -p "$my_cache_path"|wc -l)
asset_count=$(htcacheclean -a -p "$my_cache_path"|egrep -o "\.($(echo ${fieldnames[*]}|tr ' ' '|'))"|sort|uniq --count)
printf "total.value %d\n" "$total"
for i in ${fieldnames[*]}; do
c=$(echo "$asset_count"|sed -rn "/$i/s;^\s*([0-9]+).*;\1;p")
[[ -z $c ]] && c=U
printf "%s.value %s\n" "$i" "$c"
done
exit 0

196
plugins/apt/acng Executable file
View file

@ -0,0 +1,196 @@
#!/usr/bin/perl
=head1 NAME
acng - Graph activity for Apt-Cacher NG, request count and bytes
=head1 APPLICABLE SYSTEMS
Systems with "Apt-Cacher NG" installed and running.
=head1 DESCRIPTION
This plugin will add graphs for "bytes in and out" and "requests in
and out" for systems with "Apt-Cacher NG" installed.
=head1 CONFIGURATION
The plugin must have permission to read the log of Apt-Cacher NG. (On
Debian 8, this file is world readable by default).
The path to the logfile can be set with the "logfile" environment
variable.
=head2 DEFAULT CONFIGURATION
[acng]
env.logfile /var/log/apt-cacher-ng/apt-cacher.log
=head1 USAGE
Link this plugin to /etc/munin/plugins/ and restart the munin-node.
=head1 MAGIC MARKERS
#%# family=contrib
#%# capabilities=autoconf
=head1 AUTHOR
Stig Sandbeck Mathisen
=head1 LICENSE
GPLv3
=cut
use strict;
use warnings;
use Munin::Plugin;
use Storable qw(nfreeze thaw);
use MIME::Base64;
my $logfile = $ENV{'logfile'} ||= '/var/log/apt-cacher-ng/apt-cacher.log';
need_multigraph;
# Read or initialize state used by the log tailer, and the plugin.
sub read_state {
my ($pos, $statsin) = restore_state;
my $stats = thaw(decode_base64 $statsin) if $statsin;
$pos = 0 unless defined $pos;
$stats = {} unless defined $stats;
return ($pos, $stats);
}
# Write state.
#
# "pos" is logfile position, and "stats" is a data structure with
# counters used by the plugin.
#
# Note: Munin::Plugin::save_state has limited functionality, so the
# data structure is serialized and converted to plain text.
sub write_state {
my ($pos, $stats) = @_;
my $statsout = encode_base64 nfreeze($stats);
save_state($pos, $statsout);
}
sub parse_logfile {
my $logfile = shift;
my ($pos, $stats) = read_state;
my @keys = ( 'time', 'direction', 'size', 'client', 'file' );
# Open log
my ( $fh, $reset ) = tail_open( $logfile, $pos );
die "Unable to open logfile\n" unless ($fh);
while (<$fh>) {
chomp;
my @values = split( /\|/, $_ );
my %logentry;
@logentry{@keys} = @values;
$stats->{'bytes'}{ $logentry{'direction'} } += $logentry{'size'};
$stats->{'requests'}{ $logentry{'direction'} }++;
}
# Close log
$pos = tail_close($fh);
write_state($pos, $stats);
return $stats;
}
sub print_autoconf{
my $logfile = shift;
if ( open(my $fh, '<', $logfile) ) {
print "yes\n";
}
else {
printf "no (could not open %s)\n", $logfile;
}
}
sub print_config{
my $stats = shift;
print << 'EOC';
multigraph acng_bytes
graph_title Apt-Cacher NG bytes
graph_order origin client
graph_vlabel bytes per ${graph_period}
graph_info Bytes transferred between origin, apt-cacher-ng and clients
origin.info bytes transferred between origin and apt-cacher-ng
origin.label origin
origin.type DERIVE
origin.min 0
client.info bytes transferred between apt-cacher-ng and clients
client.label client
client.type DERIVE
client.min 0
EOC
print << "EOV" if $ENV{'MUNIN_CAP_DIRTYCONFIG'};
origin.value $stats->{bytes}{I}
client.value $stats->{bytes}{O}
EOV
print << 'EOC';
multigraph acng_requests
graph_title Apt-Cacher NG requests
graph_order origin client
graph_vlabel requests per ${graph_period}
graph_info Requests from clients to apt-cacher-ng, and from apt-cacher-ng to origin
origin.info requests from apt-cacher-ng to origin
origin.label origin
origin.type DERIVE
origin.min 0
client.info requests from clients to apt-cacher-ng
client.label client
client.type DERIVE
client.min 0
EOC
print << "EOV" if $ENV{'MUNIN_CAP_DIRTYCONFIG'};
origin.value $stats->{requests}{I}
client.value $stats->{requests}{O}
EOV
}
sub print_values{
my $stats = shift;
print << "EOV";
multigraph acng_bytes
origin.value $stats->{bytes}{I}
client.value $stats->{bytes}{O}
multigraph acng_requests
origin.value $stats->{requests}{I}
client.value $stats->{requests}{O}
EOV
}
if ($ARGV[0] and $ARGV[0] eq 'autoconf') {
print_autoconf($logfile);
}
elsif ($ARGV[0] and $ARGV[0] eq 'config') {
my $stats = parse_logfile($logfile);
print_config($stats);
}
else {
my $stats = parse_logfile($logfile);
print_values($stats);
}

View file

@ -29,9 +29,13 @@ check out this git repository from
aptitude install python-apt
git clone git://github.com/munin-monitoring/contrib.git
cd contrib/plugins/apt/deb_packages
sudo cp deb_packages.py /etc/munin/plugins
sudo cp deb_packages.py /etc/munin/plugins/deb_packages
sudo cp deb_packages.munin-conf /etc/munin/plugin-conf.d/deb_packages
Verify the installation by
sudo munin-run deb_packages
### Configuration
If you copied deb_packages.munin-conf to plugin-conf.d you have a starting point.
A typical configuration looks like this

View file

@ -4,6 +4,10 @@
# [backuppc]
# user backuppc
# env.pcdir /var/lib/BackupPC/pc
# env.full_warning 10 # warn if FULL backup older than N days
# env.full_critical 20 # critical if FULL backup older than N days
# env.incr_warning 1 # warn if INCR backup older than N days
# env.incr_critical 3 # critical if INCR backup older than N days
#
#%# family=backuppc
#%# capabilities=autoconf
@ -42,6 +46,18 @@ if [ "$1" = "config" ]; then
do
echo "$(clean_fieldname ${h})_full.label $(clean_fieldname ${h}) Full"
echo "$(clean_fieldname ${h})_incr.label $(clean_fieldname ${h}) Incr"
if [ -n "$full_warning" ]; then
echo "$(clean_fieldname ${h})_full.warning $full_warning"
fi
if [ -n "$incr_warning" ]; then
echo "$(clean_fieldname ${h})_incr.warning $incr_warning"
fi
if [ -n "$full_critical" ]; then
echo "$(clean_fieldname ${h})_full.critical $full_critical"
fi
if [ -n "$incr_critical" ]; then
echo "$(clean_fieldname ${h})_incr.critical $incr_critical"
fi
done
exit 0
@ -150,3 +166,5 @@ one per row. The columns are:
mangle
Set if this backup has mangled file names and attributes. Always true
for backups in v1.4.0 and above. False for all backups prior to v1.4.0.
__END__

274
plugins/balanceng/bng Executable file
View file

@ -0,0 +1,274 @@
#!/usr/bin/perl
# munin plugin for BalanceNG
# https://www.inlab.de/load-balancer/index.html
#
# (w) 2015 by Rhonda D'Vine <rhonda@strg.at>
# (c) 2015 by strg.at GmbH <http://strg.at/>
#
# 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.
#
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
use warnings;
use strict;
use Munin::Plugin;
my $host;
my %servers;
my %targets;
# we support autoconf
#%# family=auto
#%# capabilities=autoconf suggest
# Check for multigraph capabilities
need_multigraph();
# Handle munin 'autoconf' command
do_autoconf() if ( $ARGV[0] && $ARGV[0] eq 'autoconf' );
# Fetch data values
do_fetch_values();
# Handle munin 'config' command
# This can only be done after getting the data
if ( defined $ARGV[0] && $ARGV[0] eq 'config' ) {
do_config();
}
generate_output();
exit 0;
sub do_autoconf { # {{{ check if we can offer autoconf
print (-x '/sbin/bng' ? "yes\n" : "no\n");
exit 0;
} # }}}
sub do_fetch_values { # {{{ fetch all the names and values needed
## MIBs from https://www.inlab.de/load-balancer/BalanceNG-V3-Manual.pdf
# node name
open READ, "/sbin/bng -g .1.3.6.1.4.1.2771.1.5 |" || die "$0: can't fork bng: $!\n";
<READ>;
<READ>;
$host = <READ>;
chomp $host;
close READ;
my $next;
# server names
$next = '.1.3.6.1.4.1.2771.1.60.3';
while (open READ, "/sbin/bng -n $next |") {
$next = <READ>;
chomp $next;
if ($next !~ /^\.1\.3\.6\.1\.4\.1\.2771\.1\.60\.3/) {
close READ;
last;
}
<READ>;
my $name = <READ>;
chomp $name;
push @{$servers{name}}, clean_fieldname($name);
close READ;
}
# server sent bytes
$next = '.1.3.6.1.4.1.2771.1.60.15';
while (open READ, "/sbin/bng -n $next |") {
$next = <READ>;
chomp $next;
if ($next !~ /^\.1\.3\.6\.1\.4\.1\.2771\.1\.60\.15/) {
close READ;
last;
}
<READ>;
my $name = <READ>;
chomp $name;
push @{$servers{sent}}, $name;
$servers{senttotal} += $name;
close READ;
}
# server recv bytes
$next = '.1.3.6.1.4.1.2771.1.60.17';
while (open READ, "/sbin/bng -n $next |") {
$next = <READ>;
chomp $next;
if ($next !~ /^\.1\.3\.6\.1\.4\.1\.2771\.1\.60\.17/) {
close READ;
last;
}
<READ>;
my $name = <READ>;
chomp $name;
push @{$servers{recv}}, $name;
$servers{recvtotal} += $name;
close READ;
}
# target names
$next = '.1.3.6.1.4.1.2771.1.70.3';
while (open READ, "/sbin/bng -n $next |") {
$next = <READ>;
chomp $next;
if ($next !~ /^\.1\.3\.6\.1\.4\.1\.2771\.1\.70\.3/) {
close READ;
last;
}
<READ>;
my $name = <READ>;
chomp $name;
push @{$targets{name}}, clean_fieldname($name);
close READ;
}
# target sent bytes
$next = '.1.3.6.1.4.1.2771.1.70.27';
while (open READ, "/sbin/bng -n $next |") {
$next = <READ>;
chomp $next;
if ($next !~ /^\.1\.3\.6\.1\.4\.1\.2771\.1\.70\.27/) {
close READ;
last;
}
<READ>;
my $name = <READ>;
chomp $name;
push @{$targets{sent}}, $name;
$targets{senttotal} += $name;
close READ;
}
# target recv bytes
$next = '.1.3.6.1.4.1.2771.1.70.29';
while (open READ, "/sbin/bng -n $next |") {
$next = <READ>;
chomp $next;
if ($next !~ /^\.1\.3\.6\.1\.4\.1\.2771\.1\.70\.29/) {
close READ;
last;
}
<READ>;
my $name = <READ>;
chomp $name;
push @{$targets{recv}}, $name;
$targets{recvtotal} += $name;
close READ;
}
} # }}}
sub do_config { # {{{ write out the configuration
print <<"EOF";
multigraph bng
graph_title Bng Throughput
graph_order sent recv
graph_args --base 1000 -l 0
graph_vlabel Packets/\${graph_period}
graph_category network
graph_info this graph shows the outbound traffic for $host
sent.label Sent
sent.draw AREA
sent.type DERIVE
sent.min 0
recv.label Received
recv.draw AREA
recv.type DERIVE
recv.min 0
EOF
foreach my $interface (@{$servers{name}}, @{$targets{name}}) {
print <<"EOF";
multigraph bng.${interface}
graph_title Interface $interface traffic
graph_order sent recv
graph_args --base 1000 -l 0
graph_vlabel Packets/\${graph_period}
graph_category network
graph_info this graph shows the total traffic for ${interface}
sent.label ${interface}_Sent
sent.draw AREA
sent.type DERIVE
sent.min 0
recv.label ${interface}_Received
recv.draw AREA
recv.type DERIVE
recv.min 0
EOF
}
exit 0;
} # }}}
sub generate_output { # {{{ write out the data
print <<"EOF";
multigraph bng
sent.value $servers{senttotal}
recv.value $servers{recvtotal}
EOF
my $i;
$i = 0;
foreach my $interface (@{$servers{name}}) {
print <<"EOF";
multigraph bng.${interface}
sent.value $servers{sent}[$i]
recv.value $servers{recv}[$i]
EOF
$i++;
}
$i = 0;
foreach my $interface (@{$targets{name}}) {
print <<"EOF";
multigraph bng.${interface}
sent.value $targets{sent}[$i]
recv.value $targets{recv}[$i]
EOF
$i++;
}
} # }}}
# vim:fdm=marker:

View file

@ -66,11 +66,14 @@ GPLv2
=cut
# IMAP Configuration Directory
CONFIGDIR=$(awk -F : '/^configdirectory:/ { gsub(/ /, "", $2); print $2 }' /etc/imapd.conf 2> /dev/null)
PROCDIR="${CONFIGDIR}/proc"
PROCDIR=$(awk -F : '/^proc_path:/ { gsub(/ /, "", $2); print $2 }' /etc/imapd.conf 2> /dev/null)
if [ "x${PROCDIR}x" = "xx" ]; then
CONFIGDIR=$(awk -F : '/^configdirectory:/ { gsub(/ /, "", $2); print $2 }' /etc/imapd.conf 2> /dev/null)
PROCDIR="${CONFIGDIR}/proc"
fi
if [ "$1" = "autoconf" ]; then
if [ "x${CONFIGDIR}x" != "xx" ] && [ -d ${PROCDIR} ]; then
if [ "x${PROCDIR}x" != "xx" ] && [ -d ${PROCDIR} ]; then
echo yes
else
echo "no (no cyrus-imapd procdir found)"
@ -79,7 +82,7 @@ if [ "$1" = "autoconf" ]; then
fi
# Check if we actually got some sensible data
if [ "x${CONFIGDIR}x" = "xx" ]; then
if [ "x${PROCDIR}x" = "xx" ]; then
exit 1
fi

View file

@ -46,6 +46,7 @@ my %runtime_stats = (
"vnodes" => ["vn_active","vn_alloc","vn_get","vn_hold","vn_rele","vn_reclaim","vn_remove","vn_free"],
"buf" => ["xb_get","xb_create","xb_get_locked","xb_get_locked_waited","xb_busy_locked","xb_miss_locked","xb_page_retries","xb_page_found","xb_get_read"],
"ibt2" => ["xs_ibt_2_lookup","xs_ibt_2_compare","xs_ibt_2_insrec","xs_ibt_2_delrec","xs_ibt_2_newroot","xs_ibt_2_killroot","xs_ibt_2_increment","xs_ibt_2_decrement","xs_ibt_2_lshift","xs_ibt_2_rshift","xs_ibt_2_split","xs_ibt_2_join","xs_ibt_2_alloc","xs_ibt_2_free","xs_ibt_2_moves"],
"fibt2" => ["xs_fibt_2_lookup","xs_fibt_2_compare","xs_fibt_2_insrec","xs_fibt_2_delrec","xs_fibt_2_newroot","xs_fibt_2_killroot","xs_fibt_2_increment","xs_fibt_2_decrement","xs_fibt_2_lshift","xs_fibt_2_rshift","xs_fibt_2_split","xs_fibt_2_join","xs_fibt_2_alloc","xs_fibt_2_free","xs_fibt_2_moves"],
"bmbt2" => ["xs_bmbt_2_lookup","xs_bmbt_2_compare","xs_bmbt_2_insrec","xs_bmbt_2_delrec","xs_bmbt_2_newroot","xs_bmbt_2_killroot","xs_bmbt_2_increment","xs_bmbt_2_decrement","xs_bmbt_2_lshift","xs_bmbt_2_rshift","xs_bmbt_2_split","xs_bmbt_2_join","xs_bmbt_2_alloc","xs_bmbt_2_free","xs_bmbt_2_moves"],
"abtc2" => ["xs_abtc_2_lookup","xs_abtc_2_compare","xs_abtc_2_insrec","xs_abtc_2_delrec","xs_abtc_2_newroot","xs_abtc_2_killroot","xs_abtc_2_increment","xs_abtc_2_decrement","xs_abtc_2_lshift","xs_abtc_2_rshift","xs_abtc_2_split","xs_abtc_2_join","xs_abtc_2_alloc","xs_abtc_2_free","xs_abtc_2_moves"],
"abtb2" => ["xs_abtb_2_lookup","xs_abtb_2_compare","xs_abtb_2_insrec","xs_abtb_2_delrec","xs_abtb_2_newroot","xs_abtb_2_killroot","xs_abtb_2_increment","xs_abtb_2_decrement","xs_abtb_2_lshift","xs_abtb_2_rshift","xs_abtb_2_split","xs_abtb_2_join","xs_abtb_2_alloc","xs_abtb_2_free","xs_abtb_2_moves"],

120
plugins/docker/docker_cpu Executable file
View file

@ -0,0 +1,120 @@
#!/usr/bin/perl -w
# -*- perl -*-
=head1 NAME
docker_cpu - Munin plugin to monitor docker container CPU usage.
=head1 APPLICABLE SYSTEMS
Should work on any Linux system that has docker support.
=head1 CONFIGURATION
Root privilege required to execute docker command.
1. Create a new file named "docker" inside the folder /etc/munin/plugin-conf.d/
2. Docker file content:
[docker_cpu]
user root
=head1 MAGIC MARKERS
#%# family=auto
#%# capabilities=autoconf
=head1 VERSION
v.0.1
=head1 AUTHOR
Copyright (C) 2015 Samuel Cantero.
Email: scanterog at gmail dot com
=head1 LICENSE
GPLv3
=cut
my $docker=`which docker`;
if ( defined $ARGV[0] and $ARGV[0] eq "autoconf" ) {
if ($docker) {
print "yes\n";
exit 0;
}
else{
print "no (Docker has not been found)\n";
exit 0;
}
}
$docker =~ s/\s+$//;
my @containers = split "\n" , `$docker ps --no-trunc=true`;
my $result;
for my $i (1 .. $#containers)
{
my @fields = split / +/, $containers[$i];
my $id = $fields[0];
my $name = $fields[$#fields];
# manage container name containing arithmetic operators and dots. E.g, my-container.
$name =~ s/[-\+*\/\.]/_/g;
# truncate container name with "," character.
$name =~ s/,.*//g;
if (open(my $file, '<', "/sys/fs/cgroup/cpuacct/docker/$id/cpuacct.usage"))
{
my $total_cpu_ns = <$file>;
$total_cpu_ns =~ s/\s+$//;
close $file;
if (open($file, '<', "/sys/fs/cgroup/cpuacct/docker/$id/cpuacct.usage_percpu"))
{
my @ncpu = split / /, <$file>;
close $file;
push @result, {'name'=>$name, 'total_cpu_ns'=>$total_cpu_ns, 'ncpu'=>$#ncpu};
}
}
}
if (defined $ARGV[0] and $ARGV[0] eq "config")
{
my $nanoSecondsInSecond=1000000000;
my $graphlimit = $result[0]{'ncpu'};
foreach(@result){
if ($$_{'ncpu'} > $graphlimit){
$graphlimit = $$_{'ncpu'};
}
}
$graphlimit = $graphlimit * 100;
print "graph_title Docker container CPU usage\n";
print "graph_args --base 1000 -r --lower-limit 0 --upper-limit $graphlimit\n";
print "graph_vlabel %\n";
print "graph_scale no\n";
print "graph_period second\n";
print "graph_category Docker\n";
print "graph_info This graph shows docker container CPU usage.\n";
foreach(@result)
{
print "$$_{'name'}.label $$_{'name'}\n";
print "$$_{'name'}.draw LINE2\n";
print "$$_{'name'}.min 0\n";
print "$$_{'name'}.type DERIVE\n";
print "$$_{'name'}.cdef $$_{'name'},$nanoSecondsInSecond,/\n";
}
exit 0;
}
# Note: Counters/derive need to report integer values.
foreach(@result)
{
$tcpu = ($$_{'total_cpu_ns'}*100); #to percentage
print "$$_{'name'}.value $tcpu\n";
}
# vim:syntax=perl

98
plugins/docker/docker_memory Executable file
View file

@ -0,0 +1,98 @@
#!/usr/bin/perl -w
# -*- perl -*-
=head1 NAME
docker_memory - Munin plugin to monitor docker container memory usage.
=head1 APPLICABLE SYSTEMS
Should work on any Linux system that has docker support.
=head1 CONFIGURATION
Root privilege required to execute docker command.
1. Create a new file named "docker" inside the folder /etc/munin/plugin-conf.d/
2. Docker file content:
[docker_memory]
user root
=head1 MAGIC MARKERS
#%# family=auto
#%# capabilities=autoconf
=head1 VERSION
v.0.1
=head1 AUTHOR
Copyright (C) 2015 Samuel Cantero.
Email: scanterog at gmail dot com
=head1 LICENSE
GPLv3
=cut
my $docker=`which docker`;
if ( defined $ARGV[0] and $ARGV[0] eq "autoconf" ) {
if ($docker) {
print "yes\n";
exit 0;
}
else{
print "no (Docker has not been found)\n";
exit 0;
}
}
$docker =~ s/\s+$//;
my @containers = split "\n" , `$docker ps --no-trunc=true`;
my $result;
for my $i (1 .. $#containers)
{
my @fields = split / +/, $containers[$i];
my $id = $fields[0];
my $name = $fields[$#fields];
# manage container name containing arithmetic operators and dots. E.g, my-container.
$name =~ s/[-\+*\/\.]/_/g;
# truncate container name with "," character.
$name =~ s/,.*//g;
if (open(my $file, '<', "/sys/fs/cgroup/memory/docker/$id/memory.usage_in_bytes"))
{
my $memory_bytes = <$file>;
$memory_bytes =~ s/\s+$//;
push @result, {'name'=>$name, 'memory_bytes'=>$memory_bytes};
}
}
if (defined $ARGV[0] and $ARGV[0] eq "config")
{
print "graph_title Docker container memory usage\n";
print "graph_args --base 1024 -l 0\n";
print "graph_vlabel Bytes\n";
print "graph_category Docker\n";
print "graph_info This graph shows docker container memory usage.\n";
foreach(@result)
{
print "$$_{'name'}.label $$_{'name'}\n";
print "$$_{'name'}.draw LINE2\n";
}
exit 0;
}
foreach(@result)
{
print "$$_{'name'}.value $$_{'memory_bytes'}\n";
}
# vim:syntax=perl

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View file

@ -20,7 +20,7 @@ mktempfile () {
mktemp -t $1
}
LOGFILE=${logfile:-/var/log/xferlog}
LOGFILE=${logfile:-/var/log/proftpd/xferlog}
LOGTAIL=${logtail:-`which logtail`}
STATEFILE=/var/lib/munin/plugin-state/xferlog-bytes.offset

View file

@ -20,7 +20,7 @@ mktempfile () {
mktemp -t $1
}
LOGFILE=${logfile:-/var/log/xferlog}
LOGFILE=${logfile:-/var/log/proftpd/xferlog}
LOGTAIL=${logtail:-`which logtail`}
STATEFILE=/var/lib/munin/plugin-state/xferlog-count.offset

View file

@ -22,7 +22,7 @@
"""
import sys, os
import sys, os, re
from subprocess import check_output
# set path to your gunicorn pid
@ -44,11 +44,9 @@ class GunicornMemoryStatus():
except:
raise Exception("Couldn't read gunicorn pid information")
def print_total_memory(self):
print ('total_memory.value %d' % self._get_total_memory())
def _get_master_pid(self):
master_pid_file = open(GUNICORN_PID_PATH)
self.master_pid = master_pid_file.read().rstrip()
@ -74,7 +72,18 @@ class GunicornMemoryStatus():
return worker_memory_usage
def print_config():
print "graph_title Gunicorn - Memory Usage"
instance = None
name = os.path.basename(sys.argv[0])
if name != "gunicorn_memory_status":
for r in ("^gunicorn_(.*?)_memory_status$", "^gunicorn_memory_status_(.*?)$"):
m = re.match(r, name, re.IGNORECASE)
if m:
instance = m.group(1)
break
graph_title = "graph_title Gunicorn - Memory Usage"
if instance:
graph_title = "%s - %s" % (graph_title, instance)
print graph_title
print "graph_args --base 1024 -l 0"
print "graph_vlabel Megabytes"
print "graph_category gunicorn"

View file

@ -21,7 +21,7 @@
"""
import sys, os
import sys, os, re
from subprocess import check_output
from time import sleep
@ -87,7 +87,18 @@ class GunicornStatus():
return user_time + kernel_time
def print_config():
print "graph_title Gunicorn - Status"
instance = None
name = os.path.basename(sys.argv[0])
if name != "gunicorn_status":
for r in ("^gunicorn_(.*?)_status$", "^gunicorn_status_(.*?)$"):
m = re.match(r, name, re.IGNORECASE)
if m:
instance = m.group(1)
break
graph_title = "graph_title Gunicorn - Status"
if instance:
graph_title = "%s - %s" % (graph_title, instance)
print graph_title
print "graph_args -l 0"
print "graph_vlabel Number of workers"
print "graph_category gunicorn"

View file

@ -40,7 +40,7 @@ server {
=head2 APACHE 2.2 CONFIG
FastCgiExternalServer /var/run/hhvm_admin.fcgi -host 127.0.0.1:8080
Listen 127.0.0.1:8081
Listen 127.0.0.1:8081
<VirtualHost 127.0.0.1:8081>
Alias /check-health /var/run/hhvm_admin.fcgi
Alias /status.json /var/run/hhvm_admin.fcgi
@ -107,8 +107,6 @@ tc-profsize.label TC Profiling Size
tc-profsize.info Translation Cache Profiling Size
tc-coldsize.label TC Cold Size
tc-coldsize.info Translation Cache Cold Size
tc-trampolinessize.label TC Trampoline Size
tc-trampolinessize.info Translation Cache Trampoline Size
tc-frozensize.label TC Frozen Size
tc-frozensize.info Translation Cache Frozen Size
rds.label RDS Used Bytes
@ -121,7 +119,7 @@ EOF
my $status = getJson( sprintf( '%s/status.json', $url ) );
printf( "multigraph hhvm_%s_threads\n", $graphName );
printf( "threads.value %d\n", int( @{ $status->{'status'}->{'threads'} } ) );
printf( "threads.value %d\n", int( @{ $status->{'status'}->{'threads'} } ) );
printf( "load.value %d\n", $health->{'load'} );
printf( "queued.value %d\n", $health->{'queued'} );
print "\n";
@ -131,7 +129,6 @@ EOF
printf( "tc-size.value %d\n", $health->{'tc-size'} );
printf( "tc-profsize.value %d\n", $health->{'tc-profsize'} );
printf( "tc-coldsize.value %d\n", $health->{'tc-coldsize'} );
printf( "tc-trampolinessize.value %d\n", $health->{'tc-trampolinessize'} );
printf( "tc-frozensize.value %d\n", $health->{'tc-frozensize'} );
printf( "rds.value %d\n", $health->{'rds'} );
printf( "units.value %d\n", $health->{'units'} );
@ -151,4 +148,4 @@ sub getJson( $ ) {
die( sprintf( "Could not decode json from '%s'.", $url ) );
}
return $data;
}
}

View file

@ -66,8 +66,20 @@ my $wgetBin = "/usr/bin/wget";
my $type = basename($0);
$type =~ s/jenkins_//;
my %states = ('blue' =>'stable', 'blue_anime' =>'stable', 'yellow'=>'unstable', 'yellow_anime'=>'unstable', 'red'=>'failing', 'red_anime'=>'failing', 'disabled'=>'disabled', 'notbuilt_anime' =>'disabled', 'aborted'=>'failing', 'aborted_anime'=>'failing' );
my %counts = ('blue' => 0, 'yellow'=>0, 'red'=>0, 'disabled'=>0);
my %states = (
'blue' =>'stable',
'blue_anime' =>'stable',
'yellow'=>'unstable',
'yellow_anime'=>'unstable',
'red'=>'failing',
'red_anime'=>'failing',
'disabled'=>'disabled',
'notbuilt' => 'disabled',
'notbuilt_anime' =>'disabled',
'aborted'=>'failing',
'aborted_anime'=>'failing'
);
my %counts = ('stable' => 0, 'unstable'=>0, 'failing'=>0, 'disabled'=>0);
if ( exists $ARGV[0] and $ARGV[0] eq "config" ) {
if( $type eq "results" ) {
@ -123,11 +135,15 @@ if ( exists $ARGV[0] and $ARGV[0] eq "config" ) {
my $result = `$cmd/api/json`;
my $parsed = decode_json($result);
foreach my $cur(@{$parsed->{'jobs'}}) {
$counts{$cur->{'color'}} += 1;
if (defined $states{$cur->{'color'}}) {
$counts{$states{$cur->{'color'}}} += 1;
} else {
warn "Ignoring unknown color " . $cur->{'color'} . "\n"
}
}
foreach my $status (keys %counts) {
print "build_$states{$status}.value $counts{$status}\n";
print "build_$status.value $counts{$status}\n";
}
exit;
}

48
plugins/lxd/lxd_disk Executable file
View file

@ -0,0 +1,48 @@
#!/usr/bin/python3
import sys
errors=[]
HAS_LIB=True
try:
from pylxd import api
except:
HAS_LIB=False
errors.append("no pylxd module")
c=None
HAS_ACCESS=True
try:
c=api.API()
c.container_list()
except:
HAS_ACCESS=False
errors.append("no socket access")
if len(sys.argv) == 2 and sys.argv[1]=="autoconf":
if HAS_LIB and HAS_ACCESS:
print("yes")
else:
print("no ("+" and ".join(errors)+")")
sys.exit(0)
if not (HAS_LIB and HAS_ACCESS):
# pylxd not installed or lxd socket not accessible
sys.exit(1)
if len(sys.argv) == 2 and sys.argv[1]=="config":
print("graph_title LXD container disk usage")
print("graph_args --base 1000 --lower-limit 0")
print("graph_vlabel Bytes")
print("graph_category lxd")
print("graph_info This shows the disk usage of storage in containers. Make sure to install pylxd in python3.")
for name in c.container_list():
for disk in c.container_info(name)['disk']:
print(name+"-"+disk+".label "+name)
print(name+"-"+disk+".draw LINE2")
sys.exit(0)
for name in c.container_list():
for disk in c.container_info(name)['disk']:
print(name+"-"+disk+".value "+str(c.container_info(name)['disk'][disk]['usage']))

46
plugins/lxd/lxd_mem Executable file
View file

@ -0,0 +1,46 @@
#!/usr/bin/python3
import sys
errors=[]
HAS_LIB=True
try:
from pylxd import api
except:
HAS_LIB=False
errors.append("no pylxd module")
c=None
HAS_ACCESS=True
try:
c=api.API()
c.container_list()
except:
HAS_ACCESS=False
errors.append("no socket access")
if len(sys.argv) == 2 and sys.argv[1]=="autoconf":
if HAS_LIB and HAS_ACCESS:
print("yes")
else:
print("no ("+" and ".join(errors)+")")
sys.exit(0)
if not (HAS_LIB and HAS_ACCESS):
# pylxd not installed or lxd socket not accessible
sys.exit(1)
if len(sys.argv) == 2 and sys.argv[1]=="config":
print("graph_title LXD container memory")
print("graph_args --base 1024 --lower-limit 0")
print("graph_vlabel Bytes")
print("graph_category lxd")
print("graph_info This shows the memory usage of each container. Make sure to install pylxd in python3.")
for name in c.container_list():
print(name+".label "+name)
print(name+".draw AREASTACK")
sys.exit(0)
for name in c.container_list():
print(name+".value "+str(c.container_info(name)['memory']['usage']))

88
plugins/mail/policyd-spf-python Executable file
View file

@ -0,0 +1,88 @@
#! /bin/bash
#
# Munin plugin to monitor postfix-policyd-spf-python results
# Contributed by Alexander Koch <lynix47@gmail.com>
#
# This plugin is published under the terms of the MIT License.
#
# Parameters understood:
# config (required)
# autoconf (optional - used by munin-config)
#
# Config variables:
# logfile - Where to find the postfix log (mail.log)
#
# Add the following line to a file in /etc/munin/plugin-conf.d:
# env.logfile /var/log/your/mail.log
#
# Magic markers (optional - used by munin-config and installation scripts):
#
#%# family=auto
#%# capabilities=autoconf
#
# Configuration
#
STAT_FILE=${STAT_FILE:-/var/lib/munin/plugin-state/plugin-plcyd-spf-python.state}
LOGFILE=${logfile:-/var/log/mail.log}
if [ "$1" = "autoconf" ]; then
echo yes
exit 0
fi
if [ "$1" = "config" ]; then
echo 'graph_title SPF Check Results'
echo 'graph_category postfix'
echo 'graph_args --base 1000 -l 0'
echo 'graph_vlabel Count/s'
echo 'count_pass.label Pass'
echo 'count_pass.type DERIVE'
echo 'count_pass.min 0'
echo 'count_pass.colour 00cc00'
echo 'count_fail.label Fail'
echo 'count_fail.type DERIVE'
echo 'count_fail.min 0'
echo 'count_fail.colour cc0000'
echo 'count_none.label None'
echo 'count_none.type DERIVE'
echo 'count_none.min 0'
echo 'count_none.colour 0066b3'
echo 'count_temperror.label Temperror'
echo 'count_temperror.type DERIVE'
echo 'count_temperror.min 0'
echo 'count_temperror.colour ff8000'
echo 'count_neutral.label Neutral'
echo 'count_neutral.type DERIVE'
echo 'count_neutral.min 0'
echo 'count_neutral.colour ffcc00'
exit 0
fi
#
# Log parsing
#
function get_log_count() {
egrep "policyd-spf\[[0-9]+\]: $1;" "$LOGFILE" | grep "$(date '+%b %e')" | wc -l
}
PASS=$(get_log_count "Pass")
FAIL=$(get_log_count "Fail")
NONE=$(get_log_count "None")
TEMPERR=$(get_log_count "Temperror")
NEUTRAL=$(get_log_count "Neutral")
echo "count_pass.value $PASS"
echo "count_fail.value $FAIL"
echo "count_none.value $NONE"
echo "count_temperror.value $TEMPERR"
echo "count_neutral.value $NEUTRAL"
exit 0

View file

@ -0,0 +1,57 @@
#!/usr/bin/env perl
# ex:ts=4
use strict;
use warnings;
use Cache::Memcached;
# Based on original plugin, extended to unix socket use
# https://github.com/western, westroads@gmail.com
=head1 example config for /plugin-conf.d/munin-node
[memcached_bytes_1]
env.server 127.0.0.1:11211
env.label "first local server"
[memcached_bytes_2]
env.server /var/run/memcached/memcached.sock
env.label "second local server"
=cut
my $label = exists $ENV{'label'} ? $ENV{'label'} : '';
unless( $label ){
if( $0 =~ /memcached_ext_bytes_([\d\w]+)$/ ){
$label = $1;
}
}
my $cmd = shift || '';
if ($cmd eq 'config') {
print "graph_title Memcached bytes used on $label\n";
print "graph_args --base 1024 -l 0\n";
print "graph_vlabel bytes\n";
print "graph_category memcached\n";
print "graph_info This graph monitors the size of the memcached cache.\n";
print "bytes.label bytes used\n";
print "bytes.info Number of bytes currently used\n";
print "bytes.min 0\n";
print "bytes.draw AREA\n";
print "maxbytes.label maximum available\n";
print "maxbytes.info The configured cache size\n";
print "maxbytes.min 0\n";
exit 0;
}
my $server = exists $ENV{'server'} ? $ENV{'server'} : '127.0.0.1:11211';
my $memd = new Cache::Memcached { 'servers' => [$server] };
my $memstats = $memd->stats(['misc']);
print "bytes.value " . $memstats->{hosts}->{$server}->{misc}->{bytes} . "\n";
print "maxbytes.value " .
$memstats->{hosts}->{$server}->{misc}->{limit_maxbytes} . "\n";

View file

@ -0,0 +1,53 @@
#!/usr/bin/env perl
# ex:ts=4
use strict;
use warnings;
use Cache::Memcached;
# Based on original plugin, extended to unix socket use
# https://github.com/western, westroads@gmail.com
=head1 example config for /plugin-conf.d/munin-node
[memcached_connections_1]
env.server 127.0.0.1:11211
env.label "first local server"
[memcached_connections_2]
env.server /var/run/memcached/memcached.sock
env.label "second local server"
=cut
my $label = exists $ENV{'label'} ? $ENV{'label'} : '';
unless( $label ){
if( $0 =~ /memcached_ext_connections_([\w\d]+)$/ ){
$label = $1;
}
}
my $cmd = shift || '';
if ($cmd eq 'config') {
print "graph_title Memcached connections on $label\n";
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel connections\n";
print "graph_category memcached\n";
print "graph_info This graph monitors the connections to the memcached server.\n";
print "connections.label connections\n";
print "connections.info Number of connections to memcached\n";
print "connections.min 0\n";
print "connections.draw AREA\n";
exit 0;
}
my $server = exists $ENV{'server'} ? $ENV{'server'} : '127.0.0.1:11211';
my $memd = new Cache::Memcached { 'servers' => [$server] };
my $memstats = $memd->stats(['misc']);
print "connections.value " .
$memstats->{hosts}->{$server}->{misc}->{curr_connections} . "\n";

View file

@ -0,0 +1,60 @@
#!/usr/bin/env perl
# ex:ts=4
use strict;
use warnings;
use Cache::Memcached;
# Based on original plugin, extended to unix socket use
# https://github.com/western, westroads@gmail.com
=head1 example config for /plugin-conf.d/munin-node
[memcached_hits_1]
env.server 127.0.0.1:11211
env.label "first local server"
[memcached_hits_2]
env.server /var/run/memcached/memcached.sock
env.label "second local server"
=cut
my $label = exists $ENV{'label'} ? $ENV{'label'} : '';
unless( $label ){
if( $0 =~ /memcached_ext_hits_([\w\d]+)$/ ){
$label = $1;
}
}
my $cmd = shift || '';
if ($cmd eq 'config') {
print "graph_title Memcached cache hits and misses on $label\n";
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel requests\n";
print "graph_category memcached\n";
print "graph_info This graph monitors the number of cache hits and misses.\n";
print "hits.label hits\n";
print "hits.info Number of cache hits\n";
print "hits.min 0\n";
print "hits.type DERIVE\n";
print "misses.label misses\n";
print "misses.info Number of cache misses\n";
print "misses.min 0\n";
print "misses.type DERIVE\n";
print "misses.draw AREA\n";
exit 0;
}
my $server = exists $ENV{'server'} ? $ENV{'server'} : '127.0.0.1:11211';
my $memd = new Cache::Memcached { 'servers' => [$server] };
my $memstats = $memd->stats(['misc']);
print "hits.value " . $memstats->{hosts}->{$server}->{misc}->{get_hits} . "\n";
print "misses.value " .
$memstats->{hosts}->{$server}->{misc}->{get_misses} . "\n";

View file

@ -0,0 +1,53 @@
#!/usr/bin/env perl
# ex:ts=4
use strict;
use warnings;
use Cache::Memcached;
# Based on original plugin, extended to unix socket use
# https://github.com/western, westroads@gmail.com
=head1 example config for /plugin-conf.d/munin-node
[memcached_items_1]
env.server 127.0.0.1:11211
env.label "first local server"
[memcached_items_2]
env.server /var/run/memcached/memcached.sock
env.label "second local server"
=cut
my $label = exists $ENV{'label'} ? $ENV{'label'} : '';
unless( $label ){
if( $0 =~ /memcached_ext_items_([\w\d]+)$/ ){
$label = $1;
}
}
my $cmd = shift || '';
if ($cmd eq 'config') {
print "graph_title Memcached cached items on $label\n";
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel items\n";
print "graph_category memcached\n";
print "graph_info This graph monitors the number of items stored by the memcached server.\n";
print "items.label items\n";
print "items.info Number of cached items\n";
print "items.min 0\n";
print "items.draw AREA\n";
exit 0;
}
my $server = exists $ENV{'server'} ? $ENV{'server'} : '127.0.0.1:11211';
my $memd = new Cache::Memcached { 'servers' => [$server] };
my $memstats = $memd->stats(['misc']);
print "items.value " .
$memstats->{hosts}->{$server}->{misc}->{curr_items} . "\n";

View file

@ -0,0 +1,59 @@
#!/usr/bin/env perl
# ex:ts=4
use strict;
use warnings;
use Cache::Memcached;
# Based on original plugin, extended to unix socket use
# https://github.com/western, westroads@gmail.com
=head1 example config for /plugin-conf.d/munin-node
[memcached_requests_1]
env.server 127.0.0.1:11211
env.label "first local server"
[memcached_requests_2]
env.server /var/run/memcached/memcached.sock
env.label "second local server"
=cut
my $label = exists $ENV{'label'} ? $ENV{'label'} : '';
unless( $label ){
if( $0 =~ /memcached_ext_requests_([\w\d]+)$/ ){
$label = $1;
}
}
my $cmd = shift || '';
if ($cmd eq 'config') {
print "graph_title Memcached requests on $label\n";
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel requests\n";
print "graph_category memcached\n";
print "graph_info This graph monitors the number of get and set requests.\n";
print "gets.label gets\n";
print "gets.info Number of get requests\n";
print "gets.min 0\n";
print "gets.type DERIVE\n";
print "gets.draw AREA\n";
print "sets.label sets\n";
print "sets.info Number of set requests\n";
print "sets.min 0\n";
print "sets.type DERIVE\n";
print "sets.draw STACK\n";
exit 0;
}
my $server = exists $ENV{'server'} ? $ENV{'server'} : '127.0.0.1:11211';
my $memd = new Cache::Memcached { 'servers' => [$server] };
my $memstats = $memd->stats(['misc']);
print "gets.value " . $memstats->{hosts}->{$server}->{misc}->{cmd_get} . "\n";
print "sets.value " . $memstats->{hosts}->{$server}->{misc}->{cmd_set} . "\n";

View file

@ -0,0 +1,60 @@
#!/usr/bin/env perl
# ex:ts=4
use strict;
use warnings;
use Cache::Memcached;
# Based on original plugin, extended to unix socket use
# https://github.com/western, westroads@gmail.com
=head1 example config for /plugin-conf.d/munin-node
[memcached_traffic_1]
env.server 127.0.0.1:11211
env.label "first local server"
[memcached_traffic_2]
env.server /var/run/memcached/memcached.sock
env.label "second local server"
=cut
my $label = exists $ENV{'label'} ? $ENV{'label'} : '';
unless( $label ){
if( $0 =~ /memcached_ext_traffic_([\w\d]+)$/ ){
$label = $1;
}
}
my $cmd = shift || '';
if ($cmd eq 'config') {
print "graph_title Memcached network traffic on $label\n";
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel bits per \${graph_period}\n";
print "graph_category memcached\n";
print "graph_info This graph monitors the network traffic of the memcached server.\n";
print "up.label bits in\n";
print "up.info Traffic received by memcached\n";
print "up.min 0\n";
print "up.cdef up,8,*\n";
print "up.type COUNTER\n";
print "up.draw AREA\n";
print "down.label bits out\n";
print "down.info Traffic sent by memcached\n";
print "down.min 0\n";
print "down.cdef down,8,*\n";
print "down.type COUNTER\n";
exit 0;
}
my $server = exists $ENV{'server'} ? $ENV{'server'} : '127.0.0.1:11211';
my $memd = new Cache::Memcached { 'servers' => [$server] };
my $memstats = $memd->stats(['misc']);
print "up.value " . $memstats->{hosts}->{$server}->{misc}->{bytes_read} . "\n";
print "down.value " . $memstats->{hosts}->{$server}->{misc}->{bytes_written} . "\n";

View file

@ -54,6 +54,8 @@ if len(sys.argv) > 1 and sys.argv[1] == 'config':
for process in procs:
for stat in procs[process]:
print "monit_%s_%s.label %s.%s" % (process, stat, process, stat)
if stat == 'total_memory':
print "monit_%s_%s.warning 1:" % (process, stat)
sys.exit(0)
for process in procs:

View file

@ -81,7 +81,6 @@ if (count($argv) === 2 && $argv[1] === 'config') {
echo "graph_args --base 1024 --lower-limit 0\n";
echo "graph_vlabel size\n";
echo "graph_category Moodle\n";
echo "graph_scale no\n";
echo "graph_total total\n";
echo "graph_info Displays the total size of moodle users files and repartition by type\n";
@ -119,7 +118,6 @@ echo "graph_title Moodle Files Size\n";
echo "graph_args --base 1024 --lower-limit 0\n";
echo "graph_vlabel size\n";
echo "graph_category Moodle\n";
echo "graph_scale yes\n";
echo "graph_total total\n";
echo "graph_info Displays the total size of moodle users files and repartition by type\n";

54
plugins/network/arp_bsd_ Normal file
View file

@ -0,0 +1,54 @@
#!/bin/sh
#
# Wildcard-plugin to monitor arp on interfaces. To monitor an
# interface, link arp_bsd_<interface> to this file. E.g.
#
# ln -s /usr/local/share/munin/plugins/arp_bsd_ /usr/local/etc/munin/plugins/arp_bsd_vlanX
#
# ...will monitor arp on interface vlanX.
#
# Any device found in /sbin/ifconfig can be monitored.
#
# Bugs : This plugins has been tested extensively on FreeBSD only
#
# Author : Luc Duchosal <luc.duchosal (at) arcantel (dot) ch>
#
# Magic markers (optional - used by munin-config and some installation
# scripts):
#
#%# family=auto
#%# capabilities=autoconf suggest
INTERFACE=`basename $0 | sed 's/^arp_bsd_//g'`
if [ "$1" = "autoconf" ]; then
if [ -x /sbin/ifconfig ]; then
echo yes
exit 0
else
echo "no (/sbin/ifconfig not found)"
exit 0
fi
fi
if [ "$1" = "suggest" ]; then
if [ -x /sbin/ifconfig ]; then
/sbin/ifconfig -a | /usr/bin/grep -E '^[a-z]' | /usr/bin/awk -F\: '{print $1;}'
exit 0
else
exit 1
fi
fi
if [ "$1" = "config" ]; then
echo "graph_title $INTERFACE arp"
echo 'graph_args --base 1000'
echo 'graph_vlabel arp per ${graph_period}'
echo 'graph_category network'
echo 'arp.label arp'
exit 0
fi
/usr/sbin/arp -an | /usr/bin/grep $INTERFACE | /usr/bin/wc -l | /usr/bin/awk '{ print "arp.value", $1;}'

View file

@ -1,15 +1,11 @@
#! /bin/sh
# Currently the plugin does *not* autostart
#
# It has to be launched via rc.d :
# munin-run if1sec_eth0 acquire
pluginfull="$0" # full name of plugin
plugin="${0##*/}" # name of plugin
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
IFACE="${0##*/if1sec_}" # interface
if [ ! -r "/sys/class/net/$IFACE/statistics/tx_bytes" ]
then
@ -19,44 +15,86 @@ 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
(
exec <&- >&- 2>&-
while sleep 1
do
read tx < /sys/class/net/$IFACE/statistics/tx_bytes
read rx < /sys/class/net/$IFACE/statistics/rx_bytes
echo "$tx $rx"
done | awk "{
now = systime()
print \"${IFACE}_tx.value \" now \":\" \$1
print \"${IFACE}_rx.value \" now \":\" \$2
system(\"\")
}" >> $cache
) &
echo $! > $pidfile
exit 0
fi
if [ "$1" = "config" ]
then
cat <<EOF
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
graph_category network
graph_data_size custom 1d, 10s for 1w, 1m for 1t, 5m for 450d
graph_vlabel bits/sec
update_rate 1
${IFACE}_tx.label ${IFACE} TX bytes
${IFACE}_tx.label ${IFACE} TX bits
${IFACE}_tx.cdef ${IFACE}_tx,8,*
${IFACE}_tx.type DERIVE
${IFACE}_tx.min 0
${IFACE}_rx.label ${IFACE} RX bytes
${IFACE}_rx.label ${IFACE} RX bits
${IFACE}_rx.cdef ${IFACE}_rx,8,*
${IFACE}_rx.type DERIVE
${IFACE}_rx.min 0
EOF
exit 0
# If max speed is easily available, report it. More complex
# code could be copied from "if_".
if [ -r /sys/class/net/$IFACE/speed ]
then
SPEED=$(cat /sys/class/net/$IFACE/speed)
echo "${IFACE}_rx.max" $((SPEED / 8 * 1000000))
echo "${IFACE}_tx.max" $((SPEED / 8 * 1000000))
echo "${IFACE}_rx.info Received traffic on the $IFACE interface. Maximum speed is ${SPEED} Mbps."
echo "${IFACE}_tx.info Transmitted traffic on the $IFACE interface. Maximum speed ${SPEED} Mbps."
fi
exit 0
fi
# values
# Autorun logic
running=true
if [ ! -e ${cache} ]
then
# no cache file
running=false
elif [ ! -s ${cache} ]
then
# empty cache file
if [ -s ${pidfile} ]
then
# kill -0 will return success if this user is allowed to send
# a signal to the process. This means the PID exists and
# belongs to the plugin user, which should have few false
# positives.
if ! kill -0 $(cat ${pidfile})
then
running=false
fi
else
running=false
fi
fi
if ! $running
then
$0 acquire &
# wait a little so we have some data to report
sleep 3
fi
# Finally: Print collected values, truncate to mark spot.
cat ${cache}
> ${cache}

252
plugins/network/pf_tables_ Normal file
View file

@ -0,0 +1,252 @@
#!/usr/bin/perl -w
# -*- perl -*-
=head1 NAME
pf_tables : Munin plugin to monitor pf tables.
Inout: bandwidth usage for table
Addresses: number of entries in table
=head1 APPLICABLE SYSTEMS
Should work on any BSD that has pf(4).
Examples:
=over
=item pf_tables_inout_tablename
=item pf_tables_addresses_authenticated
=item pf_tables_addresses_badboys
=head1 CONFIGURATION
[pf_tables_*]
user root
=head1 INTERPRETATION
The plugin simply runs the pfctl -sTables -vvv command and counts the number of
Addresses and InBytes/OutBytes in each table.
=head1 BUGS
Only tested extensively on FreeBSD.
=head1 MAGIC MARKERS
#%# family=auto
#%# capabilities=autoconf suggest
=head1 VERSION
$Id$
=head1 AUTHOR
Copyright (C) 2015.
Original version by Luc Duchosal (at) arcantel (dot) ch.
Created by Luc Duchosal, 2015
=head1 LICENSE
BSD
=cut
use strict;
use Munin::Plugin;
$0 =~ /pf_tables_(addresses|inout)_(.+)$/;
my $name = $2;
my $operation = $1;
if ( defined($ARGV[0])) {
if ($ARGV[0] eq 'autoconf') {
print "yes\n";
exit 0;
}
if ($ARGV[0] eq "config") {
if (!defined($name)) {
print "Unknown table\n";
exit 0;
}
if (!defined($operation)) {
print "Unknown operation\n";
exit 0;
}
if ($operation =~ m/addresses/) {
print "graph_title Connected users ($name)\n";
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel Users\n";
print "graph_scale no\n";
print "graph_category pf\n";
print "graph_printf %3.0lf\n";
print "users.label users\n";
print "users.draw AREASTACK\n";
print "users.colour 00C000\n";
foreach my $field (qw(users)) {
print_thresholds($field);
}
}
if ($operation =~ m/inout/) {
print "graph_title Network bandwidth ($name)\n";
print "graph_args --base 1024 -l 0\n";
print "graph_vlabel Bandwidth\n";
print "graph_scale yes\n";
print "graph_category pf\n";
# print "graph_printf %3.0lf\n";
print "in.label in\n";
print "in.type DERIVE\n";
print "in.draw AREASTACK\n";
print "in.colour C00000\n";
print "in.cdef in,8,*\n";
print "in.min 0\n";
print "in.graph no\n";
print "out.label out\n";
print "out.type DERIVE\n";
print "out.negative in\n";
print "out.draw AREASTACK\n";
print "out.colour 0000C0\n";
print "out.cdef out,8,*\n";
print "out.min 0\n";
print "out.graph no\n";
foreach my $field (qw(in out)) {
print_thresholds($field);
}
}
exit 0;
}
if ($ARGV[0] eq "suggest") {
my %tables = &tables();
foreach my $key (keys(%tables)) {
print "addresses_$key\n";
print "inout_$key\n";
}
exit 0;
}
}
if (!defined($name)) {
print "Usage: pf_tables_addresses_tablename or pf_tables_inout_tablename\n";
exit 1;
}
my %tables = &tables();
if (!exists $tables{$name}) {
print "Unknown table name $name\n";
exit 2;
}
if ($operation =~ m/addresses/) {
my $users = $tables{$name}->{"addresses"};
print "users.value $users\n";
}
if ($operation =~ m/inout/) {
my $in = $tables{$name}->{"inpassbytes"};
my $out = $tables{$name}->{"outpassbytes"};
print "in.value $in\n";
print "out.value $out\n";
}
sub tables {
# # pfctl -s Tables -vv
# -pa-r-- auth
# Addresses: 0
# Cleared: Fri Sep 18 17:34:42 2015
# References: [ Anchors: 0 Rules: 14 ]
# Evaluations: [ NoMatch: 43624 Match: 788 ]
# In/Block: [ Packets: 0 Bytes: 0 ]
# In/Pass: [ Packets: 30908 Bytes: 2704516 ]
# In/XPass: [ Packets: 124 Bytes: 7897 ]
# Out/Block: [ Packets: 0 Bytes: 0 ]
# Out/Pass: [ Packets: 30288 Bytes: 26313114 ]
# Out/XPass: [ Packets: 89 Bytes: 21166 ]
my $output = `/sbin/pfctl -s Tables -vv 2> /dev/null`;
my %tables;
my $name;
foreach (split(/\n/, $output)) {
if (m|^[cpairhC\-]{7}\s+(\w+)$|) {
$name = $1;
$tables{$name}->{"name"} = $1;
next;
}
if (m|Addresses:\s+([0-9]+)$|) {
$tables{$name}->{"addresses"} = $1;
next;
}
if (m|Cleared:\s+(.+)$|) {
$tables{$name}->{"cleared"} = $1;
next;
}
if (m|In/Block:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
$tables{$name}->{"inblockpackets"} = $1;
$tables{$name}->{"inblockbytes"} = $2;
next;
}
if (m|In/Pass:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
$tables{$name}->{"inpasspackets"} = $1;
$tables{$name}->{"inpassbytes"} = $2;
next;
}
if (m|In/XPass:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
$tables{$name}->{"inxpasspackets"} = $1;
$tables{$name}->{"inxpassbytes"} = $2;
next;
}
if (m|Out/Block:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
$tables{$name}->{"outblockpackets"} = $1;
$tables{$name}->{"outblockbytes"} = $2;
next;
}
if (m|Out/Pass:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
$tables{$name}->{"outpasspackets"} = $1;
$tables{$name}->{"outpassbytes"} = $2;
next;
}
if (m|Out/XPass:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
$tables{$name}->{"outxpasspackets"} = $1;
$tables{$name}->{"outxpassbytes"} = $2;
next;
}
}
return %tables;
}
# vim:syntax=perl

View file

@ -1,155 +1,140 @@
#!/usr/bin/php
<?php
/*
Plugin: radio
Author: Philipp Giebel (spam@stimpyrama.org)
Version: 0.1
Munin (http://munin.projects.linpro.no/) Plugin for counting
listeners to both shout- and icecast streams.
Requirements: * PHP (jap, I know that sucks.. ;) )
Plugin: radio
Author: Philipp Giebel (spam@stimpyrama.org)
Version: 0.2
Munin (http://munin-monitoring.org/) Plugin for counting
listeners to both shout- and icecast streams.
Get the latest version at:
http://munin-monitoring.org/log/munin-contrib/plugins/network/radio
Requirements: * PHP (jap, I know that sucks.. ;) )
CHANGELOG
v0.1 - Quick & Dirty proof of concept
v0.2 - Updated to match output of current versions of ice- and shoutcast.
*/
// -------------- CONFIGURATION START ---------------------------------------------------------------
$cfg = array(
// SERVER #1
array( "type" => "ice", // server-type (ice/shout)
"host" => "192.168.1.5", // server hostname or ip
"port" => 8000, // server port
"mountpoint" => "eclectix.mp3", // mountpoint to check (icecast only)
"name" => "IceCast" // name for use in munin graphs
),
// SERVER #2
array( "type" => "shout", // server-type
"host" => "radio.eclectix.de", // server hostname or ip
"port" => 8000, // server port
"name" => "ShoutCast" // name for use in munin graphs
)
);
// -------------- CONFIGURATION END ----------------------------------------------------------------
function getIce( $host, $port, $mount, $name ) {
$error = false;
$fp = fsockopen( $host, $port, $errno, $errstr, 10 );
if ( !$fp ) {
$error = $errstr ."(". $errno .")";
} else {
fputs( $fp, "GET /status HTTP/1.1\r\n" );
fputs( $fp, "Host: ". $host ."\r\n" );
fputs($fp, "User-Agent: Mozilla\r\n");
fputs( $fp, "Connection: close\r\n\r\n" );
$xml = "";
while ( !feof( $fp ) ) {
$xml .= fgets( $fp, 512 );
}
fclose($fp);
if ( stristr( $xml, "HTTP/1.0 200 OK" ) == true ) {
$xml = trim( substr( $xml, 42 ) );
} else {
$error = "Bad login";
}
if ( !$error ) {
$res = array( "found" => true );
$mount = str_replace( ".", "\.", $mount );
preg_match_all( "/Mount Point : \(\/(". $mount .")\).*?\<tr\>\<td\>Current Listeners:\<\/td\>\<td class=\"streamdata\"\>(\d*?)\<\/td\>\<\/tr\><tr>\<td\>Peak Listeners:\<\/td\>\<td class=\"streamdata\"\>(\d*?)\<\/td\>\<\/tr\>/s", $xml, $parser );
$res["mount"] = $parser[1][0];
$res["listeners"] = $parser[2][0];
$res["listeners_peak"] = $parser[3][0];
$res["name"] = $name;
} else {
$res = $error;
}
}
return $res;
}
function getShout( $host, $port, $name ) {
$error = false;
$fp = fsockopen( $host, $port, $errno, $errstr, 10 );
if ( !$fp ) {
$error = $errstr ."(". $errno .")";
} else {
fputs( $fp, "GET / HTTP/1.0\r\n" );
fputs($fp, "User-Agent: Mozilla\r\n");
fputs( $fp, "Connection: close\r\n\r\n" );
$xml = "";
while ( !feof( $fp ) ) {
$xml .= fgets($fp, 512);
}
fclose( $fp );
if ( stristr( $xml, "HTTP/1.0 200 OK" ) == true ) {
$xml = trim( substr( $xml, 42 ) );
} else {
$error = "Bad login";
}
if ( !$error ) {
$res = array( "found" => true );
preg_match_all( "/.*?Stream Status: \<\/font\>\<\/td\>\<td\>\<font class=default\>\<b\>Stream is up at \d*? kbps with \<B\>(\d*?) of \d*? listeners \(\d*? unique\)\<\/b\>\<\/b\>/s", $xml, $parser );
$res["listeners"] = $parser[1][0];
$res["name"] = $name;
} else {
$res = $error;
}
}
return $res;
// -------------- CONFIGURATION START ---------------------------------------
$cfg = array(
// SERVER #1
array( "name" => "IceCast", // name for munin
"type" => "ice", // server-type (ice/shout)
"host" => "ice.example.com", // server hostname or ip
"port" => 8000, // server port
"mountpoint" => "live" // mountpoint to check
// (icecast only)
),
// SERVER #2
array( "name" => "ShoutCast", // name for munin
"type" => "shout", // server-type
"host" => "127.0.0.1", // server hostname or ip
"port" => 8000 // server port
)
);
// -------------- CONFIGURATION END -----------------------------------------
error_reporting(E_ERROR);
function getIce( $host, $port, $mount, $name ) {
$error = false;
if ( !$fp = fsockopen( $host, $port, $errno, $errstr, 10 ) ) {
$error = $errstr ."(". $errno .")";
} else {
fputs( $fp, "GET /status.xsl HTTP/1.1\r\n" );
fputs( $fp, "Host: ". $host ."\r\n" );
fputs( $fp, "User-Agent: Mozilla\r\n" );
fputs( $fp, "Connection: close\r\n\r\n" );
$xml = "";
while ( !feof( $fp ) ) {
$xml .= fgets( $fp, 512 );
}
fclose( $fp );
if ( stristr( $xml, "HTTP/1.0 200 OK" ) == true ) {
$xml = trim( substr( $xml, 42 ) );
} else {
$error = "Bad login";
}
if ( !$error ) {
$res = array( "found" => true );
$mount = str_replace( ".", "\.", $mount );
preg_match_all( "/Mount Point \/(". $mount .").*?\<tr\>\<td\>Current Listeners:\<\/td\>\<td class=\"streamdata\"\>(\d*?)\<\/td\>\<\/tr\><tr>\<td\>Peak Listeners:\<\/td\>\<td class=\"streamdata\"\>(\d*?)\<\/td\>\<\/tr\>/s", $xml, $parser );
$res["mount"] = $parser[1][0];
$res["listeners"] = intval( $parser[2][0] );
$res["listeners_peak"] = intval( $parser[3][0] );
$res["name"] = $name;
} else {
$res = $error;
}
}
return $res;
}
function getShout( $host, $port, $name ) {
$error = false;
if ( !$fp = fsockopen( $host, $port, $errno, $errstr, 10 ) ) {
$error = $errstr ."(". $errno .")";
} else {
fputs( $fp, "GET /index.html?sid=1 HTTP/1.0\r\n" );
fputs( $fp, "User-Agent: Mozilla\r\n" );
fputs( $fp, "Connection: close\r\n\r\n" );
$xml = "";
while ( !feof( $fp ) ) {
$xml .= fgets( $fp, 512 );
}
fclose( $fp );
if ( stristr( $xml, "HTTP/1.1 200 OK" ) == true ) {
$xml = trim( substr( $xml, 42 ) );
} else {
$error = "Bad login";
}
if ( !$error ) {
$res = array( "found" => true );
preg_match_all( "/.*?Stream Status: <\/td\>\<td\><b\>Stream is up at \d*? kbps with (\d*?) of \d*? listeners/s", $xml, $parser );
$res["listeners"] = intval( $parser[1][0] );
$res["name"] = $name;
} else {
$res = $error;
}
}
return $res;
}
if ( !isset( $argv[1] ) ) $argv[1] = '';
switch( $argv[1] ) {
case "config":
echo "graph_title Stream Listeners\n";
echo "graph_category Network\n";
echo "graph_vlabel listeners\n";
echo "graph_hlabel listeners\n";
echo "graph_args --base 1000 -l 0\n";
echo "graph_scale no\n";
echo "graph_info Number of listeners to shout- and / or icecast streams\n";
echo "complete.info Complete listeners\n";
echo "complete.label complete\n";
echo "graph_order";
foreach ( $cfg as $c ) {
echo " ". strtolower( $c["name"] );
}
echo " complete\n";
foreach ( $cfg as $c ) {
echo strtolower( $c["name"] ) .".info ". $c["name"] ." listeners\n";
echo strtolower( $c["name"] ) .".label ". strtolower( $c["name"] ) ."\n";
}
break;
default:
$complete = 0;
foreach ( $cfg as $c ) {
switch ( $c["type"] ) {
case "ice":
$res = getIce( $c["host"], $c["port"], $c["mountpoint"], $c["name"] );
break;
case "shout":
$res = getShout( $c["host"], $c["port"], $c["name"] );
break;
}
switch( $argv[1] ) {
case "config":
echo "graph_title Stream Listeners\n";
echo "graph_category Network\n";
echo "graph_vlabel listeners\n";
echo "graph_hlabel listeners\n";
echo "graph_args --base 1000 -l 0\n";
echo "graph_scale no\n";
echo "graph_order";
foreach ( $cfg as $c ) {
echo " ". strtolower( $c["name"] );
}
echo " complete\n";
// echo "\n";
echo "graph_info Number of listeners to shout- and / or icecast streams\n";
foreach ( $cfg as $c ) {
echo strtolower( $c["name"] ) .".info ". $c["name"] ." listeners\n";
echo strtolower( $c["name"] ) .".label ". strtolower( $c["name"] ) ."\n";
}
echo "complete.info Complete listeners\n";
echo "complete.label complete\n";
break;
default:
$complete = 0;
foreach ( $cfg as $c ) {
switch ( $c["type"] ) {
case "ice":
$res = getIce( $c["host"], $c["port"], $c["mountpoint"], $c["name"] );
$complete += $res["listeners"];
break;
case "shout":
$res = getShout( $c["host"], $c["port"], $c["name"] );
$complete += $res["listeners"];
break;
}
echo strtolower($c["name"]) .".value ". $res["listeners"] ."\n";
}
echo "complete.value ". $complete ."\n";
break;
}
if ( is_array( $res ) ) {
echo strtolower($c["name"]) .".value ". $res["listeners"] ."\n";
$complete += $res["listeners"];
} else {
echo strtolower($c["name"]) .".value 0\n";
}
}
echo "complete.value ". $complete ."\n";
break;
}
?>

View file

@ -25,9 +25,12 @@
# Use it in your site configuration (/etc/nginx/sites-enabled/anything.conf):
# access_log /var/log/nginx/upstream.log upstream;
#
# Attention! Because munin-node does not have read permission for nginx log files we need to run it as root.
#
# And specify some options in /etc/munin/plugin-conf.d/munin-node:
#
# [nginx_upstream_multi_upstream]
# user root
# env.graphs cache http time request
# env.log /var/log/nginx/upstream.log
# env.upstream 10.0.0.1:80 10.0.0.2:8080 unix:/tmp/upstream3
@ -199,8 +202,8 @@ else:
try:
logHandle = open(logPath, "r")
except Exception:
print "Log file %s not readable" % logPath
except Exception as e:
print "Log file %s not readable: %s" % (logPath, e.strerror)
sys.exit(1)
try:
@ -278,7 +281,8 @@ else:
lastByteHandle = open(lastBytePath, "w")
lastByteHandle.write(str(logHandle.tell()))
lastByteHandle.close()
except Exception:
except Exception as e:
print e.strerror
sys.exit(1)
logHandle.close()

44
plugins/openntpd/openntp_offset Executable file
View file

@ -0,0 +1,44 @@
#!/bin/sh
#
# Plugin to measure OpenNTPd offset, delay and jitter for the active peer.
#
# Usage: Place it in the munin plugins directory (/usr/local/etc/munin/plugins/
# or /etc/munin/plugins/). Might require running as root in order to access the
# ntpctl socket.
#
# AUTHOR: Vladimir Krstulja <info@acheronmedia.com>
# LICENSE: GPLv2
#
#%# family=auto
#%# capabilities=autoconf
NTPCTL=`which ntpctl`
# Config
if [ "$1" = "autoconf" ] ; then
if [ -f "$NTPCTL" ]; then
echo 'yes'
else
echo 'no (no ntpctl)'
fi
exit 0
fi
# Autoconf
if [ "$1" = "config" ] ; then
echo "graph_title OpenNTP offset statistics for active peer"
echo "graph_args --base 1000 --vertical-label seconds --lower-limit 0"
echo "graph_category time"
echo "graph_info Current status: `$NTPCTL -s status`"
echo "delay.label Delay"
echo "delay.cdef delay,1000,/"
echo "offset.label Offset"
echo "offset.cdef offset,1000,/"
echo "jitter.label Jitter"
echo "jitter.cdef jitter,1000,/"
exit 0
fi
# Main plugin function
$NTPCTL -s all | awk '/\*/{printf("offset.value %.3f\ndelay.value %.3f\njitter.value %.3f\n",$7,$8,$9)}'

View file

@ -1,52 +0,0 @@
#!/bin/sh
#
# Plugin to monitor error.log from apache server.
# Revision 0.1 2011/06/17 12:00:00 Ulrich Lusseau
# Initial revision
#
# Parameters:
#
# config (required)
# autoconf (optional - used by munin-config)
#
# Magick markers (optional):
#%# family=auto
#%# capabilities=autoconf
# config example for /etc/munin/plugin-conf.d/munin-node
#[apache_log]
#user root
#env.logfile /home/newsite/logs/errors.log
#
LOG=${logfile:-/var/log/apache2/error.log}
if [ "$1" = "autoconf" ]; then
if [ -r "$LOG" ]; then
echo yes
exit 0
else
echo no
exit 1
fi
fi
if [ "$1" = "config" ]; then
echo 'graph_title PHP Errors from ' $LOG
echo 'graph_args --base 1000 -l 0'
echo 'graph_vlabel Errors'
echo 'LogWarning.label PHP Warning errors'
echo 'LogNotice.label PHP Notice errors'
echo 'LogFatal.label PHP Fatal errors'
echo 'LogFile.label File does not exist errors'
exit 0
fi
awk 'BEGIN{c["LogWarning"]=0;c["LogNotice"]=0;c["LogFatal"]=0;c["LogFile"]=0; }
/PHP Warning/{c["LogWarning"]++}
/PHP Notice/{c["LogNotice"]++}
/PHP Fatal error/{c["LogFatal"]++}
/File does not exist/{c["LogFile"]++}
END{for(i in c){print i".value " c[i]} }' < $LOG

66
plugins/php/php_errors_ Normal file
View file

@ -0,0 +1,66 @@
#!/bin/bash
: << =cut
=head1 NAME
Plugin to monitor error.log from apache server
=head1 CONFIGURATION
[php_errors_newsite]
user www-data
env.logfile /home/newsite/logs/errors.log /var/log/php/otherlog.log
=head1 AUTHOR
Raphaël Droz <raphael.droz+floss@gmail.com>
Revision 0.2 2016/03/23 22:00:00 Raphaël Droz
Revision 0.1 2011/06/17 12:00:00 Ulrich Lusseau
=head1 MAGICK MARKERS
#%# family=auto
#%# capabilities=autoconf
=cut
. $MUNIN_LIBDIR/plugins/plugin.sh
LOGS=${logfile:-/var/log/apache2/error.log}
if [[ $1 == autoconf ]]; then
for LOG in $LOGS; do
if [[ ! -r $LOGS ]]; then
echo no
exit 1
fi
done
echo yes
exit 0
fi
if [[ $1 == config ]]; then
echo 'graph_title PHP Errors from ' $LOGS
echo 'graph_args --base 1000 -l 0'
echo 'graph_vlabel Errors'
echo 'LogWarning.label PHP Warning errors'
echo 'LogNotice.label PHP Notice errors'
echo 'LogFatal.label PHP Fatal errors'
echo 'LogFile.label File does not exist errors'
exit 0
fi
awk -f - $LOGS <<EOF
BEGIN { c["LogWarning"]=0; c["LogNotice"]=0; c["LogFatal"]=0; c["LogFile"]=0; }
/PHP Warning/{ c["LogWarning"]++ }
/PHP Notice/{ c["LogNotice"]++ }
/PHP Fatal error/{ c["LogFatal"]++ }
/File does not exist/{ c["LogFile"]++ }
END{ for(i in c) { print i".value " c[i] } }
EOF

View file

@ -10,23 +10,23 @@ Inspirated by php5-fpm_status plugin by Daniel Caillibaud
=head1 APPLICABLE SYSTEMS
Any php-fpm host
You will need the perl fastcgi::client on your host
Any php-fpm host
You will need the perl fastcgi::client on your host
=head1 CONFIGURATION
You have to put this in your plugin.conf.d folder
You have to put this in your plugin.conf.d folder
# If your php process is listening on TCP
# If your php process is listening on TCP
[php_fpm_process]
env.serveraddr 127.0.0.1
env.port 9000
env.path /status
env.path /status
# If your php process is listening on Unix Socket
[php_fpm_process]
env.sock /var/run/php5-fpm.sock
env.path /status
env.path /status
=head1 MAGIC MARKERS
@ -35,11 +35,11 @@ You have to put this in your plugin.conf.d folder
=head1 VERSION
v1.0
v1.0
=head1 AUTHOR
Minitux
Minitux
=head1 LICENSE
@ -47,6 +47,7 @@ GNU General Public License, version 3
=cut
use File::Basename;
use FCGI::Client;
my $ish = 1;
@ -55,6 +56,8 @@ my $body = "";
my $IDLE = 0;
my $ACTIVE = 0;
my $TOTAL = 0;
my $SLOW_REQUESTS = 0;
my $PLUGIN_NAME = basename($0);
my $SERVERADDR = $ENV{'serveraddr'} || "127.0.0.1";
my $PORT = $ENV{'port'} || "9000";
@ -68,7 +71,7 @@ if ($UNIX_SOCK) {
$sock = IO::Socket::UNIX->new(
Peer => $UNIX_SOCK,
);
if (!$sock) {
if (!$sock) {
print "Server maybe down, unabled to connect to $UNIX_SOCK";
exit 2;
}
@ -78,7 +81,7 @@ if ($UNIX_SOCK) {
PeerAddr => $SERVERADDR,
PeerPort => $PORT,
);
if (!$sock) {
if (!$sock) {
print "Server maybe down, unabled to connect to $SERVERADDR:$PORT";
exit 2;
}
@ -86,7 +89,7 @@ if ($UNIX_SOCK) {
my $client = FCGI::Client::Connection->new( sock => $sock );
my ( $stdout, $stderr, $appstatus ) = $client->request(
my ( $stdout, $stderr, $appstatus ) = $client->request(
+{
REQUEST_METHOD => 'GET',
SCRIPT_FILENAME => '',
@ -112,33 +115,53 @@ while($stdout =~ /([^\n]*)\n?/g) {
if ( defined $ARGV[0] and $ARGV[0] eq "config" )
{
if($body =~ m/pool:\s+(.*?)\n/) {
$pool = $1;
}
print "graph_title php5-fpm status $pool\n";
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel Processes\n";
print "graph_scale yes\n";
print "graph_category php-fpm\n";
print "graph_info This graph shows the php5-fpm process manager status from pool: $pool\n";
print "active.label Active processes\n";
print "active.type GAUGE\n";
print "active.draw AREA\n";
print "active.info The number of active processes\n";
print "idle.label Idle processes\n";
print "idle.type GAUGE\n";
print "idle.draw STACK\n";
print "idle.info The number of idle processes\n";
print "total.label Total processes\n";
print "total.type GAUGE\n";
print "total.draw LINE2\n";
print "total.info The number of idle + active processes\n";
exit 0
}
print <<"EOF";
multigraph ${PLUGIN_NAME}_process
graph_title php5-fpm processes for $pool
graph_args --base 1000 -l 0
graph_vlabel Processes
graph_scale yes
graph_category php-fpm
graph_info This graph shows the php5-fpm process manager status from pool: $pool
active.label Active processes
active.type GAUGE
active.draw AREA
active.info The number of active processes
idle.label Idle processes
idle.type GAUGE
idle.draw STACK
idle.info The number of idle processes
total.label Total processes
total.type GAUGE
total.draw LINE2
total.info The number of idle + active processes
print $body;
multigraph ${PLUGIN_NAME}_slowrequests
graph_title php5-fpm slow requests $pool
graph_args --base 1000 -l 0
graph_vlabel Slow requests
graph_scale yes
graph_category php-fpm
graph_info This graph shows the php5-fpm slow request from pool: $pool
slow_requests.label Slow requests
slow_requests.type DERIVE
slow_requests.draw LINE2
slow_requests.min 0
slow_requests.info evolution of slow requests
EOF
exit 0
}
# print $body;
print "multigraph ${PLUGIN_NAME}_process\n";
if($body =~ m/idle processes: (.*?)\n/) {
$IDLE = $1;
@ -152,3 +175,10 @@ if($body =~ m/total processes: (.*?)\n/) {
$TOTAL = $1;
print "total.value ".$TOTAL."\n";
}
if($body =~ m/slow requests: (.*?)\n/) {
$SLOW_REQUESTS = $1;
print "\n";
print "multigraph ${PLUGIN_NAME}_slowrequests\n";
print "slow_requests.value ".$SLOW_REQUESTS."\n";
}

View file

@ -114,6 +114,12 @@ maildrop.label maildrop
incoming.label incoming
corrupt.label corrupt
hold.label held
active.draw AREA
deferred.draw STACK
maildrop.draw STACK
incoming.draw STACK
corrupt.draw STACK
hold.draw STACK
EOF
for field in active deferred maildrop incoming corrupt hold; do
print_warning $field

View file

@ -67,9 +67,6 @@ if (exists $ARGV[0]) {
my (undef, undef, $dbname) = split (/_/, $0, 3);
die "No dbname configured (did you make the proper symlink?)" unless $dbname;
my @datasources = DBI->data_sources ('Pg')
or die ("Can't read any possible data sources: $?");
my $dsn = "DBI:Pg:dbname=$dbname";
$dsn .= ";host=$dbhost" if $dbhost;
print "#$dsn\n" if $debug;

View file

@ -25,7 +25,7 @@ import os
import telnetlib
import re
def main():
def main():
try:
mode = sys.argv[1]
except IndexError:
@ -33,7 +33,7 @@ def main():
wildcard = sys.argv[0].split("prosody_")[1].split("_")[0]
host = os.environ.get('host', 'localhost')
port = int(os.environ.get('port', 5582))
if mode == "suggest":
print "c2s"
print "s2s"
@ -47,7 +47,7 @@ def main():
print "graph_title Prosody C2S Connections"
print "graph_vlabel users"
print "graph_category Prosody"
print "all_client_connections.label client connections"
print "secure_client_connections.label secure client connections"
print "insecure_client_connections.label insecure client " \
@ -64,7 +64,7 @@ def main():
secure_client_connections = int(parsed_info[0])
print "secure_client_connections.value %s" % \
(secure_client_connections)
telnet.write("c2s:show_insecure()\n")
telnet_response = telnet.read_until("insecure client connections",
5)
@ -75,19 +75,19 @@ def main():
all_client_connections = secure_client_connections + \
insecure_client_connections
print "all_client_connections.value %s" % (all_client_connections)
telnet.write("quit")
telnet.write("quit\n")
elif wildcard == "s2s":
if mode == "config":
print "graph_title Prosody S2S Connections"
print "graph_vlabel servers"
print "graph_category Prosody"
print "outgoing_connections.label outgoing connections"
print "incoming_connections.label incoming connections"
sys.exit(0)
else:
else:
server_connections_re = re.compile(r"(\d+) outgoing, (\d+)")
telnet = telnetlib.Telnet(host, port)
telnet.write("s2s:show()\n")
@ -95,8 +95,8 @@ def main():
parsed_info = server_connections_re.findall(telnet_response)
print "outgoing_connections.value %s" % (parsed_info[0][0])
print "incoming_connections.value %s" % (parsed_info[0][1])
telnet.write("quit")
telnet.write("quit\n")
elif wildcard == "presence":
if mode == "config":
print "graph_title Prosody Client Presence"
@ -110,8 +110,8 @@ def main():
print "dnd.label Do Not Disturb Clients"
sys.exit(0)
else:
client_presence_re = re.compile(r"- (.*?)\(\d+\)")
else:
client_presence_re = re.compile(r"[-\]] (.*?)\(\d+\)")
telnet = telnetlib.Telnet(host, port)
telnet.write("c2s:show()\n")
telnet_response = telnet.read_until("clients", 5)
@ -121,7 +121,7 @@ def main():
print "away.value %s" % (parsed_info.count("away"))
print "xa.value %s" % (parsed_info.count("xa"))
print "dnd.value %s" % (parsed_info.count("dnd"))
telnet.write("quit")
telnet.write("quit\n")
elif wildcard == "uptime":
if mode == "config":
@ -147,7 +147,7 @@ def main():
uptime_value = float(parsed_info[0]) + float(parsed_info[1])/24 +\
float(parsed_info[2])/60/24
print "uptime.value %s" % (uptime_value)
telnet.write("quit")
telnet.write("quit\n")
elif wildcard == "users":
if mode == "config":

View file

@ -35,9 +35,11 @@
use strict;
use IO::Socket::INET;
use IO::Socket::UNIX;
use Switch;
my $HOST = exists $ENV{'host'} ? $ENV{'host'} : "127.0.0.1";
my $UNIX_SOCKET = exists $ENV{'unixsocket'} ? $ENV{'unixsocket'} : ''; # path to Redis Unix sock file
my $PORT = exists $ENV{'port'} ? $ENV{'port'} : 6379;
my $PASSWORD = exists $ENV{'password'} ? $ENV{'password'} : undef;
my $TITLE_PREFIX = exists $ENV{'title_prefix'} ? $ENV{'title_prefix'} . ": " : "";
@ -208,12 +210,26 @@ switch ($0) {
close ($sock);
sub get_conn {
my $sock = IO::Socket::INET->new(
PeerAddr => $HOST,
PeerPort => $PORT,
Timeout => 10,
Proto => 'tcp'
);
my $sock;
if( $UNIX_SOCKET && -S $UNIX_SOCKET ){
$sock = IO::Socket::UNIX->new(
Type => SOCK_STREAM(),
Peer => $UNIX_SOCKET,
);
}else{
$sock = IO::Socket::INET->new(
PeerAddr => $HOST,
PeerPort => $PORT,
Timeout => 10,
Proto => 'tcp'
);
}
if ( defined( $PASSWORD ) ) {
print $sock "AUTH ", $PASSWORD, "\r\n";
my $result = <$sock> || die "can't read socket: $!";

68
plugins/sensors/battery_ Executable file
View file

@ -0,0 +1,68 @@
#! /bin/sh
# Plugin to monitor the battery status via the uevent API
#
# (c) 2015 - GPLv2 - steve.schnepp@pwkf.org
#
# It is a wildcard plugin, symlink it with the battery directory
# default is to display charge as mAh, but you can also use percentage if you
# prefer, by setting the env var "percent" to "yes".
#
# [battery_*]
# env.percent no
#
battery_name=${0##*_}
percent=${percent:-"no"}
if [ "$1" = "config" ]
then
echo "graph_title Battery $battery_name"
if [ "$percent" = "yes" ]
then
echo "graph_vlabel %"
else
echo "graph_vlabel mAh"
fi
echo "charge_design.label Design charge"
echo "charge_design.draw AREA"
[ "$percent" = "yes" ] && echo "charge_design.cdef charge_design,charge_design,/,100,*"
echo "charge_full.label Full charge"
echo "charge_full.draw AREA"
[ "$percent" = "yes" ] && echo "charge_full.cdef charge_full,charge_design,/,100,*"
echo "charge_now.label Current charge"
echo "charge_now.draw AREA"
[ "$percent" = "yes" ] && echo "charge_now.cdef charge_now,charge_design,/,100,*"
exit 0
fi
# Crudely read all the vars into the current namespace
. /sys/class/power_supply/$battery_name/uevent
echo "charge_design.value $(( $POWER_SUPPLY_CHARGE_FULL_DESIGN / 1000 )) "
echo "charge_full.value $(( $POWER_SUPPLY_CHARGE_FULL / 1000 ))"
echo "charge_now.value $(( $POWER_SUPPLY_CHARGE_NOW / 1000 ))"
exit 0
:<< DATA
cat /sys/class/power_supply/$1/uevent
POWER_SUPPLY_NAME=CMB1
POWER_SUPPLY_STATUS=Charging
POWER_SUPPLY_PRESENT=1
POWER_SUPPLY_TECHNOLOGY=Li-ion
POWER_SUPPLY_CYCLE_COUNT=0
POWER_SUPPLY_VOLTAGE_MIN_DESIGN=10800000
POWER_SUPPLY_VOLTAGE_NOW=11418000
POWER_SUPPLY_CURRENT_NOW=2668000
POWER_SUPPLY_CHARGE_FULL_DESIGN=5200000
POWER_SUPPLY_CHARGE_FULL=5000000
POWER_SUPPLY_CHARGE_NOW=100000
POWER_SUPPLY_CAPACITY=2
POWER_SUPPLY_CAPACITY_LEVEL=Normal
POWER_SUPPLY_MODEL_NAME=CP293570
POWER_SUPPLY_MANUFACTURER=Fujitsu
DATA

View file

@ -0,0 +1,90 @@
#!/usr/bin/perl -w
# -*- perl -*-
# vim: ft=perl
=head1 NAME
snmp__cisco_sbs_cpu - Munin plugin to monitor CPU Usage on Cisco Small Business Switches.
=head1 APPLICABLE SYSTEMS
Cisco Small Business Switches (SBXXXX devices)
=head1 CONFIGURATION
As a rule SNMP plugins need site specific configuration. The default
configuration (shown here) will only work on insecure sites/devices.
[snmp_*]
env.version 2
env.community public
In general SNMP is not very secure at all unless you use SNMP version
3 which supports authentication and privacy (encryption). But in any
case the community string for your devices should not be "public".
Please see 'perldoc Munin::Plugin::SNMP' for further configuration
information.
=head1 INTERPRETATION
CPU Percentage gives an idea of utilization of the device. High CPU
can indicate a configuration problem or overutilization of the device.
=head1 MAGIC MARKERS
#%# family=snmpauto
#%# capabilities=snmpconf
=head1 VERSION
$Id$
=head1 BUGS
None known.
=head1 AUTHOR
Copyright (C) 2015 James DeVincentis
=head1 LICENSE
GPLv3.
=cut
use strict;
use Munin::Plugin::SNMP;
if (defined $ARGV[0] and $ARGV[0] eq 'snmpconf') {
print "require 1.3.6.1.4.1.9.6.1.101.1.7.0 [0-9]\n";
exit 0;
}
if (defined $ARGV[0] and $ARGV[0] eq "config") {
my ($host) = Munin::Plugin::SNMP->config_session();
print "host_name $host\n" unless $host eq 'localhost';
print <<"EOF";
graph_title CPU Utilization
graph_args --base 1000 -l 0 -u 100
graph_vlabel CPU %
graph_category system
graph_info This graph shows the percentage of CPU used at different intervals. High CPU Utilization can indicate a configuration problem or overutilization of the device.
load5sec.label 5s
load5sec.info 5 Second CPU Utilization Average
load5sec.draw LINE1
load1min.label 1m
load1min.info 1 Minute CPU Utilization Average
load1min.draw LINE1
load5min.label 5m
load5min.info 5 Minute CPU Utilization Average
EOF
exit 0;
}
my $session = Munin::Plugin::SNMP->session();
print "load5sec.value ", $session->get_single('1.3.6.1.4.1.9.6.1.101.1.7.0'), "\n";
print "load1min.value ", $session->get_single('1.3.6.1.4.1.9.6.1.101.1.8.0'), "\n";
print "load5min.value ", $session->get_single('1.3.6.1.4.1.9.6.1.101.1.9.0'), "\n";

View file

@ -0,0 +1,109 @@
#!/usr/bin/perl -w
# -*- perl -*-
# vim: ft=perl
=head1 NAME
snmp__syno_hddtemp - Munin plugin to monitor the temperature of
harddisks in an Synology NAS.
=head1 APPLICABLE SYSTEMS
Any Synology NAS device which provides the synoDisk MIB.
=head1 CONFIGURATION
As a rule SNMP plugins need site specific configuration. The default
configuration (shown here) will only work on insecure sites/devices.
[snmp_*]
env.version 2
env.community public
In general SNMP is not very secure at all unless you use SNMP version
3 which supports authentication and privacy (encryption). But in any
case the community string for your devices should not be "public".
Please see 'perldoc Munin::Plugin::SNMP' for further configuration
information.
=head1 INTERPRETATION
The temperature of each disk installed in °C.
=head1 MIB INFORMATION
This plugin requires support for the synoDisk. It reports
the temperature of the installed disks.
=head1 MAGIC MARKERS
#%# family=snmpauto
#%# capabilities=snmpconf
=head1 VERSION
$Id$
=head1 BUGS
None known.
=head1 AUTHOR
Copyright (C) 2015 Thomas Arthofer
This plugin was derived from snmp__netstat by Lars Strand with updates
by Matthew Boyle.
=head1 LICENSE
GPLv2.
=cut
use strict;
use Munin::Plugin::SNMP;
my $oid_drives = '1.3.6.1.4.1.6574.2.1.1';
if (defined $ARGV[0] and $ARGV[0] eq 'snmpconf') {
print "require ${oid_drives}. [0-9]\n";
exit 0;
}
my ($session, $error) = Munin::Plugin::SNMP->session();
my $table = $session->get_hash(
-baseoid => $oid_drives, # IF-MIB
-cols => {
2 => 'name',
3 => 'type',
6 => 'temp',
}
);
if (defined $ARGV[0] and $ARGV[0] eq 'config') {
my ($host) = Munin::Plugin::SNMP->config_session();
print "host_name $host\n" unless $host eq 'localhost';
print "graph_title HDD temperature\n";
print "graph_category sensors\n";
print "graph_vlabel Degrees Celsius\n";
print "graph_info This graph shows the temperature of all HDDs in the Diskstation.\n";
foreach my $key ( sort keys %$table )
{
print "temp$key.label $table->{$key}->{'name'}\n";
print "temp$key.info Temperature of $table->{$key}->{'name'} ($table->{$key}->{'type'})\n";
}
exit 0;
}
my $names = $session->get_entries(-columns => [ $oid_drives ]);
foreach my $key ( sort keys %$table )
{
print "temp$key.value $table->{$key}->{'temp'}\n";
}

View file

@ -0,0 +1,91 @@
#!/usr/bin/perl -w
# -*- cperl -*-
# vim: ft=perl
=head1 NAME
snmp__syno_temperature - Munin plugin to retrieve current temperature from a
Synology NAS.
=head1 APPLICABLE SYSTEMS
Any Synology NAS device which provides the synoSystem MIB.
=head1 CONFIGURATION
As a rule SNMP plugins need site specific configuration. The default
configuration (shown here) will only work on insecure sites/devices.
[snmp_*]
env.version 2
env.community public
In general SNMP is not very secure at all unless you use SNMP version
3 which supports authentication and privacy (encryption). But in any
case the community string for your devices should not be "public".
Please see 'perldoc Munin::Plugin::SNMP' for further configuration
information.
=head1 INTERPRETATION
This plugin queries the current temperature of the NAS.
=head1 MIB INFORMATION
This plugin requires support for the synoSystem MIB by Synology.
It reports the contents of the temperature OID.
=head1 MAGIC MARKERS
#%# family=snmpauto
#%# capabilities=snmpconf
=head1 VERSION
$Id$
=head1 BUGS
None known.
=head1 AUTHOR
Copyright (C) 2015 Thomas Arthofer
=head1 LICENSE
GPLv2 or (at your option) any later version.
=cut
use strict;
use Munin::Plugin::SNMP;
if (defined $ARGV[0] and $ARGV[0] eq "snmpconf") {
print "require 1.3.6.1.4.1.6574.1.2.0 [0-9]\n"; # Number
exit 0;
}
if (defined $ARGV[0] and $ARGV[0] eq "config") {
my ($host) = Munin::Plugin::SNMP->config_session();
print "host_name $host\n" unless $host eq 'localhost';
print "graph_title Temperatures
graph_args --base 1000 -l 0
graph_vlabel Degrees Celsius
graph_category sensors
graph_info This graph shows the temperature of the diskstation.
temp.label CPU
temp.info The temperature of the onboard CPU.
";
exit 0;
}
my $session = Munin::Plugin::SNMP->session(-translate =>
[ -timeticks => 0x0 ]);
my $temp = $session->get_single (".1.3.6.1.4.1.6574.1.2.0") || 'ERROR';
print "Retrived uptime is '$temp'\n" if $Munin::Plugin::SNMP::DEBUG;
print "temp.value ", $temp, "\n";

View file

@ -0,0 +1,102 @@
#!/usr/bin/perl -w
# -*- cperl -*-
# vim: ft=perl
=head1 NAME
snmp__syno_ups - Munin plugin to retrieve various information of the
UPS attached to a Synology NAS.
=head1 APPLICABLE SYSTEMS
Any Synology NAS device which provides the synoUPS MIB.
=head1 CONFIGURATION
As a rule SNMP plugins need site specific configuration. The default
configuration (shown here) will only work on insecure sites/devices.
[snmp_*]
env.version 2
env.community public
In general SNMP is not very secure at all unless you use SNMP version
3 which supports authentication and privacy (encryption). But in any
case the community string for your devices should not be "public".
Please see 'perldoc Munin::Plugin::SNMP' for further configuration
information.
=head1 INTERPRETATION
The plugin reports the following stats about the UPS attached:
- Load in %
- Charge in %
=head1 MIB INFORMATION
This plugin requires support for the synoUPS MIB by Synology.
=head1 MAGIC MARKERS
#%# family=snmpauto
#%# capabilities=snmpconf
=head1 VERSION
$Id$
=head1 BUGS
None known.
=head1 AUTHOR
Copyright (C) 2015 Thomas Arthofer
=head1 LICENSE
GPLv2 or (at your option) any later version.
=cut
use strict;
use Munin::Plugin::SNMP;
if (defined $ARGV[0] and $ARGV[0] eq "snmpconf") {
print "require 1.3.6.1.4.1.6574.4.3.1.1.0 [0-9]\n"; # Charge
print "require 1.3.6.1.4.1.6574.4.2.12.1.0 [0-9]\n"; # Load
exit 0;
}
if (defined $ARGV[0] and $ARGV[0] eq "config") {
my ($host) = Munin::Plugin::SNMP->config_session();
print "host_name $host\n" unless $host eq 'localhost';
print "graph_title UPS
graph_args --base 1000 -l 0
graph_vlabel Status of UPS
graph_category system
graph_info This graph shows the status of the attached UPS.
charge.label Charge
charge.info Charge status of battery.
charge.draw LINE2
load.label Load
load.info Load on the UPS
";
exit 0;
}
my $session = Munin::Plugin::SNMP->session(-translate =>
[ -timeticks => 0x0 ]);
my $charge = $session->get_single (".1.3.6.1.4.1.6574.4.3.1.1.0") || 'ERROR';
$charge = unpack "f", reverse pack "H*", $charge;
my $load = $session->get_single (".1.3.6.1.4.1.6574.4.2.12.1.0") || 'ERROR';
$load = unpack "f", reverse pack "H*", $load;
print "Retrived charge '$charge'\n" if $Munin::Plugin::SNMP::DEBUG;
print "Retrived load '$load'\n" if $Munin::Plugin::SNMP::DEBUG;
print "charge.value ", $charge, "\n";
print "load.value ", $load, "\n";

182
plugins/streaming/icecast2_stats_ Executable file
View file

@ -0,0 +1,182 @@
#!/usr/bin/python3
#
# This plugin shows the statistics of every source currently connected to the Icecast2 server.
# See the Icecast2_ plugin for collecting data of specific mountpoints.
#
# An icecast server v2.4 or later is required for this module since it uses the status-json.xsl
# output (see http://www.icecast.org/docs/icecast-2.4.1/server-stats.html).
#
# The following data for each source is available:
# * listeners: current count of listeners
# * duration: the age of the stream/source
#
# Additionally the Icecast service uptime is available.
#
# This plugin requires Python 3 (e.g. for urllib instead of urllib2).
#
#
# Environment variables:
# * status_url: defaults to "http://localhost:8000/status-json.xsl"
#
#
# Copyright (C) 2015 Lars Kruse <devel@sumpfralle.de>
#
# 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/>.
#
#
# Magic markers
#%# capabilities=autoconf suggest
#%# family=auto
import datetime
import json
import os
import urllib.request
import sys
status_url = os.getenv("status_url", "http://localhost:8000/status-json.xsl")
PLUGIN_SCOPES = ("sources_listeners", "sources_duration", "service_uptime")
PLUGIN_NAME_PREFIX = "icecast2_stats_"
def clean_fieldname(name):
""" see http://munin-monitoring.org/wiki/notes_on_datasource_names
This function is a bit clumsy as it tries to avoid using a regular
expression for the sake of micropython compatibility.
"""
def get_valid(char, position):
if char == '_':
return '_'
elif 'a' <= char.lower() <= 'z':
return char
elif (position > 0) and ('0' <= char <= '9'):
return char
else:
return '_'
return "".join([get_valid(char, position) for position, char in enumerate(name)])
def parse_iso8601(datestring):
""" try to avoid using an external library for parsing an ISO8601 date string """
if datestring.endswith("Z"):
timestamp_string = datestring[:-1]
time_delta = datetime.timedelta(minutes=0)
else:
# the "offset_text" is something like "+0500" or "-0130"
timestamp_string, offset_text = datestring[:-5], datestring[-5:]
offset_minutes = int(offset_text[1:3]) * 60 + int(offset_text[3:])
if offset_text.startswith("+"):
pass
elif offset_text.startswith("-"):
offset_minutes *= -1
else:
# invalid format
return None
time_delta = datetime.timedelta(minutes=offset_minutes)
local_time = datetime.datetime.strptime(timestamp_string, "%Y-%m-%dT%H:%M:%S")
return local_time + time_delta
def get_iso8601_age_days(datestring):
now = datetime.datetime.now()
timestamp = parse_iso8601(datestring)
if timestamp:
return (now - timestamp).total_seconds() / (24 * 60 * 60)
else:
return None
def _get_json_statistics():
with urllib.request.urlopen(status_url) as conn:
json_body = conn.read()
return json.loads(json_body.decode("utf-8"))
def get_sources():
sources = []
for source in _get_json_statistics()["icestats"]["source"]:
path_name = source["listenurl"].split("/")[-1]
sources.append({"name": path_name,
"fieldname": clean_fieldname(path_name),
"listeners": source["listeners"],
"duration_days": get_iso8601_age_days(source["stream_start_iso8601"])})
sources.sort(key=lambda item: item["name"])
return sources
def get_server_uptime_days():
return get_iso8601_age_days(_get_json_statistics()["icestats"]["server_start_iso8601"])
def get_scope():
called_name = os.path.basename(sys.argv[0])
if called_name.startswith(PLUGIN_NAME_PREFIX):
scope = called_name[len(PLUGIN_NAME_PREFIX):]
if not scope in PLUGIN_SCOPES:
print("Invalid scope requested: {0} (expected: {1})".format(scope, "/".join(PLUGIN_SCOPES)), file=sys.stderr)
sys.exit(2)
else:
print("Invalid filename - failed to discover plugin scope", file=sys.stderr)
sys.exit(2)
return scope
if __name__ == "__main__":
action = sys.argv[1] if (len(sys.argv) > 1) else None
if action == "autoconf":
try:
get_sources()
print("yes")
except OSError:
print("no")
elif action == "suggest":
for scope in PLUGIN_SCOPES:
print(scope)
elif action == "config":
scope = get_scope()
if scope == "sources_listeners":
print("graph_title Total number of listeners")
print("graph_vlabel listeners")
print("graph_category Icecast")
for index, source in enumerate(get_sources()):
print("{0}.label {1}".format(source["fieldname"], source["name"]))
print("{0}.draw {1}".format(source["fieldname"], ("AREA" if (index == 0) else "STACK")))
elif scope == "sources_duration":
print("graph_title Duration of sources")
print("graph_vlabel duration in days")
print("graph_category Icecast")
for source in get_sources():
print("{0}.label {1}".format(source["fieldname"], source["name"]))
elif scope == "service_uptime":
print("graph_title Icecast service uptime")
print("graph_vlabel uptime in days")
print("graph_category Icecast")
print("uptime.label service uptime")
elif action is None:
scope = get_scope()
if scope == "sources_listeners":
for source in get_sources():
print("{0}.value {1}".format(source["fieldname"], source["listeners"]))
elif scope == "sources_duration":
for source in get_sources():
print("{0}.value {1}".format(source["fieldname"], source["duration_days"] or 0))
elif scope == "service_uptime":
print("uptime.value {0}".format(get_server_uptime_days()))
else:
print("Invalid argument given: {0}".format(action), file=sys.stderr)
sys.exit(1)
sys.exit(0)

View file

@ -0,0 +1,273 @@
/*
* if1sec C plugin
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <inttypes.h>
#include <fcntl.h>
#include <time.h>
#include <sys/file.h>
#define PROC_STAT "/proc/net/dev"
#define PLUGIN_NAME "if1sec-c"
int fail(char* msg) {
perror(msg);
return 1;
}
/* Returns the ifname from a /proc/net/dev line
* It will return an inside pointer to line, and modifiy the end with a \0
*/
char* get_ifname_from_procstatline(char* line) {
char *ifname;
for (ifname = line; (*ifname) == ' '; ifname ++);
char *ifname_end;
for (ifname_end = ifname; (*ifname_end) != ':'; ifname_end ++);
(*ifname_end) = '\0';
return ifname;
}
int config() {
/* Get the number of if */
int f;
if ( !(f=open(PROC_STAT, O_RDONLY)) ) {
return fail("cannot open " PROC_STAT);
}
// Starting with -2, since the 2 lines on top are header lines
int nif = -2;
const int buffer_size = 64 * 1024;
char buffer[buffer_size];
// whole /proc/stat can be read in 1 syscall
if (read(f, buffer, buffer_size) <= 0) {
return fail("cannot read " PROC_STAT);
}
// tokenization per-line
char* line; char *saveptr;
char* newl = "\n";
for (line = strtok_r(buffer, newl, &saveptr); line; line = strtok_r(NULL, newl, &saveptr)) {
// Skip the header lines
if (nif ++ < 0) { continue; }
char* if_name = get_ifname_from_procstatline(line);
printf(
"multigraph if_%s_1sec" "\n"
"graph_order down up" "\n"
"graph_title %s traffic" "\n"
"graph_category system::1sec" "\n"
"graph_vlabel bits in (-) / out (+) per ${graph_period}" "\n"
"graph_data_size custom 1d, 10s for 1w, 1m for 1t, 5m for 1y" "\n"
, if_name, if_name
);
printf(
"down.label -" "\n"
"down.type DERIVE" "\n"
"down.graph no" "\n"
"down.cdef down,8,*" "\n"
"down.min 0" "\n"
"up.label bps" "\n"
"up.type DERIVE" "\n"
"up.negative down" "\n"
"up.cdef down,8,*" "\n"
"up.min 0" "\n"
);
}
close(f);
return 0;
}
char* pid_filename;
char* cache_filename;
/* Wait until the next second, and return the EPOCH */
time_t wait_until_next_second() {
struct timespec tp;
clock_gettime(CLOCK_REALTIME, &tp);
time_t current_epoch = tp.tv_sec;
long nsec_to_sleep = 1000*1000*1000 - tp.tv_nsec;
/* Only sleep if needed */
if (nsec_to_sleep > 0) {
tp.tv_sec = 0;
tp.tv_nsec = nsec_to_sleep;
nanosleep(&tp, NULL);
}
return current_epoch + 1;
}
int acquire() {
/* fork ourselves if not asked otherwise */
char* no_fork = getenv("no_fork");
if (! no_fork || strcmp("1", no_fork)) {
if (fork()) return;
// we are the child, complete the daemonization
/* Close standard IO */
fclose(stdin);
fclose(stdout);
fclose(stderr);
/* create new session and process group */
setsid();
}
/* write the pid */
FILE* pid_file = fopen(pid_filename, "w");
fprintf(pid_file, "%d\n", getpid());
fclose(pid_file);
/* Reading /proc/stat */
int f = open(PROC_STAT, O_RDONLY);
/* open the spoolfile */
int cache_file = open(cache_filename, O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IWUSR);
/* loop each second */
while (1) {
/* wait until next second */
time_t epoch = wait_until_next_second();
const int buffer_size = 64 * 1024;
char buffer[buffer_size];
if (lseek(f, 0, SEEK_SET) < 0) {
return fail("cannot seek " PROC_STAT);
}
// whole PROC file can be read in 1 syscall
if (read(f, buffer, buffer_size) <= 0) {
return fail("cannot read " PROC_STAT);
}
// ignore the 1rst line
char* line; char *saveptr;
const char* newl = "\n";
/* lock */
flock(cache_file, LOCK_EX);
int nif = -2;
for (line = strtok_r(buffer, newl, &saveptr); line; line = strtok_r(NULL, newl, &saveptr)) {
// Skip the header lines
if (nif ++ < 0) { continue; }
char if_id[64];
uint_fast64_t r_bytes, r_packets, r_errs, r_drop, r_fifo, r_frame, r_compressed, r_multicast;
uint_fast64_t t_bytes, t_packets, t_errs, t_drop, t_fifo, t_frame, t_compressed, t_multicast;
sscanf(line, "%s"
" "
"%llu %llu %llu %llu %llu %llu %llu %llu"
" "
"%llu %llu %llu %llu %llu %llu %llu %llu"
, if_id
, &r_bytes, &r_packets, &r_errs, &r_drop, &r_fifo, &r_frame, &r_compressed, &r_multicast
, &t_bytes, &t_packets, &t_errs, &t_drop, &t_fifo, &t_frame, &t_compressed, &t_multicast
);
// Remove trailing ':' of if_id
if_id[strlen(if_id) - 1] = '\0';
char out_buffer[1024];
sprintf(out_buffer,
"multigraph if_%s_1sec" "\n"
"up.value %ld:%llu" "\n"
"down.value %ld:%llu" "\n"
, if_id
, epoch, r_bytes
, epoch, t_bytes
);
write(cache_file, out_buffer, strlen(out_buffer));
}
/* unlock */
flock(cache_file, LOCK_UN);
}
close(cache_file);
close(f);
return 0;
}
int fetch() {
FILE* cache_file = fopen(cache_filename, "r+");
/* lock */
flock(fileno(cache_file), LOCK_EX);
/* cat the cache_file to stdout */
char buffer[1024];
while (fgets(buffer, 1024, cache_file)) {
printf("%s", buffer);
}
ftruncate(fileno(cache_file), 0);
fclose(cache_file);
return 0;
}
int main(int argc, char **argv) {
/* resolve paths */
char *MUNIN_PLUGSTATE = getenv("MUNIN_PLUGSTATE");
/* Default is current directory */
if (! MUNIN_PLUGSTATE) MUNIN_PLUGSTATE = ".";
size_t MUNIN_PLUGSTATE_length = strlen(MUNIN_PLUGSTATE);
pid_filename = malloc(MUNIN_PLUGSTATE_length + strlen("/" PLUGIN_NAME ".") + strlen("pid") + 1); pid_filename[0] = '\0';
cache_filename = malloc(MUNIN_PLUGSTATE_length + strlen("/" PLUGIN_NAME ".") + strlen("value") + 1); cache_filename[0] = '\0';
strcat(pid_filename, MUNIN_PLUGSTATE);
strcat(pid_filename, "/" PLUGIN_NAME "." "pid");
strcat(cache_filename, MUNIN_PLUGSTATE);
strcat(cache_filename, "/" PLUGIN_NAME "." "value");
if (argc > 1) {
char* first_arg = argv[1];
if (! strcmp(first_arg, "config")) {
return config();
}
if (! strcmp(first_arg, "acquire")) {
return acquire();
}
}
return fetch();
}
/***** DEMO
/proc/net/dev sample
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 4364 54 0 0 0 0 0 0 4364 54 0 0 0 0 0 0
eth0: 3459461624 22016512 0 70 0 0 0 0 3670486138 18117144 0 0 0 0 0 0
*****/

View file

@ -0,0 +1,4 @@
/multicpu1sec-c
/multicpu1sec.o
/multicpu1sec.pid
/multicpu1sec.value

View file

@ -5,6 +5,7 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
@ -20,23 +21,30 @@ int fail(char* msg) {
int config() {
/* Get the number of CPU */
FILE* f;
if ( !(f=fopen(PROC_STAT, "r")) ) {
int f;
if ( !(f=open(PROC_STAT, O_RDONLY)) ) {
return fail("cannot open " PROC_STAT);
}
// Starting with -1, since the first line is the "global cpu line"
int ncpu = -1;
while (! feof(f)) {
char buffer[1024];
if (fgets(buffer, 1024, f) == 0) {
break;
}
if (! strncmp(buffer, "cpu", 3)) ncpu ++;
const int buffer_size = 64 * 1024;
char buffer[buffer_size];
// whole /proc/stat can be read in 1 syscall
if (read(f, buffer, buffer_size) <= 0) {
return fail("cannot read " PROC_STAT);
}
fclose(f);
// tokenization per-line
char* line;
char* newl = "\n";
for (line = strtok(buffer, newl); line; line = strtok(NULL, newl)) {
if (! strncmp(line, "cpu", 3)) ncpu ++;
}
close(f);
printf(
"graph_title multicpu1sec\n"
@ -104,43 +112,62 @@ int acquire() {
fprintf(pid_file, "%d\n", getpid());
fclose(pid_file);
/* Reading /proc/stat */
int f = open(PROC_STAT, O_RDONLY);
/* open the spoolfile */
int cache_file = open(cache_filename, O_CREAT | O_APPEND | O_WRONLY);
/* loop each second */
while (1) {
/* wait until next second */
time_t epoch = wait_until_next_second();
/* Reading /proc/stat */
FILE* f = fopen(PROC_STAT, "r");
// Read and ignore the 1rst line
char buffer[1024];
fgets(buffer, 1024, f);
/* open the spoolfile */
FILE* cache_file = fopen(cache_filename, "a");
const int buffer_size = 64 * 1024;
char buffer[buffer_size];
if (lseek(f, 0, SEEK_SET) < 0) {
return fail("cannot seek " PROC_STAT);
}
// whole /proc/stat can be read in 1 syscall
if (read(f, buffer, buffer_size) <= 0) {
return fail("cannot read " PROC_STAT);
}
// ignore the 1rst line
char* line;
const char* newl = "\n";
line = strtok(buffer, newl);
/* lock */
flock(fileno(cache_file), LOCK_EX);
while (! feof(f)) {
if (fgets(buffer, 1024, f) == 0) {
// EOF
break;
}
flock(cache_file, LOCK_EX);
for (line = strtok(NULL, newl); line; line = strtok(NULL, newl)) {
// Not on CPU lines anymore
if (strncmp(buffer, "cpu", 3)) break;
if (strncmp(line, "cpu", 3)) break;
char cpu_id[64];
long usr, nice, sys, idle, iowait, irq, softirq;
sscanf(buffer, "%s %ld %ld %ld %ld %ld %ld %ld", cpu_id, &usr, &nice, &sys, &idle, &iowait, &irq, &softirq);
sscanf(line, "%s %ld %ld %ld %ld %ld %ld %ld", cpu_id, &usr, &nice, &sys, &idle, &iowait, &irq, &softirq);
long used = usr + nice + sys + iowait + irq + softirq;
fprintf(cache_file, "%s.value %ld:%ld\n", cpu_id, epoch, used);
char out_buffer[1024];
sprintf(out_buffer, "%s.value %ld:%ld\n", cpu_id, epoch, used);
write(cache_file, out_buffer, strlen(out_buffer));
}
fclose(cache_file);
fclose(f);
/* unlock */
flock(cache_file, LOCK_UN);
}
close(cache_file);
close(f);
return 0;
}
int fetch() {
@ -157,6 +184,8 @@ int fetch() {
ftruncate(fileno(cache_file), 0);
fclose(cache_file);
return 0;
}
int main(int argc, char **argv) {

View file

@ -30,6 +30,7 @@ fi
if [ "$1" = "config" ]; then
echo "graph_title NTP offset and delay to peer $PEER"
echo "graph_category time"
echo "graph_args --base 1000 --vertical-label msec"
echo "offset.label Offset"
echo "offset.draw LINE2"

View file

@ -1,33 +1,55 @@
#!/bin/sh
#
# (c) Andreas Kreisl
# (c) Andreas Kreisl extended by Tobias Schramm
#
# Link name will be used as title: apc_{$title}
#
# env.keys LOADPCT BCHARGE LINEV BATTV TIMELEFT
# env.unit % or Volt or Minutes
#
if [ -z "$keys" ]; then
keys="TIMELEFT"
keys="LINEV LOADPCT BCHARGE NUMXFERS TIMELEFT"
fi
apcinfo=`/sbin/apcaccess`
if [ "$1" = "config" ]; then
title=`basename $0 | sed 's/^apc_//g' | awk '{ sub(/^./,toupper(substr($0,1,1))); print; }'`
echo "graph_title APC Status - $title"
echo 'graph_args --base 1000 -l 0 '
echo "graph_vlabel $unit"
echo 'graph_category sensors'
echo 'multigraph apc_status'
echo "graph_title UPS Status - $title"
echo 'graph_args --base 1000'
echo 'graph_category hardware'
title=`/sbin/apcaccess | egrep "^MODEL" | awk '{print $3" "$4" "$5" "$6" "$7" "$8" "$9;}'`
echo "graph_info $title"
for key in $keys; do
echo "$key.label $key"
echo "$key.info Value of $key."
echo "$key.draw LINE2"
echo "$key.info Value of $key"
echo "$key.draw LINE1"
done
for key in $keys; do
key_lower=`echo "$key" | awk '{print tolower($0);}'`
unit=`echo "$apcinfo" | egrep "^$key" | awk '{print $4;}'`
echo "multigraph apc_status.$key_lower"
echo "graph_title $key"
echo 'graph_args --base 1000'
if [ -n "$unit" ]; then
echo "graph_vlabel $unit"
fi
echo 'graph_category hardware'
echo "$key.label $key"
echo "$key.info $key."
echo "$key.draw LINE1"
done
exit 0
fi
searchkey=`echo "$keys" | tr " " "\|"`
/sbin/apcaccess | egrep "$searchkey" | awk '{print $1".value "$3;}'
echo 'multigraph apc_status'
for key in $keys; do
echo "$apcinfo" | egrep "^$key" | awk '{print $1".value "$3;}'
done
for key in $keys; do
key_lower=`echo "$key" | awk '{print tolower($0)}'`
echo "multigraph apc_status.$key_lower"
echo "$apcinfo" | egrep "^$key" | awk '{print $1".value "$3;}'
done

View file

@ -19,9 +19,12 @@ your actual plugins directory.
In your plugins.conf add
```
[varnish4_*]
group varnish
env.varnishstat varnishstat
env.name
```
`group varnish` Since Varnish version 4.1, Varnish shared log utilities must be run in a context with *varnish* group membership.
`env.varnishstat` can be a full path to varnishstat if it's
not in the path already.

View file

@ -34,6 +34,7 @@ The plugin needs to be able to execute varnishstat.
The configuration section shows the defaults
[varnish4_*]
group varnish
env.varnishstat varnishstat
env.name
@ -232,7 +233,7 @@ my %ASPECTS = (
'order' => 'client_req cache_hit cache_miss '
. 'cache_hitpass' ,
'vlabel' => '%',
'args' => '-u 100 --rigid',
'args' => '-l 0 -u 100 --rigid',
'scale' => 'no',
'values' => {
'client_req' => {
@ -630,15 +631,15 @@ my %ASPECTS = (
},
'bans_tested' => {
'type' => 'DERIVE',
'min' => '0'
'min' => '0'
},
'bans_obj_killed' => {
'type' => 'DERIVE',
'min' => '0'
'min' => '0'
},
'bans_tests_tested' => {
'type' => 'DERIVE',
'min' => '0'
'min' => '0'
},
'bans_dups' => {
'type' => 'GAUGE'
@ -750,6 +751,7 @@ my %ASPECTS = (
},
'sess_pipe_overflow' => {
'type' => 'DERIVE'
}
}
},
@ -778,9 +780,9 @@ my %ASPECTS = (
sub translate_type
{
my $d = $_[0];
if ($d eq "i") {
if ($d eq "i" or $d eq "g") {
$d = "GAUGE";
} elsif ($d eq "a") {
} elsif ($d eq "a" or $d eq "c") {
$d = "DERIVE";
}
return $d;

View file

@ -68,14 +68,14 @@ def find_vm_names(pids):
result = {}
for pid in pids:
cmdline = open("/proc/%s/cmdline" % pid, "r")
result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-_]*)\x00\-.*$",r"\1", cmdline.readline()))
result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-_-]*)\x00\-.*$",r"\1", cmdline.readline()))
return result
def list_pids():
''' Find the pid of kvm processes
@return a list of pids from running kvm
'''
pid = Popen("pidof kvm", shell=True, stdout=PIPE)
pid = Popen("pidof qemu-system-x86_64", shell=True, stdout=PIPE)
return pid.communicate()[0].split()
def fetch(vms):

View file

@ -85,14 +85,14 @@ def find_vm_names(pids):
result = {}
for pid in pids:
cmdline = open("/proc/%s/cmdline" % pid, "r")
result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-_]*)\x00\-.*$",r"\1", cmdline.readline()))
result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-_-]*)\x00\-.*$",r"\1", cmdline.readline()))
return result
def list_pids():
''' Find the pid of kvm processes
@return a list of pids from running kvm
'''
pid = Popen("pidof kvm", shell=True, stdout=PIPE)
pid = Popen("pidof qemu-system-x86_64", shell=True, stdout=PIPE)
return pid.communicate()[0].split()
if __name__ == "__main__":

View file

@ -82,14 +82,14 @@ def find_vm_names(pids):
result = {}
for pid in pids:
cmdline = open("/proc/%s/cmdline" % pid, "r")
result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-_]*)\x00\-.*$",r"\1", cmdline.readline()))
result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-_-]*)\x00\-.*$",r"\1", cmdline.readline()))
return result
def list_pids():
''' Find the pid of kvm processes
@return a list of pids from running kvm
'''
pid = Popen("pidof kvm", shell=True, stdout=PIPE)
pid = Popen("pidof qemu-system-x86_64", shell=True, stdout=PIPE)
return pid.communicate()[0].split()
if __name__ == "__main__":

View file

@ -84,7 +84,7 @@ def find_vm_names(pids):
result = {}
for pid in pids:
cmdline = open("/proc/%s/cmdline" % pid, "r")
result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-_]*)\x00\-.*$",r"\1", cmdline.readline()))
result[pid] = clean_vm_name(re.sub(r"^.*-name\x00([a-zA-Z0-9.-_-]*)\x00\-.*$",r"\1", cmdline.readline()))
return result
def get_vm_mac(pid):
@ -100,7 +100,7 @@ def list_pids():
''' Find the pid of kvm processes
@return a list of pids from running kvm
'''
pid = Popen("pidof kvm", shell=True, stdout=PIPE)
pid = Popen("pidof qemu-system-x86_64", shell=True, stdout=PIPE)
return pid.communicate()[0].split()
def find_vms_tap():

View file

@ -13,6 +13,11 @@
# http://api.openweathermap.org/data/<api>/weather?<query_string>
#
## From Oct 9 2015 OpenWeather needs you to register and get an APIKEY
# include this key by setting 'env.apikey' in munin plugin config, i.e.:
# [openweather_*]
# env.apikey XYZ
query_string=$(printf '%s' "${0#*_}" | tr '_' '=')
TMPFILE=$(mktemp)
trap 'rm -f $TMPFILE' EXIT
@ -20,7 +25,7 @@ trap 'rm -f $TMPFILE' EXIT
# API returns temp in K, we have to convert it in C
KELVIN_BIAS=273
curl -s "http://api.openweathermap.org/data/2.5/weather?mode=xml&${query_string}" > $TMPFILE
curl -s "http://api.openweathermap.org/data/2.5/weather?mode=xml&${query_string}&APPID=${apikey}" > $TMPFILE
CITY=$(fgrep "<city id=" $TMPFILE | tr -sc '[:alnum:]' ' ' | cut -d " " -f 6)

View file

@ -1,4 +1,4 @@
#!/usr/local/bin/bash
#!/usr/bin/env bash
#
# Plugin to monitor a ZFS Filesystem
#