#!/usr/bin/perl # # Copyright Jean-Samuel Reynaud # Licensed under GPL v2 =head1 NAME bind95_ - Graph dns requests by type =head1 DESCRIPTION We use this script to produce graph with munin for dns requests. This version work with bind 9.5 Thanks to Benjamin Pineau for perl cleaning and corrections =head1 CONFIGURATION This script must have his name start with bind95_ =over 2 bind95_ : Global bind statistic bind95_test.com : Bind statistic for test.com zone (no view) bind95_test.com@internal : Bind statistic for test.com zone (view internal) =back You should have to add the following lines to you plugin configuration (/etc/munin/plugin-conf.d/munin-node): =over 2 [bind95_*] user root stat_file /var/cache/bind/named.stats rndc /usr/sbin/rndc =back =head1 MAGIC MARKERS #%# family=auto #%# capabilities=autoconf =head1 AUTHORS Jean-Samuel Reynaud Andreas Perhab =head1 LICENSE GPLv2 =cut use strict; use warnings; use Digest::MD5 qw(md5_hex); # change those to reflect your bind configuration (use plugin configuration) # stat file my $stat_file = $ENV{'stat_file'} || "/var/cache/bind/named.stats"; # rndc path my $rndc = $ENV{'rndc'} || "/usr/sbin/rndc"; my $domain = $0; if ($domain =~ m/^.*bind95_[\w\d\._\-]+@[\w\d\._\-]+?$/) { $domain =~ s/^.*bind95_([\w\d\._\-]*)@([\w\d\._\-]+)?$/$1 (view: $2)/; } elsif ($domain =~ m/^.*bind95_[\w\d\._\-]+$/) { $domain =~ s/^.*bind95_([\w\d\._\-]+)$/$1/; } else { $domain = "View: _bind"; } my @counters = ( 'IPv4 requests received', 'requests with EDNS(0) received', 'TCP requests received', 'auth queries rejected', 'recursive queries rejected', 'transfer requests rejected', 'update requests rejected', 'responses sent', 'truncated responses sent', 'responses with EDNS(0) sent', 'queries resulted in successful answer', 'queries resulted in authoritative answer', 'queries resulted in non authoritative answer', 'queries resulted in referral answer', 'queries resulted in nxrrset', 'queries resulted in SERVFAIL', 'queries resulted in NXDOMAIN', 'queries caused recursion', 'duplicate queries received', 'queries dropped', 'other query failures', 'requested transfers completed', 'transfer requests succeeded', 'IPv4 notifies sent', 'IPv4 notifies received', 'notifies rejected', 'IPv4 SOA queries sent', 'IPv4 IXFR requested' ); # Parse the statistic file sub parseFile { my @printed_counters = (); my $dom = shift @_; open(IN,"<$stat_file") or die "Can't open $stat_file : $!"; my $current_zone = ""; while () { chomp; my $l = $_; if ($l =~ /\[/ ) { $l =~ s/\[//g; $l =~ s/\]//g; $current_zone = $l; } else { $l =~ s/^ *//g; if ($l =~ /^[0-9]/ && $current_zone eq $domain) { my ($val,$desc) = split(' ',$l,2); if (grep { $desc eq $_ } @counters) { printf "%s.value %u\n",md5_hex($desc),$val; push @printed_counters, $desc; } } } } close(IN); foreach(@counters) { my $desc = $_; my @already_printed = grep { $desc eq $_ } @printed_counters; if (!@already_printed) { printf "%s.value 0\n", md5_hex($desc); } } } # Config mode if ( defined($ARGV[0]) && $ARGV[0] eq "config" ) { printf "graph_title Dns requests %s\n",($domain eq "View: _bind" ? " all domains":$domain); printf "graph_vlabel requests/s\n"; printf "graph_category dns\n"; printf "graph_info This graph display dns requests for %s\n",($domain eq "View: _bind" ? "all domains":$domain); foreach(@counters) { my $s = $_; printf "%s.label %s\n",md5_hex($s),$s; printf "%s.type DERIVE\n",md5_hex($s); printf "%s.min 0\n",md5_hex($s); } exit 0; } if ( defined($ARGV[0]) && $ARGV[0] eq "autoconf" ) { if (! -f $stat_file) { printf "no (Unable to file bind stat file on %s)",$stat_file; exit 0; } if (! -f $rndc) { printf "no (Unable to file rndc tool (configured : %s))",$rndc; exit 0; } exit 0; } # Remove old stat file unlink ($stat_file); # Ask to bind to build new one `$rndc stats`; # Parse the stat file and return result parseFile($domain);