Stats
Niall O'Reilly
Niall.oReilly at ucd.ie
Fri Mar 27 14:42:02 UTC 2009
On Fri, 2009-03-27 at 09:25 -0400, John D. Vo wrote:
> What do you guys use to turn this:
> --- Statistics Dump --- (1238151600)
> +++ Statistics Dump +++ (1238155200)
> success 3280261
> referral 363
> nxrrset 745513
> nxdomain 392614
> recursion 1173408
> failure 1115632
> --- Statistics Dump --- (1238155200)
The following works (for me!) with either this (above) format
of dump or the richer format used in more recent BIND releases.
I'm not certain that the statistics selected for processing in
each case correspond exactly. I think they're pretty close.
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my $PROG = $0; $PROG =~ s|.*/||;
# Configuration
my $Config = {
statpath => '/var/named/run',
statfilename => 'named.stats',
probe => [ qw( /usr/local/sbin/rndc stats ) ],
};
my $State = {
skip => 0,
time => undef,
chain => [ { } ],
};
my $x;
# Result
my $MRTGdata = {
in => '-1',
out => '-1',
uptime => '0',
name => '0'
};
# Check that statpath directory exists
$x = $Config->{statpath};
-d $x or die(sprintf("%s: %s: %s\n", $PROG, $!, $x));
# Check that probe binary is a file and executable
$x = $Config->{probe}->[0];
(-f $x and -x $x) or die(sprintf("%s: %s: %s\n", $PROG, $!, $x));
# Save current size of file, if it exists
my $file = join('/', map { $Config->{$_} } (qw(statpath statfilename)));
$State->{skip} = (stat($file))[7] if ( -f $file );
# Save current time
$State->{'time'} = time();
# Issue probe
open(PROBE, '-|', @{$Config->{probe}})
or die "$PROG: $!\n";
close PROBE;
# Collect data
open(FILE, '<', $file)
or die(sprintf("%s: %s: %s\n", $PROG, $!, $file));
$State->{size} = (stat(FILE))[7];
seek(FILE,$State->{skip},0) if $State->{size} > $State->{skip};
my @stats = <FILE>;
close FILE;
# Process stats
# warn join('', @stats);
for ( my ($i, $j, $phase, $stamp, $bucket) = (0, 0, 'IDLE');
$i < scalar(@stats);
$i++ ) {
my $line = $stats[$i];
if ( $line =~ /^\++\s+Statistics Dump\s+\++\s+\((\d+)\)/ ) {
$stamp = $1;
if ($stamp >= $State->{time}) {
$phase = $stamp;
$bucket = $State->{chain}->[++$j] = [ ];
$State->{chain}->[0]->{$phase} = $j;
push @$bucket, $i;
}
}
if ($phase eq 'IDLE') {
# warn "$PROG: skipping: ", $line;
next;
}
if ( $line =~ /^-+\s+Statistics Dump\s+-+\s+\((\d+)\)/ ) {
$stamp = $1;
if ($stamp eq $phase) {
push @$bucket, $i;
$State->{chain}->[0]->{last} = $State->{chain}->[0]->{$phase};
$phase = 'IDLE';
}
}
}
foreach my $chain ( $State->{chain} ) {
my $last = $chain->[0]->{last};
last unless defined $last;
my ($lo, $hi) = @{$chain->[$last]};
# warn sprintf("%s: scanning lines %d - %d\n", $PROG, $lo, $hi);
my $format = ( $stats[++$lo] =~ /^\+/ ) ? 'new' : 'old';
# warn "$PROG: format: $format\n";
# Analyze new format
if ($format eq 'new') {
$MRTGdata->{in} = 0;
$MRTGdata->{out} = 0;
my $group = '';
foreach ( @stats[$lo .. $hi] ) {
$group = $1 if /^\++ (.*) \++/;
next unless $group eq 'Name Server Statistics';
$MRTGdata->{in} += $1 if /\s+(\d+) IPv4 requests received/;
$MRTGdata->{out} += $1 if /\s+(\d+) queries resulted in non authoritative answer/;
}
}
# Analyze old format
elsif ($format eq 'old') {
$MRTGdata->{in} = 0;
$MRTGdata->{out} = 0;
foreach ( @stats[$lo .. $hi] ) {
$MRTGdata->{in} += $1 if /^success (\d+)/;
$MRTGdata->{in} += $1 if /^referral (\d+)/;
$MRTGdata->{in} += $1 if /^nxrrset (\d+)/;
$MRTGdata->{in} += $1 if /^nxdomain (\d+)/;
$MRTGdata->{in} += $1 if /^failure (\d+)/;
$MRTGdata->{out} += $1 if /^recursion (\d+)/;
}
}
}
# Present result as expected by MRTG
map {
printf "%s\n", $MRTGdata->{$_}
} ( qw(in out uptime name) );
print "\n";
More information about the bind-users
mailing list