1
0
Fork 0
mirror of https://github.com/munin-monitoring/contrib.git synced 2025-07-21 18:41:03 +00:00

- have some dirs

This commit is contained in:
Steve Schnepp 2012-02-13 18:24:46 +01:00
parent 0b089ea777
commit 08346aac58
687 changed files with 0 additions and 0 deletions

80
plugins/varnish/varnish2_ Executable file
View file

@ -0,0 +1,80 @@
#!/usr/bin/perl
# Original author: Bjørn Ruberg
# Updated to Varnish 2.0/added instructions: Daniel Wirtz
#
# Installation (Debian):
# 1. Upload file to /usr/share/munin/plugins
# 2. Create symlinks:
# ln -s /usr/share/munin/plugins/varnish2_ /etc/munin/plugins/varnish_cache
# ln -s /usr/share/munin/plugins/varnish2_ /etc/munin/plugins/varnish_backend
# ln -s /usr/share/munin/plugins/varnish2_ /etc/munin/plugins/varnish_shm
# 3. Restart Munin-Node:
# /etc/init.d/munin-node restart
$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+\d+\.\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;

806
plugins/varnish/varnish_ Executable file
View file

@ -0,0 +1,806 @@
#!/usr/bin/perl -w
#
# varnish_ - Munin plugin for Multiple Varnish Servers
# Copyright (C) 2009 Redpill Linpro AS
#
# Author: Kristian Lyngstøl <kristian@redpill-linpro.com>
# Modified by Paul Mansfield so that it can be used with multiple
# varnish instances
#
# 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 2 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use strict;
# Set to 1 to enable output when a variable is defined in a graph but
# omitted because it doesn't exist in varnishstat.
my $DEBUG = 0;
# Set to 1 to ignore 'DEBUG' and suggest all available aspects.
my $FULL_SUGGEST = 0;
# Varnishstat executable. Include full path if it's not in your path.
my $varnishstatexec = exists $ENV{'varnishstat'} ? $ENV{'varnishstat'} : "varnishstat";
# For multiple instances
my $varnishname = exists $ENV{'name'} ? $ENV{'name'} : undef;
my %varnishstat = ();
my %varnishstatnames = ();
my $self; # Haha, myself, what a clever pun.
# Parameters that can be defined on top level of a graph. Config will print
# them as "graph_$foo $value\n"
my @graph_parameters = ('title','total','order','scale','vlabel','args');
# Parameters that can be defined on a value-to-value basis and will be
# blindly passed to config. Printed as "$fieldname.$param $value\n".
#
# 'label' is hardcoded as it defaults to a varnishstat-description if not
# set.
my @field_parameters = ('graph', 'min', 'max', 'draw', 'cdef', 'warning',
'colour', 'info', 'type');
# Data structure that defines all possible graphs (aspects) and how they
# are to be plotted. Every top-level entry is a graph/aspect. Each top-level graph
# MUST have title set and 'values'.
#
# The 'values' hash must have at least one value definition. The actual
# value used is either fetched from varnishstat based on the value-name, or
# if 'rpn' is defined: calculated. 'type' SHOULD be set.
#
# Graphs with 'DEBUG' set to anything is omitted from 'suggest'.
#
# 'rpn' on values allows easy access to graphs consisting of multiple
# values from varnishstat. (Reverse polish notation). The RPN
# implementation only accepts +-*/ and varnishstat-values.
#
# With the exception of 'label', which is filled with the
# varnishstat-description if left undefined, any value left undefined will
# be left up to Munin to define/ignore/yell about.
#
# See munin documentation or rrdgraph/rrdtool for more information.
my %ASPECTS = (
'request_rate' => {
'title' => 'Request rates',
'order' => 'cache_hit cache_hitpass cache_miss '
. 'backend_conn backend_unhealthy '
. 'client_req client_conn' ,
'values' => {
'client_conn' => {
'type' => 'DERIVE',
'min' => '0',
'colour' => '444444',
'graph' => 'ON'
},
'client_req' => {
'type' => 'DERIVE',
'colour' => '111111',
'min' => '0'
},
'cache_hit' => {
'type' => 'DERIVE',
'draw' => 'AREA',
'colour' => '00FF00',
'min' => '0'
},
'cache_hitpass' => {
'info' => 'Hitpass are cached passes: An '
. 'entry in the cache instructing '
. 'Varnish to pass. Typically '
. 'achieved after a pass in '
. 'vcl_fetch.',
'type' => 'DERIVE',
'draw' => 'STACK',
'colour' => 'FFFF00',
'min' => '0'
},
'cache_miss' => {
'type' => 'DERIVE',
'colour' => 'FF0000',
'draw' => 'STACK',
'min' => '0'
},
'backend_conn' => {
'type' => 'DERIVE',
'colour' => '995599',
'min' => '0'
},
'backend_unhealthy' => {
'colour' => 'FF55FF',
'type' => 'GAUGE'
},
's_pipe' => {
'type' => 'DERIVE',
'min' => '0',
'colour' => '1d2bdf'
},
's_pass' => {
'type' => 'DERIVE',
'min' => '0',
'colour' => '785d0d'
}
}
},
'hit_rate' => {
'title' => 'Hit rates',
'order' => 'client_req cache_hit cache_miss '
. 'cache_hitpass' ,
'vlabel' => '%',
'args' => '-u 100 --rigid',
'scale' => 'no',
'values' => {
'client_req' => {
'type' => 'DERIVE',
'min' => '0',
'graph' => 'off'
},
'cache_hit' => {
'type' => 'DERIVE',
'min' => '0',
'draw' => 'AREA',
'cdef' => 'cache_hit,client_req,/,100,*'
},
'cache_miss' => {
'type' => 'DERIVE',
'draw' => 'STACK',
'min' => '0',
'cdef' => 'cache_miss,client_req,/,100,*'
},
'cache_hitpass' => {
'type' => 'DERIVE',
'draw' => 'STACK',
'min' => '0',
'cdef' => 'cache_hitpass,client_req,/,100,*'
},
}
},
'backend_traffic' => {
'title' => 'Backend traffic',
'values' => {
'backend_conn' => {
'type' => 'DERIVE',
'min' => '0'
},
'backend_unhealthy' => {
'type' => 'GAUGE',
'min' => '0',
'warning' => ':1'
},
'backend_busy' => {
'type' => 'DERIVE',
'min' => '0'
},
'backend_fail' => {
'type' => 'DERIVE',
'min' => '0'
},
'backend_reuse' => {
'type' => 'DERIVE',
'min' => 0
},
'backend_recycle' => {
'type' => 'DERIVE',
'min' => 0
},
'backend_unused' => {
'type' => 'DERIVE',
'min' => '0'
},
'backend_req' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'objects' => {
'title' => 'Number of objects',
'values' => {
'n_object' => {
'type' => 'GAUGE',
'label' => 'Number of objects'
},
'n_objecthead' => {
'type' => 'GAUGE',
'label' => 'Number of object heads',
'info' => 'Each object head can have one '
. 'or more ojbect attached, '
. 'typically based on the Vary: header'
}
}
},
'transfer_rates' => {
'title' => 'Transfer rates',
'order' => 's_bodybytes s_hdrbytes',
'args' => '-l 0',
'vlabel' => 'bit/s',
'values' => {
's_hdrbytes' => {
'type' => 'DERIVE',
'label' => 'Header traffic',
'draw' => 'STACK',
'min' => '0',
'info' => 'HTTP Header traffic. TCP/IP '
. 'overhead is not included.',
'cdef' => 's_hdrbytes,8,*'
},
's_bodybytes' => {
'type' => 'DERIVE',
'draw' => 'AREA',
'label' => 'Body traffic',
'min' => '0',
'cdef' => 's_bodybytes,8,*'
}
}
},
'threads' => {
'title' => 'Thread status',
'values' => {
'n_wrk' => {
'type' => 'GAUGE',
'min' => '0',
'warning' => '1:'
},
'n_wrk_create' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_wrk_failed' => {
'type' => 'DERIVE',
'min' => '0',
'warning' => ':1'
},
'n_wrk_max' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_wrk_overflow' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_wrk_drop' => {
'type' => 'DERIVE',
'min' => '0',
'warning' => ':1'
}
}
},
'memory_usage' => {
'title' => 'Memory usage',
'order' => 'sm_balloc sma_nbytes sms_nbytes',
'total' => 'Total',
'args' => '--base 1024',
'values' => {
'sm_balloc' => {
'type' => 'GAUGE',
'draw' => 'AREA'
},
'sma_nbytes' => {
'type' => 'GAUGE',
'draw' => 'STACK'
},
'sms_nbytes' => {
'type' => 'GAUGE',
'draw' => 'STACK'
}
}
},
'uptime' => {
'title' => 'Varnish uptime',
'vlabel' => 'days',
'scale' => 'no',
'values' => {
'uptime' => {
'type' => 'GAUGE',
'cdef' => 'uptime,86400,/'
}
}
},
'objects_per_objhead' => {
'title' => 'Objects per objecthead',
'DEBUG' => 'yes',
'values' => {
'obj_per_objhead' => {
'type' => 'GAUGE',
'label' => 'Objects per object heads',
'rpn' => [ 'n_object','n_objecthead','/' ]
}
}
},
'losthdr' => {
'title' => 'HTTP Header overflows',
'DEBUG' => 'yes',
'values' => {
'losthdr' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'obj_sendfile_vs_write' => {
'title' => 'Objects delivered with sendfile() versus '
. 'write()',
'DEBUG' => 'yes',
'values' => {
'n_objsendfile' => {
'type' => 'DERIVE',
'min' => '0',
},
'n_objwrite' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'hcb' => {
'title' => 'Critbit data',
'DEBUG' => 'yes',
'values' => {
'hcb_nolock' => {
'type' => 'DERIVE',
'min' => '0'
},
'hcb_lock' => {
'type' => 'DERIVE',
'min' => '0'
},
'hcb_insert' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'esi' => {
'title' => 'ESI',
'DEBUG' => 'yes',
'values' => {
'esi_parse' => {
'type' => 'DERIVE',
'min' => '0'
},
'esi_errors' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'objoverflow' => {
'title' => 'Objects overflowing workspace',
'DEBUG' => 'yes',
'values' => {
'n_objoverflow' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'session' => {
'title' => 'Sessions',
'DEBUG' => 'yes',
'values' => {
'sess_closed' => {
'type' => 'DERIVE',
'min' => '0'
},
'sess_pipeline' => {
'type' => 'DERIVE',
'min' => '0'
},
'sess_readahead' => {
'type' => 'DERIVE',
'min' => '0'
},
'sess_linger' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'session_herd' => {
'title' => 'Session herd',
'DEBUG' => 'yes',
'values' => {
'sess_herd' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'shm_writes' => {
'title' => 'SHM writes and records',
'DEBUG' => 'yes',
'values' => {
'shm_records' => {
'type' => 'DERIVE',
'min' => '0'
},
'shm_writes' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'shm' => {
'title' => 'Shared memory activity',
'DEBUG' => 'yes',
'values' => {
'shm_flushes' => {
'type' => 'DERIVE',
'min' => '0'
},
'shm_cont' => {
'type' => 'DERIVE',
'min' => '0'
},
'shm_cycles' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'allocations' => {
'title' => 'Memory allocation requests',
'DEBUG' => 'yes',
'values' => {
'sm_nreq' => {
'type' => 'DERIVE',
'min' => '0'
},
'sma_nreq' => {
'type' => 'DERIVE',
'min' => '0'
},
'sms_nreq' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'vcl_and_purges' => {
'title' => 'VCL and purges',
'DEBUG' => 'yes',
'values' => {
'n_backend' => {
'type' => 'GAUGE'
},
'n_vcl' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_vcl_avail' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_vcl_discard' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_purge' => {
'type' => 'GAUGE'
},
'n_purge_add' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_purge_retire' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_purge_obj_test' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_purge_re_test' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_purge_dups' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'expunge' => {
'title' => 'Object expunging',
'values' => {
'n_expired' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_lru_nuked' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'lru' => {
'title' => 'LRU activity',
'DEBUG' => 'yes',
'values' => {
'n_lru_saved' => {
'type' => 'DERIVE',
'min' => '0'
},
'n_lru_moved' => {
'type' => 'DERIVE',
'min' => '0'
}
}
},
'data_structures' => {
'DEBUG' => 'YES',
'title' => 'Data structure sizes',
'values' => {
'n_srcaddr' => {
'type' => 'GAUGE'
},
'n_srcaddr_act' => {
'type' => 'GAUGE'
},
'n_sess_mem' => {
'type' => 'GAUGE'
},
'n_sess' => {
'type' => 'GAUGE'
},
'n_smf' => {
'type' => 'GAUGE'
},
'n_smf_frag' => {
'type' => 'GAUGE'
},
'n_smf_large' => {
'type' => 'GAUGE'
},
'n_vbe_conn' => {
'type' => 'GAUGE'
},
'n_bereq' => {
'type' => 'GAUGE'
}
}
}
);
# Populate %varnishstat with values and %varnishstatnames with
# descriptions.
sub populate_stats
{
my $arg = "-1";
if ($varnishname) {
$arg .= " -n $varnishname";
}
foreach my $line (`$varnishstatexec $arg`) {
chomp($line);
if ($line =~ /^([^ ]*)\s+(\d+)\s+(\d*\.\d*)\s+(.*)$/) {
$varnishstat{"$1"} = $2;
$varnishstatnames{"$1"} = $4;
}
}
}
# Bail-function.
sub usage
{
if (defined(@_) && "@_" ne "") {
print STDERR "@_" . "\n\n";
}
print STDERR "Known arguments: suggest, config, autoconf.\n";
print STDERR "Run with suggest to get a list of known aspects.\n";
exit 1;
}
# Print 'yes' and exit true if it's reasonable to use this plugin.
# Otherwise exit with false and a human-readable reason.
sub autoconf
{
if (`which $varnishstatexec` eq '') {
print "no (which $varnishstatexec returns blank)\n";
exit 1;
}
print "yes\n";
exit 0;
}
# Suggest relevant aspects/values of $self.
# 'DEBUG'-graphs are excluded.
sub suggest
{
foreach my $key (keys %ASPECTS) {
if (defined($ASPECTS{$key}{'DEBUG'}) && $FULL_SUGGEST != 1) {
next;
}
print "$key\n";
}
}
# Print the value of a two-dimensional hash if it exist.
# Returns false if non-existant.
#
# Output is formatted for plugins if arg4 is blank, otherwise arg4 is used
# as the title/name of the field (ie: arg4=graph_titel).
sub print_if_exist
{
my %values = %{$_[0]};
my $value = $_[1];
my $field = $_[2];
my $title = "$value.$field";
if (defined($_[3])) {
$title = $_[3];
}
if (defined($values{$value}{$field})) {
print "$title $values{$value}{$field}";
print " - $varnishname" if ($title eq 'graph_title');
print "\n";
} else {
return 0;
}
}
# Walk through the relevant aspect and print all top-level configuration
# values and value-definitions.
sub get_config
{
my $graph = $_[0];
# Need to double-check since set_aspect only checks this if there
# is no argument (suggest/autoconf doesn't require a valid aspect)
if (!defined($ASPECTS{$graph})) {
usage "No such aspect";
}
my %values = %{$ASPECTS{$graph}{'values'}};
print "graph_category Varnish\n";
foreach my $field (@graph_parameters) {
print_if_exist(\%ASPECTS,$graph,$field,"graph_$field");
}
foreach my $value (keys %values) {
# Need either RPN definition or a varnishstat value.
if (!defined($varnishstat{$value}) &&
!defined($values{$value}{'rpn'})) {
if ($DEBUG) {
print "ERROR: $value not part of varnishstat.\n"
}
next;
}
if (!print_if_exist(\%values,$value,'label')) {
print "$value.label $varnishstatnames{$value}\n";
}
foreach my $field (@field_parameters) {
print_if_exist(\%values,$value,$field);
}
}
}
# Read and verify the aspect ($self) -
# the format is varnish_NAME__aspect or varnish_aspect
sub set_aspect
{
$self = $0;
$self =~ s/^.*\/varnish_//;
if ($self =~ /^(\w+)__(.*)$/)
{
$varnishname = $1;
$self = $2;
}
if (!defined($ASPECTS{$self}) && @ARGV == 0) {
usage "No such aspect";
}
}
# Handle arguments (config, autoconf, suggest)
# Populate stats for config is necessary, but we want to avoid it for
# autoconf as it would generate a nasty error.
sub check_args
{
if (@ARGV && $ARGV[0] eq '') {
shift @ARGV;
}
if (@ARGV == 1) {
if ($ARGV[0] eq "config") {
populate_stats;
get_config($self);
exit 0;
} elsif ($ARGV[0] eq "autoconf") {
autoconf($self);
exit 0;
} elsif ($ARGV[0] eq "suggest") {
suggest;
exit 0;
}
usage "Unknown argument";
}
}
# Braindead RPN: +,-,/,* will pop two items from @stack, and perform
# the relevant operation on the items. If the item in the array isn't one
# of the 4 basic math operations, a value from varnishstat is pushed on to
# the stack. IE: 'client_req','client_conn','/' will leave the value of
# "client_req/client_conn" on the stack.
#
# If only one item is left on the stack, it is printed. Otherwise, an error
# message is printed.
sub rpn
{
my @stack;
my $left;
my $right;
foreach my $item (@{$_[0]}) {
if ($item eq "+") {
$right = pop(@stack);
$left = pop(@stack);
push(@stack,$left+$right);
} elsif ($item eq "-") {
$right = pop(@stack);
$left = pop(@stack);
push(@stack,$left-$right);
} elsif ($item eq "/") {
$right = pop(@stack);
$left = pop(@stack);
push(@stack,$left/$right);
} elsif ($item eq "*") {
$right = pop(@stack);
$left = pop(@stack);
push(@stack,$left*$right);
} else {
push(@stack,int($varnishstat{$item}));
}
}
if (@stack > 1)
{
print STDERR "RPN error: Stack has more than one item left.\n";
print STDERR "@stack\n";
exit 255;
}
print "@stack";
print "\n";
}
################################
# Execution starts here #
################################
set_aspect;
check_args;
populate_stats;
# We only get here if we're supposed to.
# Walks through the relevant values and either prints the varnishstat, or
# if the 'rpn' variable is set, calls rpn() to execute ... the rpn.
#
# NOTE: Due to differences in varnish-versions, this checks if the value
# actually exist before using it.
foreach my $value (keys %{$ASPECTS{$self}{'values'}}) {
if (defined($ASPECTS{$self}{'values'}{$value}{'rpn'})) {
print "$value.value ";
rpn($ASPECTS{$self}{'values'}{$value}{'rpn'});
} else {
if (!defined($varnishstat{$value})) {
if ($DEBUG) {
print STDERR "Error: $value not part of "
. "varnishstat.\n";
}
next;
}
#print "$varnishname.$value.value ";
print "$value.value ";
print "$varnishstat{$value}\n";
}
}
# end varnish_ plugin

View file

@ -0,0 +1,35 @@
#! /bin/sh
# anders@fupp.net, 2007-09-19
# Shows the amount of virtual memory allocated by Varnish for storing cache
# objects
PATH="$PATH:/usr/local/bin"
export PATH
vversion=`varnishstat -V 2>&1 | egrep "^varnishstat" | perl -p -e "s@varnishstat\s*@@;s@\(@@;s@\)@@;s@varnish-@@"`
pvstat() {
# $1: vname $2: grabstat
printf "$1.value "
case $vversion in
1.0*) varnishstat -1 | egrep "$2" | awk '{print $1}';;
*) varnishstat -1 | egrep "$2" | awk '{print $2}';;
esac
}
case $1 in
autoconf) echo yes;;
config)
echo 'graph_title Virtual memory allocated'
echo 'graph_vlabel memory'
echo 'graph_category varnish'
echo 'graph_info This graph shows the amount of virtual memory allocated by Varnish for storing cache objects'
echo 'memory.label memory'
echo 'memory.type GAUGE'
echo 'memory.graph yes'
;;
*)
pvstat memory 'bytes allocated$'
;;
esac

View file

@ -0,0 +1,183 @@
#! /usr/bin/perl
# Varnish cache hit ratio logger/plugin
# anders@fupp.net, 2007-09-19
# Log/data file
# These must have write permission to the user the plugin runs as
# On FreeBSD, that is nobody
# Comment $mylog out to skip logging
# Set to 1 if you want to show unknown requsts (client requests which are
# neither hits nor misses):
$showunknown = 1;
$mydat = "/var/tmp/varnish_cachehitratio.dat";
#$mylog = "/var/log/varnish_cachehitratio.log";
%stat = ();
$ENV{PATH} = "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin";
open(VV, "varnishstat -V 2>&1 |");
while (<VV>) {
if (/^varnishstat/) { $vversion = $_; }
}
close(VV);
chomp($vversion);
$vversion =~ s@varnishstat\s*@@;
$vversion =~ s@\(@@;
$vversion =~ s@\)@@;
$vversion =~ s@varnish-@@;
use Date::Format;
sub popstat10 {
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 popstat {
foreach $line (`varnishstat -1`) {
chomp($line);
if ($line =~ /^\w+\s+(\d+)\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";
if ($showunknown) {
print "graph_order hitratio missratio unknownratio\n";
} else {
print "graph_order hitratio missratio\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";
if ($showunknown) {
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 = (defined $stat{"client_requests_received"}) ? $stat{"client_requests_received"} : 0;
$nhits = (defined $stat{"cache_hits"}) ? $stat{"cache_hits"} : 0;
$nmisses = (defined $stat{"cache_misses"}) ? $stat{"cache_misses"} : 0;
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 ($hits > 0 || $misses > 0) {
$xhitratio = sprintf("%.2f", $hits / ($hits+$misses)*100);
$xmissratio = sprintf("%.2f", $misses / ($hits+$misses)*100);
} else {
$xhitratio = sprintf("%.2f", 100);
$xmissratio = 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));
}
if ($showunknown) {
print "hitratio.value $hitratio\n";
} else {
print "hitratio.value $xhitratio\n";
}
print "missratio.value $missratio\n";
if ($showunknown) {
print "unknownratio.value $unknownratio\n";
}
if ($mylog ne "") {
open(LOG, ">>$mylog");
if ($showunknown) {
print LOG "hitratio=$hitratio missratio=$missratio unknown=$unknownratio hits=$hits misses=$misses requests=$requests [" . time2str("%Y-%m-%d %H:%M:%S", time) . "]\n";
} else {
print LOG "hitratio=$hitratio missratio=$missratio hits=$hits misses=$misses requests=$requests [" . time2str("%Y-%m-%d %H:%M:%S", time) . "]\n";
}
close(LOG);
}
}
sub writevalues {
open(OVAL, ">$mydat");
# xhitratio is hitratio considering only hits and misses, not client
# requests
print OVAL "$nrequests $nhits $nmisses $hitratio $xhitratio\n";
close(OVAL);
}
if ($ARGV[0] eq "autoconf") {
print "yes\n";
} elsif ($ARGV[0] eq "config") {
printconfig;
} else {
if ($vversion =~ /^1\.0/) {
popstat10;
} else {
popstat;
}
findvalues;
printvalues;
writevalues;
}

View file

@ -0,0 +1,29 @@
#!/bin/sh
#Plugin to monitor the number of healthy and sick backends
#
#
ADMINSERVER=127.0.0.1
ADMINPORT=2000
if [ "$1" = "autoconf" ]; then
echo yes
exit 0
fi
if [ "$1" = "config" ]; then
echo 'graph_title Number of Healthy Backends'
echo 'graph_vlabel number of backends'
echo 'graph_category varnish'
echo 'graph_info This graph shows the number of healthy backends in the system.'
echo 'healthy.label Healthy'
echo 'healthy.warning 2:'
echo 'healthy.critical 1:'
echo 'sick.label Sick'
exit 0
fi
healthyServers=`varnishadm -T ${ADMINSERVER}:${ADMINPORT} debug.health 2>&1 | grep 'is Healthy' | wc -l`
sickServers=`varnishadm -T ${ADMINSERVER}:${ADMINPORT} debug.health 2>&1 | grep 'is sick' | wc -l`
echo "healthy.value ${healthyServers}"
echo "sick.value ${sickServers}"

36
plugins/varnish/varnish_hitrate Executable file
View file

@ -0,0 +1,36 @@
#! /bin/sh
# anders@aftenposten.no, 2007-09-19
# Shows the rate of requests (per second) for Varnish
PATH="$PATH:/usr/local/bin"
export PATH
vversion=`varnishstat -V 2>&1 | egrep "^varnishstat" | perl -p -e "s@varnishstat\s*@@;s@\(@@;s@\)@@;s@varnish-@@"`
pvstat() {
# $1: vname $2: grabstat
printf "$1.value "
case $vversion in
1.0*) varnishstat -1 | egrep "$2" | awk '{print $1}';;
*) varnishstat -1 | egrep "$2" | awk '{print $2}';;
esac
}
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.type DERIVE'
echo 'requests.min 0'
echo 'requests.graph yes'
;;
*)
pvstat requests 'Client requests received$'
;;
esac

View file

@ -0,0 +1,34 @@
#! /bin/sh
# anders@aftenposten.no, 2007-05-08
# Shows the total number of objects in Varnish cache
PATH="$PATH:/usr/local/bin"
export PATH
vversion=`varnishstat -V 2>&1 | egrep "^varnishstat" | perl -p -e "s@varnishstat\s*@@;s@\(@@;s@\)@@;s@varnish-@@"`
pvstat() {
# $1: vname $2: grabstat
printf "$1.value "
case $vversion in
1.0*) varnishstat -1 | egrep "$2" | awk '{print $1}';;
*) varnishstat -1 | egrep "$2" | awk '{print $2}';;
esac
}
case $1 in
autoconf) echo yes;;
config)
echo 'graph_title Objects'
echo 'graph_vlabel objects'
echo 'graph_category varnish'
echo 'graph_info This graph shows the total number of objects in Varnish cache'
echo 'objects.label objects'
echo 'objects.type GAUGE'
echo 'objects.graph yes'
;;
*)
pvstat objects 'N struct object$'
;;
esac