#!/usr/bin/perl # Original idea from Internet by Evan Hoffman: # # http://www.evanhoffman.com/evan/2010/12/13/more-fun-parsing-bind-query-logs/#more-978 # # Modifications by Dusan Baljevic on 8 February 2011 # dusan.baljevic@ieee.org # # To enable BIND stats, edit named.conf and add: # # logging # { # ... # channel query-log { # file "/var/log/query-log" versions 3 size 10m; # print-time yes; # }; # category queries { query-log; }; # }; # options # { # ... # querylog yes; # }; # Description: Summarize queries per second for BIND DNS # Usage: bind-qps-calc.pl /var/named/chroot/var/log/query-log # # If you obtain this script via Web, convert it to Unix format. # Define important environment variables # $ENV{'PATH'} = "/bin:/usr/sbin:/sbin:/usr/bin"; $ENV{'PATH'} = "$ENV{PATH}:/usr/local/bin:/usr/lbin:/usr/local/sbin"; # Enforce strictness # if ( eval "require strict" ) { import strict; use strict; } else { print "WARN: Perl strict not found\n"; } # Check Perl code # #use diagnostics; #use warnings; use Time::ParseDate; my $line_num = 0; my $first_line = 0; my @dnsrecord = (); my $oldest_record = 0; my $line = ''; my $date = 0; my $dnsdate = q{}; my $dnstime = q{}; my $dnsrr = q{}; my $max_rate = 0.0; my $min_rate = 9999999.0; my %query_counter = {}; my %rr_counter = {}; my @abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ); while (<>) { chomp; $line = $_; # On my DNS servers with enabled views, log lines look like: # # 10-Feb-2011 19:44:29.068 client 127.0.0.1#59023: view internal-view: query: googleads.g.doubleclick.net IN A + (127.0.0.1) # 10-Feb-2011 19:47:14.198 client 127.0.0.1#59023: view internal-view: query: s.youtube.com IN AAAA + (127.0.0.1) # 10-Feb-2011 19:47:39.101 client 207.46.200.38#61603: view external-view: query: blah.dom IN A - (192.168.1.102) # @dnsrecord = split(/\s+/, $_); $dnsdate = $dnsrecord[0]; $dnstime = $dnsrecord[1]; if (grep(/\)$/, $line)) { $dnsrr = $dnsrecord[-3]; } else { $dnsrr = $dnsrecord[-2]; } $rr_counter{$dnsrr}++; $date = parsedate("$dnsdate $dnstime"); if ($oldest_record == 0) { $oldest_record = $date; $first_line = $line_num; print "First line:\t$line_num\tdate\t".localtime($date)."\n"; } my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($date); $year += 1900; $mon += 1; my $key = $year . '-' . sprintf('%02d',$mon) . '-' . sprintf('%02d',$mday). ' '.sprintf('%02d',$hour).':00 to '.sprintf('%02d',$hour).':59' ; if ($query_counter{$key}) { $query_counter{$key}++; } else { $query_counter{$key} = 1; } $line_num++; } print "Last line:\t$line_num\tdate\t".localtime($date)."\n"; my $elapsed = $date - $oldest_record; my $net_records = $line_num - $first_line; my $rate = q{}; if ("$net_records") { $rate = ($net_records * 1.0) / $elapsed; print "Query rate for $elapsed seconds: ".sprintf('%0.2f',$rate)." per second\n"; } foreach my $key (sort keys %query_counter) { $rate = ($query_counter{$key} * 1.0) / 3600; if ($rate > $max_rate) { $max_rate = $rate; } if ($rate > 0 && $rate < $min_rate) { $min_rate = $rate; } } my $stars = 30; my $star_factor = int($stars / $max_rate); print "\nResource Record Summary:\n"; foreach my $rrkey (sort keys %rr_counter) { if ($rr_counter{$rrkey}) { print "".sprintf('%12s', $rrkey)." records queried ".sprintf('%12d', $rr_counter{$rrkey})." times\n"; } } print "\nQueries Per Second (QPS) Summary:\n"; foreach my $key (sort keys %query_counter) { if ( "$query_counter{$key}" ) { $rate = ($query_counter{$key} * 1.0) / 3600; print "$key => ".sprintf('%12d', $query_counter{$key}).", rate ".sprintf('%0.2f',$rate)." queries/sec\t"; for ($i = 0; $i < ($star_factor * $rate); $i++) { print '*'; } print "\n"; } } exit 0;