ISC BIND has no logo, so here is a fixed Duck I've stolen from their internets

ISC BIND has no logo, so here is a Fixed Duck I’ve stolen from their internets

Been some time I had a DNS server with enough zones and queries so I have to worry about the numbers. And oh boy the time flies. Even at ISC.
So, assuming you have a BIND 9.5 and above, there is this super new feature that didn’t even get yet to the man page of named.conf (not at rhel at least) and it is called statistics-channels which is an embedded HTTP server that serves an XML file. Right, with libxml2. And it is about 4k rows, 148KB in size. On a slave server with two zones. Better than nothing I say because the previous (years back) approach of appending to a text file is even worse.

So, how to get with nice peace of structured information? Easy, add this (not in options, just drop it at the top level):

statistics-channels {
inet 127.0.0.1 port 8123 allow { 127.0.0.1; };
};

to your bind’s config, reload and see what you’ve got:

curl http://127.0.0.1:8123 > stats.xml
wc stats.xml
4850 4858 144910 stats.xml
du -h stats.xml
148K stats.xml

in the received xml you can start searching for what you need, it is all there, queries, errors, memory, uptimes, etc.

From now on, YMMV, but I need info from there every 60 seconds and I hate to create load on the hosts I monitor by monitoring. I also hate chaining execs in monitoring.

So what are the options to get the info I want into my monitoring database? Without googling, you can try and parse indented XML files, with a very “friendly” structure like this

keyname
numbers

with many options, such as:

grep -A{N} '' | grep '' | sed 's/[^0-9]//g'

which is natural but a horrible solution because I don’t like it. Or with something more elegant like this:

pcregrep -N ANY -M -o  '(?<=Requestv.>;/name>sssssssssss<;counter>;)d+'

can’t say even if it works. Try at your own risk.
And probably many other even more creative options.

But to save the world from ugliness and laziness there is only one way to do that right. Write a Python script.
Or in Perl. That is what The Real Men do.

Quick and dirty, I use Zabbix and I have some code for submitting results and querying Zabbix API in Python. So this is what you want:

import sys, urllib2
from lxml import etree
def getXml(url):
req = urllib2.Request( url )
the_page = ""
try:
result = urllib2.urlopen(req)
the_page = result.read()
except Exception,e:
sys.stderr.write( "error calling %s : [%s]n"%(url,e) )
print the_page
return the_page

url = sys.argv[1]
try:
xml=etree.fromstring( getXml(url) )
counters=xml.xpath('/isc/bind/statistics/server/nsstat[name="Requestv4" or name="Requestv6"]/counter/text()')
print int( counters[0] ) + int( counters[1] )
except Exception, e:
sys.stderr.write( "error getting info from %s : [%s]n"%(url,e) )
print "-1"

This small wonder accepts the URL to the bind page, and prints to stdout the total number of queries (ipv4/ipv6) received by the server since it has started.
Considering the size and amount of information, you will probably want to get more values from the file and to add your own parsings to the script.

P.S. As a side note, this is how you achieve the same with PowerDNS:

echo $((`pdns_control show udp-queries`+`pdns_control show tcp-queries`))

Leave a Reply

Your email address will not be published. Required fields are marked *

Post Navigation