From: des Date: Thu, 12 Jul 2007 22:38:24 +0000 (+0000) Subject: I got bored and wrote an all-singing, all-dancing Munin plugin to replace X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=12f6a6ca06aef9702122e4048bae067646c2ddd9;p=varnish I got bored and wrote an all-singing, all-dancing Munin plugin to replace 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 --- diff --git a/varnish-tools/munin/Makefile.am b/varnish-tools/munin/Makefile.am new file mode 100644 index 00000000..06bbca49 --- /dev/null +++ b/varnish-tools/munin/Makefile.am @@ -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 index 461f592a..00000000 --- a/varnish-tools/munin/README +++ /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 index 00000000..916dc839 --- /dev/null +++ b/varnish-tools/munin/autogen.sh @@ -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 index 00000000..a81c1b32 --- /dev/null +++ b/varnish-tools/munin/configure.ac @@ -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 index c3d259ed..00000000 --- a/varnish-tools/munin/varnish_cachehitratio +++ /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 = ; - 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 index 3f64b437..00000000 --- a/varnish-tools/munin/varnish_hitrate +++ /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 index 00000000..84793a60 --- /dev/null +++ b/varnish-tools/munin/varnish_munin_plugin.pl @@ -0,0 +1,207 @@ +#!/usr/bin/perl -w +#- +# Copyright (c) 2007 Linpro AS +# All rights reserved. +# +# Author: Dag-Erling Smørgrav +# +# 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_ [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 index a3c27920..00000000 --- a/varnish-tools/munin/varnish_varnishstat_ +++ /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; -