#! /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 () { 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 = ; 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; }