]> err.no Git - varnish/commitdiff
I got bored and wrote an all-singing, all-dancing Munin plugin to replace
authordes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Thu, 12 Jul 2007 22:38:24 +0000 (22:38 +0000)
committerdes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Thu, 12 Jul 2007 22:38:24 +0000 (22:38 +0000)
the ones contributed by Anders and Bjørn.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1679 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-tools/munin/Makefile.am [new file with mode: 0644]
varnish-tools/munin/README [deleted file]
varnish-tools/munin/autogen.sh [new file with mode: 0755]
varnish-tools/munin/configure.ac [new file with mode: 0644]
varnish-tools/munin/varnish_cachehitratio [deleted file]
varnish-tools/munin/varnish_hitrate [deleted file]
varnish-tools/munin/varnish_munin_plugin.pl [new file with mode: 0644]
varnish-tools/munin/varnish_varnishstat_ [deleted file]

diff --git a/varnish-tools/munin/Makefile.am b/varnish-tools/munin/Makefile.am
new file mode 100644 (file)
index 0000000..06bbca4
--- /dev/null
@@ -0,0 +1,10 @@
+# $Id$
+
+EXTRA_DIST = varnish_munin_plugin.pl
+
+install-exec-local:
+       ${install_sh} -m 0755 -c varnish_munin_plugin.pl \
+               ${DESTDIR}${bindir}/varnish_
+#      for aspect in `${DESTDIR}${bindir}/varnish_ aspects` ; do \
+#              ln -fs varnish_ ${DESTDIR}${bindir}/varnish_$$aspect ; \
+#      done
diff --git a/varnish-tools/munin/README b/varnish-tools/munin/README
deleted file mode 100644 (file)
index 461f592..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-The scripts in this directory are munin plugins for monitoring varnish.
-varnish_cachehitratio and varnish_hitrate are written by Anders
-Nordby, while varnish_varnishstat_ is written by Bjørn
-Ruberg. All three scripts uses varnishstat to acquire information.
-
-* varnish_cachehitratio shows the cache hit/miss ratio.
-* varnish_hitrate shows the rate of requests.
-* varnish_varnishstat_ shows the cache usage.
-
-To work with named varnish instances, these scripts will have to be modified
-so they can call varnishstat with the appropriate parameter. As of today,
-the scripts only call 'varnishstat -1', and thus, will only work if varnishd
-was started without the -n parameter. A solution to this problem could be to
-let the scripts read a filename from an environment variable (this must then
-be set in the munin-plugin configuration), and have this file contain the
-name (or names?) to the varnish server(s) to monitor. If the environment
-variable is not set, varnishstat will be called without the -n parameter,
-and work with the default name.
-
-Dependencies:
-* varnish_cachehitration needs the CPAN module Date::Format
-* varnish_varnishstart_ needs the CPAN module Net::Telnet
-(but does it really? It doesn't seem to use it for anything.)
diff --git a/varnish-tools/munin/autogen.sh b/varnish-tools/munin/autogen.sh
new file mode 100755 (executable)
index 0000000..916dc83
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# $Id$
+#
+
+if [ -d /usr/local/gnu-autotools/bin ] ; then
+       PATH=/usr/local/gnu-autotools/bin:${PATH}
+       export PATH
+       FIX_BROKEN_FREEBSD_PORTS="-I /usr/local/share/aclocal"
+fi
+
+automake_version=$(automake --version | tr ' ' '\n' | egrep '^[0-9]\.[0-9a-z.-]+')
+if [ -z "$automake_version" ] ; then
+    echo "unable to determine automake version"
+    exit 1
+else
+    case $automake_version in
+       0.*|1.[0-8]|1.[0-8][.-]*)
+           echo "your version of automake ($automake_version) is too old;" \
+               "you need 1.9 or newer."
+           exit 1
+           ;;
+       *)
+           ;;
+    esac
+fi
+
+set -ex
+
+aclocal ${FIX_BROKEN_FREEBSD_PORTS}
+automake --add-missing --copy --foreign
+autoconf
diff --git a/varnish-tools/munin/configure.ac b/varnish-tools/munin/configure.ac
new file mode 100644 (file)
index 0000000..a81c1b3
--- /dev/null
@@ -0,0 +1,19 @@
+# $Id$
+
+AC_PREREQ(2.59)
+AC_COPYRIGHT([Copyright (c) 2007 Linpro AS / Verdens Gang AS])
+AC_REVISION([$Id$])
+AC_INIT([Varnish Munin plugin], [trunk], [varnish-dev@projects.linpro.no])
+AC_CONFIG_SRCDIR(varnish_munin_plugin.pl)
+
+AC_CANONICAL_SYSTEM
+
+AM_INIT_AUTOMAKE
+
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+AC_CHECK_PROGS(PERL, [perl])
+AC_CHECK_PROGS(VARNISHSTAT, [varnishstat])
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/varnish-tools/munin/varnish_cachehitratio b/varnish-tools/munin/varnish_cachehitratio
deleted file mode 100644 (file)
index c3d259e..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-#! /usr/bin/perl
-# Varnish cache hit ratio logger/plugin
-# anders@aftenposten.no, 2007-05-07
-
-# Log/data file
-# These must be created with write permission to the user the plugin runs as
-# On FreeBSD, that is nobody
-# Comment $mylog out to skip logging
-
-$mydat = "/var/tmp/varnish_cachehitratio.dat";
-#$mylog = "/var/log/varnish_cachehitratio.log";
-
-%stat = ();
-$ENV{PATH} = "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin";
-
-use Date::Format;
-
-sub popstat {
-       foreach $line (`varnishstat -1`) {
-       chomp($line);
-               if ($line =~ /^\s+(\d+)\s+(.*)$/) {
-                       $val = $1;
-                       $key = $2;
-                       $key =~ s@\s@_@g;
-                       $key =~ tr@A-Z@a-z@;
-
-                       $stat{"$key"} = $val;
-               }
-       }
-}
-
-sub printconfig {
-       print "graph_title Cache hit/miss ratio\n";
-       print "graph_args --upper-limit 100 -l 0\n";
-       print "graph_vlabel % of requests\n";
-       print "graph_category varnish\n";
-       print "graph_info This graph shows the ratio of requests found in the cache and not\n";
-       print "graph_order hitratio missratio unknownratio\n";
-       print "graph_scale no\n";
-
-       print "hitratio.label hits\n";
-       print "hitratio.type GAUGE\n";
-       print "hitratio.graph yes\n";
-       print "hitratio.min 0\n";
-       print "hitratio.max 100\n";
-       print "hitratio.draw AREA\n";
-
-       print "missratio.label misses\n";
-       print "missratio.type GAUGE\n";
-       print "missratio.graph yes\n";
-       print "missratio.min 0\n";
-       print "missratio.max 100\n";
-       print "missratio.draw STACK\n";
-
-       print "unknownratio.label unknown\n";
-       print "unknownratio.type GAUGE\n";
-       print "unknownratio.graph yes\n";
-       print "unknownratio.min 0\n";
-       print "unknownratio.max 100\n";
-       print "unknownratio.draw STACK\n";
-}
-
-sub findvalues {
-       $nrequests = $stat{"client_requests_received"};
-       $nhits = $stat{"cache_hits"};
-       $nmisses = $stat{"cache_misses"};
-
-       open(OVAL, $mydat);
-       $tmpstr = <OVAL>;
-       close(OVAL);
-       chomp($tmpstr);
-
-       ($orequests,$ohits,$omisses) = split(/ /, $tmpstr, 3);
-
-       $hits = $nhits - $ohits;
-       $requests = $nrequests - $orequests;
-       $misses = $nmisses - $omisses;
-}
-
-sub printvalues {
-       if ($requests > 0) {
-               $hitratio = sprintf("%.2f", $hits / $requests * 100);
-               $missratio = sprintf("%.2f", $misses / $requests * 100);
-       } else {
-               # Assume cache hit ratio = 100% if requests < 0
-               $hitratio = sprintf("%.2f", 100);
-               $missratio = sprintf("%.2f", 0);
-       }
-
-       if (($hitratio + $missratio) > 100) {
-               # Rounding foo, hit+miss ratio is higher than 100
-               $missratio = sprintf("%.2f", 100 - $hitratio);
-               $unknownratio = sprintf("%.2f", 0);
-       } else {
-               # Unknown = rest, hit+miss ratio is upto or 100
-               $unknownratio = sprintf("%.2f", 100 - ($hitratio + $missratio));
-       }
-
-       print "hitratio.value $hitratio\n";
-       print "missratio.value $missratio\n";
-       print "unknownratio.value $unknownratio\n";
-       if ($mylog ne "") {
-               open(LOG, ">>$mylog");
-               print LOG "hitratio=$hitratio missratio=$missratio unknown=$unknownratio hits=$hits misses=$misses requests=$requests [" . time2str("%Y-%m-%d %H:%M:%S", time) . "]\n";
-               close(LOG);
-       }
-}
-
-sub writevalues {
-       open(OVAL, ">$mydat");
-       print OVAL "$nrequests $nhits $nmisses\n";
-       close(OVAL);
-}
-
-if ($ARGV[0] eq "autoconf") {
-       print "yes\n";
-} elsif ($ARGV[0] eq "config") {
-       printconfig;
-} else {
-       popstat;
-       findvalues;
-       printvalues;
-       writevalues;
-}
diff --git a/varnish-tools/munin/varnish_hitrate b/varnish-tools/munin/varnish_hitrate
deleted file mode 100644 (file)
index 3f64b43..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#! /bin/sh
-# anders@aftenposten.no, 2007-05-07
-# Shows the rate of requests (per second) for Varnish
-
-PATH="$PATH:/usr/local/bin"
-export PATH
-
-pvstat() {
-       # $1: vname $2: grabstat
-       printf "$1.value "
-       varnishstat -1 | egrep "$2" | awk '{print $1}'
-}
-
-case $1 in
-autoconf) echo yes;;
-config)
-       echo 'graph_title Hitrate'
-       echo 'graph_vlabel hits per second'
-       echo 'graph_category varnish'
-       echo 'graph_info This graph shows the rate of requests, hits per second'
-
-       echo 'requests.label requests'
-       echo 'requests.type COUNTER'
-       echo 'requests.graph yes'
-       ;;
-*)
-       pvstat requests 'Client requests received$'
-       ;;
-esac
diff --git a/varnish-tools/munin/varnish_munin_plugin.pl b/varnish-tools/munin/varnish_munin_plugin.pl
new file mode 100644 (file)
index 0000000..84793a6
--- /dev/null
@@ -0,0 +1,207 @@
+#!/usr/bin/perl -w
+#-
+# Copyright (c) 2007 Linpro AS
+# All rights reserved.
+#
+# Author: Dag-Erling Smørgrav <des@linpro.no>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id$
+#
+
+use strict;
+
+our %varnishstat;
+
+our %ASPECTS = (
+    'ratio' => {
+       'title' => 'Hit / miss ratio',
+       'type' => 'percent',
+       'values' => {
+           'hit' => {
+               'label' => 'hits',
+               'numerator' => 'cache_hit',
+               'denominator' => 'client_req',
+           },
+           'miss' => {
+               'label' => 'misses',
+               'numerator' => 'cache_miss',
+               'denominator' => 'client_req',
+           },
+       },
+    },
+);
+
+sub varnishstat($) {
+    my $field = shift;
+
+    die "no such field: $field\n"
+       unless defined($varnishstat{$field});
+    return $varnishstat{$field};
+}
+
+sub value($$) {
+    my $value = shift;
+    my $type = shift;
+
+    defined($value) || die "oops";
+    if ($type eq 'count') {
+       return varnishstat($value->{'field'});
+    } elsif ($type eq 'gauge') {
+       return varnishstat($value->{'field'});
+    } elsif ($type eq 'percent') {
+       return sprintf("%.1f", varnishstat($value->{'numerator'}) * 100.0 /
+                      varnishstat($value->{'denominator'}));
+    } elsif ($type eq 'ratio') {
+       return sprintf("%.3f", varnishstat($value->{'numerator'}) /
+                      varnishstat($value->{'denominator'}));
+    } else {
+       die "oops";
+    }
+}
+
+sub measure($) {
+    my $aspect = shift;
+
+    defined($aspect) || die "oops";
+    my @order = $aspect->{'order'} || sort(keys(%{$aspect->{'values'}}));
+    foreach (@order) {
+       print "$_.value ",
+           value($aspect->{'values'}->{$_}, $aspect->{'type'}),
+           "\n";
+    }
+}
+
+sub config($) {
+    my $aspect = shift;
+
+    defined($aspect) || die "oops";
+    print "graph_category Varnish\n";
+    print "graph_title $aspect->{'title'}\n";
+    if ($aspect->{'type'} eq 'percent') {
+       print "graph_scale no\n";
+    }
+    my @order = $aspect->{'order'} || sort(keys(%{$aspect->{'values'}}));
+    print "graph_order ", join(' ', @order), "\n";
+    foreach (@order) {
+       my $value = $aspect->{'values'}->{$_};
+       print "$_.label $value->{'label'}\n";
+       print "$_.graph yes\n";
+       if ($aspect->{'type'} eq 'count') {
+           print "$_.type COUNTER\n";
+       } elsif ($aspect->{'type'} eq 'gauge') {
+           print "$_.type GAUGE\n";
+       } elsif ($aspect->{'type'} eq 'percent') {
+           print "$_.type GAUGE\n";
+           print "$_.min 0\n";
+           print "$_.max 100\n";
+           if ($_ eq $order[0]) {
+               print "$_.draw AREA\n";
+           } else {
+               print "$_.draw STACK\n";
+           }
+       }
+    }
+}
+
+sub read_varnishstat($) {
+    my $name = shift;
+    my ($rh, $wh);
+    my $pid;
+
+    pipe($rh, $wh)
+       or die "pipe(): $!\n";
+    defined($pid = fork())
+       or die "fork(): $!\n";
+    if ($pid == 0) {
+       close($rh);
+       open(STDOUT, ">&", $wh);
+       exec "varnishstat", "-1", $name ? ("-n", $name) : ()
+           or die "exec(): $!\n";
+       die "not reachable\n";
+    }
+    close($wh);
+    while (<$rh>) {
+       if (m/^(\w+)\s+(\d+)\s+(\d*\.\d*)\s+(\w.*)$/) {
+           $varnishstat{$1} = $2;
+           $ASPECTS{$1} = {
+               'title' => $4,
+               'type' => ($3 eq ".") ? 'gauge' : 'count',
+               'values' => {
+                   $1 => {
+                       'label' => $1,
+                       'field' => $1,
+                   }
+               }
+           };
+       }
+    }
+    close($rh);
+    waitpid($pid, 0)
+       or die "waitpid(): $!\n";
+    if ($? & 0x80) {
+       die "varnishstat received signal ", $? && 0x7f, "\n";
+    } elsif ($?) {
+       die "varnishstat returned exit code ", $? >> 8, "\n";
+    }
+}
+
+sub usage() {
+
+    print STDERR "usage: varnish_<aspect> [config]\n";
+    print STDERR "aspects: ", join(', ', sort keys %ASPECTS), "\n";
+    exit 1;
+}
+
+MAIN:{
+    read_varnishstat($ENV{'VARNISH_NAME'});
+
+    my $aspect;
+    ($aspect = $0) =~ s|^(?:.*/)varnish_(\w+)$|$1|;
+
+    # XXX bug in munin-node
+    shift @ARGV
+       if (@ARGV && $ARGV[0] eq '');
+
+    if (@ARGV == 0) {
+       defined($ASPECTS{$aspect})
+           or usage();
+       measure($ASPECTS{$aspect});
+    } elsif (@ARGV == 1) {
+       if ($ARGV[0] eq 'autoconf') {
+           print "yes\n";
+       } elsif ($ARGV[0] eq 'aspects') {
+           foreach (sort keys %ASPECTS) {
+               print "$_\n";
+           }
+       } elsif ($ARGV[0] eq 'config') {
+           defined($ASPECTS{$aspect})
+               or usage();
+           config($ASPECTS{$aspect});
+       } else {
+           usage();
+       }
+    } else {
+       usage();
+    }
+}
diff --git a/varnish-tools/munin/varnish_varnishstat_ b/varnish-tools/munin/varnish_varnishstat_
deleted file mode 100644 (file)
index a3c2792..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/perl
-use Net::Telnet ();
-use Data::Dumper;
-
-$arg = shift @ARGV;
-
-%aspects = (
-            'cache' => 'Cache',
-            'backend' => 'Backend',
-           'shm' => 'SHM'
-            );
-
-(my $whut = $0) =~ s/^.*\_//;
-
-# Hvis $whut IKKE fins, men $arg fins OG er noe annet enn blabla
-# så skal den trigge
-
-if (!$whut && $arg && $arg !~ /^(suggest|autoconf)$/) {
-    print "Only 'suggest' and 'autoconf' may be used w/o symlinked name\n";
-    exit 2;
-} elsif (!$whut && !$arg) {
-    print "Uh. Bugger.\n";
-    exit 2;
-}
-
-if ($arg eq 'autoconf') {
-    print "Autoconf starting...\n";
-    exit 0;
-} elsif ($arg eq 'suggest') {
-    print "Suggest starting...\n";
-    exit 0;
-} elsif ($arg eq 'config') {
-    $config = 1;
-}
-
-$grepfor = $aspects{$whut};
-# print "Looking for $grepfor\n";
-
-if ($config) {
-    print "graph_title Varnish $grepfor usage\n";
-    print "graph_args --base 1000\n";
-    print "graph_vlabel Activity / \${graph_period}\n";
-    print "graph_category Varnish\n";
-}
-
-$i = 0;
-foreach $line (`varnishstat -1`) {
-    chomp $line;
-    if ($line =~ /^\s+(\d+)\s+($grepfor.*)$/) {
-        $val = $1;
-        $key = $2;
-        ($printkey = lc ($key)) =~ s/\s/_/g;
-        if ($config) {
-            print "$printkey\.label $key\n";
-            print "$printkey\.type DERIVE\n";
-            print "$printkey\.min 0\n";
-               print "$printkey\.draw ";
-           if ($i == 0) {
-               print "AREA\n";
-            } else {
-               print "STACK\n";
-           }
-            $i++;
-        } else {
-            print "$printkey\.value $val\n";
-        }
-    }
-}
-    
-exit;
-