Paul Wouters 4c0de48
#!/bin/sh
Paul Wouters 4c0de48
#
Paul Wouters 4c0de48
# plugin for munin to monitor usage of unbound servers.
Paul Wouters 4c0de48
#
Paul Wouters 4c0de48
# (C) 2008 W.C.A. Wijngaards.  BSD Licensed.
Paul Wouters 4c0de48
#
Paul Wouters 4c0de48
# To install; enable statistics and unbound-control in unbound.conf
Paul Wouters 4c0de48
#	server:		extended-statistics: yes
Paul Wouters 4c0de48
#			statistics-cumulative: no
Paul Wouters 4c0de48
#			statistics-interval: 0
Paul Wouters 4c0de48
#	remote-control:	control-enable: yes
Paul Wouters 4c0de48
# Run the command unbound-control-setup to generate the key files.
Paul Wouters 4c0de48
#
Paul Wouters 4c0de48
# Environment variables for this script
Paul Wouters 4c0de48
#	statefile	- where to put temporary statefile.
Paul Wouters 4c0de48
#	unbound_conf	- where the unbound.conf file is located.
Paul Wouters 4c0de48
#	unbound_control	- where to find unbound-control executable.
Paul Wouters 4c0de48
#	spoof_warn	- what level to warn about spoofing
Paul Wouters 4c0de48
#	spoof_crit	- what level to crit about spoofing
Paul Wouters 4c0de48
#
Paul Wouters 4c0de48
# You can set them in your munin/plugin-conf.d/plugins.conf file
Paul Wouters 4c0de48
# with:
Paul Wouters 4c0de48
# [unbound*]
Paul Wouters 4c0de48
# user root
Paul Wouters 4c0de48
# env.statefile /usr/local/var/munin/plugin-state/unbound-state
Paul Wouters 4c0de48
# env.unbound_conf /usr/local/etc/unbound/unbound.conf
Paul Wouters 4c0de48
# env.unbound_control /usr/local/sbin/unbound-control
Paul Wouters 4c0de48
# env.spoof_warn 1000
Paul Wouters 4c0de48
# env.spoof_crit 100000
Paul Wouters 4c0de48
#
Paul Wouters 4c0de48
# This plugin can create different graphs depending on what name
Paul Wouters 4c0de48
# you link it as (with ln -s) into the plugins directory
Paul Wouters 4c0de48
# You can link it multiple times.
Paul Wouters 4c0de48
# If you are only a casual user, the _hits and _by_type are most interesting,
Paul Wouters 4c0de48
# possibly followed by _by_rcode.
Paul Wouters 4c0de48
#
Paul Wouters 4c0de48
#	unbound_munin_hits	- base volume, cache hits, unwanted traffic
Paul Wouters 4c0de48
#	unbound_munin_queue	- to monitor the internal requestlist
Paul Wouters 4c0de48
#	unbound_munin_memory	- memory usage
Paul Wouters 4c0de48
#	unbound_munin_by_type	- incoming queries by type
Paul Wouters 4c0de48
#	unbound_munin_by_class	- incoming queries by class
Paul Wouters 4c0de48
#	unbound_munin_by_opcode	- incoming queries by opcode
Paul Wouters 4c0de48
#	unbound_munin_by_rcode	- answers by rcode, validation status
Paul Wouters 4c0de48
#	unbound_munin_by_flags	- incoming queries by flags
Paul Wouters 4c0de48
#	unbound_munin_histogram	- histogram of query resolving times
Paul Wouters 4c0de48
#
Paul Wouters 4c0de48
# Magic markers - optional - used by installation scripts and
Paul Wouters 4c0de48
# munin-config:
Paul Wouters 4c0de48
#
Paul Wouters 4c0de48
#%# family=contrib
Paul Wouters 4c0de48
#%# capabilities=autoconf suggest
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# POD documentation
Paul Wouters 4c0de48
: <<=cut
Paul Wouters 4c0de48
=head1 NAME
Paul Wouters 4c0de48
Paul Wouters 4c0de48
unbound_munin_ - Munin plugin to monitor the Unbound DNS resolver.
Paul Wouters 4c0de48
Paul Wouters 4c0de48
=head1 APPLICABLE SYSTEMS
Paul Wouters 4c0de48
Paul Wouters 4c0de48
System with unbound daemon.
Paul Wouters 4c0de48
Paul Wouters 4c0de48
=head1 CONFIGURATION
Paul Wouters 4c0de48
Paul Wouters 4c0de48
  [unbound*]
Paul Wouters 4c0de48
  user root
Paul Wouters 4c0de48
  env.statefile /var/lib/munin/plugin-state/unbound-state
Paul Wouters 4c0de48
  env.unbound_conf /etc/unbound/unbound.conf
Paul Wouters 4c0de48
  env.unbound_control /usr/sbin/unbound-control
Paul Wouters 4c0de48
  env.spoof_warn 1000
Paul Wouters 4c0de48
  env.spoof_crit 100000
Paul Wouters 4c0de48
Paul Wouters 4c0de48
Use the .env settings to override the defaults.
Paul Wouters 4c0de48
Paul Wouters 4c0de48
=head1 USAGE
Paul Wouters 4c0de48
Paul Wouters 4c0de48
Can be used to present different graphs. Use ln -s for that name in
Paul Wouters 4c0de48
the plugins directory to enable the graph.
Paul Wouters 4c0de48
unbound_munin_hits	- base volume, cache hits, unwanted traffic
Paul Wouters 4c0de48
unbound_munin_queue	- to monitor the internal requestlist
Paul Wouters 4c0de48
unbound_munin_memory	- memory usage
Paul Wouters 4c0de48
unbound_munin_by_type	- incoming queries by type
Paul Wouters 4c0de48
unbound_munin_by_class	- incoming queries by class
Paul Wouters 4c0de48
unbound_munin_by_opcode	- incoming queries by opcode
Paul Wouters 4c0de48
unbound_munin_by_rcode	- answers by rcode, validation status
Paul Wouters 4c0de48
unbound_munin_by_flags	- incoming queries by flags
Paul Wouters 4c0de48
unbound_munin_histogram - histogram of query resolving times
Paul Wouters 4c0de48
Paul Wouters 4c0de48
=head1 AUTHOR
Paul Wouters 4c0de48
Paul Wouters 4c0de48
Copyright 2008 W.C.A. Wijngaards
Paul Wouters 4c0de48
Paul Wouters 4c0de48
=head1 LICENSE
Paul Wouters 4c0de48
Paul Wouters 4c0de48
BSD
Paul Wouters 4c0de48
Paul Wouters 4c0de48
=cut
Paul Wouters 4c0de48
Paul Wouters 4c0de48
state=${statefile:-/var/lib/munin/plugin-state/unbound-state}
Paul Wouters 4c0de48
conf=${unbound_conf:-/etc/unbound/unbound.conf}
Paul Wouters 4c0de48
ctrl=${unbound_control:-/usr/sbin/unbound-control}
Paul Wouters 4c0de48
warn=${spoof_warn:-1000}
Paul Wouters 4c0de48
crit=${spoof_crit:-100000}
Paul Wouters 4c0de48
lock=$state.lock
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# number of seconds between polling attempts.
Paul Wouters 4c0de48
# makes the statefile hang around for at least this many seconds,
Paul Wouters 4c0de48
# so that multiple links of this script can share the results.
Paul Wouters 4c0de48
lee=55
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# to keep things within 19 characters
Paul Wouters 4c0de48
ABBREV="-e s/total/t/ -e s/thread/t/ -e s/num/n/ -e s/query/q/ -e s/answer/a/ -e s/unwanted/u/ -e s/requestlist/ql/ -e s/type/t/ -e s/class/c/ -e s/opcode/o/ -e s/rcode/r/ -e s/edns/e/ -e s/mem/m/ -e s/cache/c/ -e s/mod/m/"
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# get value from $1 into return variable $value
Paul Wouters 4c0de48
get_value ( ) {
Paul Wouters 4c0de48
	value="`grep '^'$1'=' $state | sed -e 's/^.*=//'`"
Paul Wouters 4c0de48
	if test "$value"x = ""x; then
Paul Wouters 4c0de48
		value="0"
Paul Wouters 4c0de48
	fi
Paul Wouters 4c0de48
}
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# download the state from the unbound server.
Paul Wouters 4c0de48
get_state ( ) {
Paul Wouters 4c0de48
	# obtain lock for fetching the state
Paul Wouters 4c0de48
	# because there is a race condition in fetching and writing to file
Paul Wouters 4c0de48
Paul Wouters 4c0de48
	# see if the lock is stale, if so, take it 
Paul Wouters 4c0de48
	if test -f $lock ; then
Paul Wouters 4c0de48
		pid="`cat $lock 2>&1`"
Paul Wouters 4c0de48
		kill -0 "$pid" >/dev/null 2>&1
Paul Wouters 4c0de48
		if test $? -ne 0 -a "$pid" != $$ ; then
Paul Wouters 4c0de48
			echo $$ >$lock
Paul Wouters 4c0de48
		fi
Paul Wouters 4c0de48
	fi
Paul Wouters 4c0de48
Paul Wouters 4c0de48
	i=0
Paul Wouters 4c0de48
	while test ! -f $lock || test "`cat $lock 2>&1`" != $$; do
Paul Wouters 4c0de48
		while test -f $lock; do
Paul Wouters 4c0de48
			# wait
Paul Wouters 4c0de48
			i=`expr $i + 1`
Paul Wouters 4c0de48
			if test $i -gt 1000; then
Paul Wouters 4c0de48
				sleep 1;
Paul Wouters 4c0de48
			fi
Paul Wouters 4c0de48
			if test $i -gt 1500; then
Paul Wouters 4c0de48
				echo "error locking $lock" "=" `cat $lock`
Paul Wouters 4c0de48
				rm -f $lock
Paul Wouters 4c0de48
				exit 1
Paul Wouters 4c0de48
			fi
Paul Wouters 4c0de48
		done
Paul Wouters 4c0de48
		# try to get it
Paul Wouters 4c0de48
		echo $$ >$lock
Paul Wouters 4c0de48
	done
Paul Wouters 4c0de48
	# do not refetch if the file exists and only LEE seconds old
Paul Wouters 4c0de48
	if test -f $state; then
Paul Wouters 4c0de48
		now=`date +%s`
Paul Wouters 4c0de48
		get_value "time.now"
Paul Wouters 4c0de48
		value="`echo $value | sed -e 's/\..*$//'`"
Paul Wouters 4c0de48
		if test $now -lt `expr $value + $lee`; then
Paul Wouters 4c0de48
			rm -f $lock
Paul Wouters 4c0de48
			return
Paul Wouters 4c0de48
		fi
Paul Wouters 4c0de48
	fi
Paul Wouters 4c0de48
	$ctrl -c $conf stats > $state
Paul Wouters 4c0de48
	if test $? -ne 0; then
Paul Wouters 4c0de48
		echo "error retrieving data from unbound server"
Paul Wouters 4c0de48
		rm -f $lock
Paul Wouters 4c0de48
		exit 1
Paul Wouters 4c0de48
	fi
Paul Wouters 4c0de48
	rm -f $lock
Paul Wouters 4c0de48
}
Paul Wouters 4c0de48
Paul Wouters 4c0de48
if test "$1" = "autoconf" ; then
Paul Wouters 4c0de48
	if test ! -f $conf; then
Paul Wouters 4c0de48
		echo no "($conf does not exist)"
Paul Wouters 4c0de48
		exit 1
Paul Wouters 4c0de48
	fi
Paul Wouters 4c0de48
	if test ! -d `dirname $state`; then
Paul Wouters 4c0de48
		echo no "($state directory does not exist)"
Paul Wouters 4c0de48
		exit 1
Paul Wouters 4c0de48
	fi
Paul Wouters 4c0de48
	echo yes
Paul Wouters 4c0de48
	exit 0
Paul Wouters 4c0de48
fi
Paul Wouters 4c0de48
Paul Wouters 4c0de48
if test "$1" = "suggest" ; then
Paul Wouters 4c0de48
	echo "hits"
Paul Wouters 4c0de48
	echo "queue"
Paul Wouters 4c0de48
	echo "memory"
Paul Wouters 4c0de48
	echo "by_type"
Paul Wouters 4c0de48
	echo "by_class"
Paul Wouters 4c0de48
	echo "by_opcode"
Paul Wouters 4c0de48
	echo "by_rcode"
Paul Wouters 4c0de48
	echo "by_flags"
Paul Wouters 4c0de48
	echo "histogram"
Paul Wouters 4c0de48
	exit 0
Paul Wouters 4c0de48
fi
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# determine my type, by name
Paul Wouters 4c0de48
id=`echo $0 | sed -e 's/^.*unbound_munin_//'`
Paul Wouters 4c0de48
if test "$id"x = ""x; then
Paul Wouters 4c0de48
	# some default to keep people sane.
Paul Wouters 4c0de48
	id="hits"
Paul Wouters 4c0de48
fi
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# if $1 exists in statefile, config is echoed with label $2
Paul Wouters 4c0de48
exist_config ( ) {
Paul Wouters 4c0de48
	mn=`echo $1 | sed $ABBREV | tr . _`
Paul Wouters 4c0de48
	if grep '^'$1'=' $state >/dev/null 2>&1; then
Paul Wouters 4c0de48
		echo "$mn.label $2"
Paul Wouters 4c0de48
		echo "$mn.min 0"
Paul Wouters 4c0de48
	fi
Paul Wouters 4c0de48
}
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# print label and min 0 for a name $1 in unbound format
Paul Wouters 4c0de48
p_config ( ) {
Paul Wouters 4c0de48
	mn=`echo $1 | sed $ABBREV | tr . _`
Paul Wouters 4c0de48
	echo $mn.label "$2"
Paul Wouters 4c0de48
	echo $mn.min 0
Paul Wouters 4c0de48
}
Paul Wouters 4c0de48
Paul Wouters 4c0de48
if test "$1" = "config" ; then
Paul Wouters 4c0de48
	if test ! -f $state; then
Paul Wouters 4c0de48
		get_state
Paul Wouters 4c0de48
	fi
Paul Wouters 4c0de48
	case $id in
Paul Wouters 4c0de48
	hits)
Paul Wouters 4c0de48
		echo "graph_title Unbound DNS traffic and cache hits"
Paul Wouters 4c0de48
		echo "graph_args --base 1000 -l 0"
Paul Wouters 4c0de48
		echo "graph_vlabel queries / second"
Paul Wouters 4c0de48
		echo "graph_category DNS"
Paul Wouters 4c0de48
		for x in thread0.num.queries thread1.num.queries \
Paul Wouters 4c0de48
		thread2.num.queries thread3.num.queries thread4.num.queries \
Paul Wouters 4c0de48
		thread5.num.queries thread6.num.queries thread7.num.queries; do
Paul Wouters 4c0de48
			exist_config $x "queries handled by `basename $x .num.queries`"
Paul Wouters 4c0de48
		done
Paul Wouters 4c0de48
		p_config "total.num.queries" "total queries from clients"
Paul Wouters 4c0de48
		p_config "total.num.cachehits" "cache hits"
Paul Wouters 4c0de48
		p_config "total.num.prefetch" "cache prefetch"
Paul Wouters 4c0de48
		p_config "num.query.tcp" "TCP queries"
Paul Wouters 4c0de48
		p_config "num.query.ipv6" "IPv6 queries"
Paul Wouters 4c0de48
		p_config "unwanted.queries" "queries that failed acl"
Paul Wouters 4c0de48
		p_config "unwanted.replies" "unwanted or unsolicited replies"
Paul Wouters 4c0de48
		echo "u_replies.warning $warn"
Paul Wouters 4c0de48
		echo "u_replies.critical $crit"
Paul Wouters 4c0de48
		echo "graph_info DNS queries to the recursive resolver. The unwanted replies could be innocent duplicate packets, late replies, or spoof threats."
Paul Wouters 4c0de48
		;;
Paul Wouters 4c0de48
	queue)
Paul Wouters 4c0de48
		echo "graph_title Unbound requestlist size"
Paul Wouters 4c0de48
		echo "graph_args --base 1000 -l 0"
Paul Wouters 4c0de48
		echo "graph_vlabel number of queries"
Paul Wouters 4c0de48
		echo "graph_category DNS"
Paul Wouters 4c0de48
		p_config "total.requestlist.avg" "Average size of queue on insert"
Paul Wouters 4c0de48
		p_config "total.requestlist.max" "Max size of queue (in 5 min)"
Paul Wouters 4c0de48
		p_config "total.requestlist.overwritten" "Number of queries replaced by new ones"
Paul Wouters 4c0de48
		p_config "total.requestlist.exceeded" "Number of queries dropped due to lack of space"
Paul Wouters 4c0de48
		echo "graph_info The queries that did not hit the cache and need recursion service take up space in the requestlist. If there are too many queries, first queries get overwritten, and at last resort dropped."
Paul Wouters 4c0de48
		;;
Paul Wouters 4c0de48
	memory)
Paul Wouters 4c0de48
		echo "graph_title Unbound memory usage"
Paul Wouters 4c0de48
		echo "graph_args --base 1024 -l 0"
Paul Wouters 4c0de48
		echo "graph_vlabel memory used in bytes"
Paul Wouters 4c0de48
		echo "graph_category DNS"
Paul Wouters 4c0de48
		p_config "mem.total.sbrk" "Total memory"
Paul Wouters 4c0de48
		p_config "mem.cache.rrset" "RRset cache memory"
Paul Wouters 4c0de48
		p_config "mem.cache.message" "Message cache memory"
Paul Wouters 4c0de48
		p_config "mem.mod.iterator" "Iterator module memory"
Paul Wouters 4c0de48
		p_config "mem.mod.validator" "Validator module and key cache memory"
Paul Wouters 4c0de48
		echo "graph_info The memory used by unbound."
Paul Wouters 4c0de48
		;;
Paul Wouters 4c0de48
	by_type)
Paul Wouters 4c0de48
		echo "graph_title Unbound DNS queries by type"
Paul Wouters 4c0de48
		echo "graph_args --base 1000 -l 0"
Paul Wouters 4c0de48
		echo "graph_vlabel queries / second"
Paul Wouters 4c0de48
		echo "graph_category DNS"
Paul Wouters 4c0de48
		for x in `grep "^num.query.type" $state`; do
Paul Wouters 4c0de48
			nm=`echo $x | sed -e 's/=.*$//'`
Paul Wouters 4c0de48
			tp=`echo $nm | sed -e s/num.query.type.//`
Paul Wouters 4c0de48
			p_config "$nm" "$tp"
Paul Wouters 4c0de48
		done
Paul Wouters 4c0de48
		echo "graph_info queries by DNS RR type queried for"
Paul Wouters 4c0de48
		;;
Paul Wouters 4c0de48
	by_class)
Paul Wouters 4c0de48
		echo "graph_title Unbound DNS queries by class"
Paul Wouters 4c0de48
		echo "graph_args --base 1000 -l 0"
Paul Wouters 4c0de48
		echo "graph_vlabel queries / second"
Paul Wouters 4c0de48
		echo "graph_category DNS"
Paul Wouters 4c0de48
		for x in `grep "^num.query.class" $state`; do
Paul Wouters 4c0de48
			nm=`echo $x | sed -e 's/=.*$//'`
Paul Wouters 4c0de48
			tp=`echo $nm | sed -e s/num.query.class.//`
Paul Wouters 4c0de48
			p_config "$nm" "$tp"
Paul Wouters 4c0de48
		done
Paul Wouters 4c0de48
		echo "graph_info queries by DNS RR class queried for."
Paul Wouters 4c0de48
		;;
Paul Wouters 4c0de48
	by_opcode)
Paul Wouters 4c0de48
		echo "graph_title Unbound DNS queries by opcode"
Paul Wouters 4c0de48
		echo "graph_args --base 1000 -l 0"
Paul Wouters 4c0de48
		echo "graph_vlabel queries / second"
Paul Wouters 4c0de48
		echo "graph_category DNS"
Paul Wouters 4c0de48
		for x in `grep "^num.query.opcode" $state`; do
Paul Wouters 4c0de48
			nm=`echo $x | sed -e 's/=.*$//'`
Paul Wouters 4c0de48
			tp=`echo $nm | sed -e s/num.query.opcode.//`
Paul Wouters 4c0de48
			p_config "$nm" "$tp"
Paul Wouters 4c0de48
		done
Paul Wouters 4c0de48
		echo "graph_info queries by opcode in the query packet."
Paul Wouters 4c0de48
		;;
Paul Wouters 4c0de48
	by_rcode)
Paul Wouters 4c0de48
		echo "graph_title Unbound DNS answers by return code"
Paul Wouters 4c0de48
		echo "graph_args --base 1000 -l 0"
Paul Wouters 4c0de48
		echo "graph_vlabel answer packets / second"
Paul Wouters 4c0de48
		echo "graph_category DNS"
Paul Wouters 4c0de48
		for x in `grep "^num.answer.rcode" $state`; do
Paul Wouters 4c0de48
			nm=`echo $x | sed -e 's/=.*$//'`
Paul Wouters 4c0de48
			tp=`echo $nm | sed -e s/num.answer.rcode.//`
Paul Wouters 4c0de48
			p_config "$nm" "$tp"
Paul Wouters 4c0de48
		done
Paul Wouters 4c0de48
		p_config "num.answer.secure" "answer secure"
Paul Wouters 4c0de48
		p_config "num.answer.bogus" "answer bogus"
Paul Wouters 4c0de48
		p_config "num.rrset.bogus" "num rrsets marked bogus"
Paul Wouters 4c0de48
		echo "graph_info answers sorted by return value. rrsets bogus is the number of rrsets marked bogus per second by the validator"
Paul Wouters 4c0de48
		;;
Paul Wouters 4c0de48
	by_flags)
Paul Wouters 4c0de48
		echo "graph_title Unbound DNS incoming queries by flags"
Paul Wouters 4c0de48
		echo "graph_args --base 1000 -l 0"
Paul Wouters 4c0de48
		echo "graph_vlabel queries / second"
Paul Wouters 4c0de48
		echo "graph_category DNS"
Paul Wouters 4c0de48
		p_config "num.query.flags.QR" "QR (query reply) flag"
Paul Wouters 4c0de48
		p_config "num.query.flags.AA" "AA (auth answer) flag"
Paul Wouters 4c0de48
		p_config "num.query.flags.TC" "TC (truncated) flag"
Paul Wouters 4c0de48
		p_config "num.query.flags.RD" "RD (recursion desired) flag"
Paul Wouters 4c0de48
		p_config "num.query.flags.RA" "RA (rec avail) flag"
Paul Wouters 4c0de48
		p_config "num.query.flags.Z" "Z (zero) flag"
Paul Wouters 4c0de48
		p_config "num.query.flags.AD" "AD (auth data) flag"
Paul Wouters 4c0de48
		p_config "num.query.flags.CD" "CD (check disabled) flag"
Paul Wouters 4c0de48
		p_config "num.query.edns.present" "EDNS OPT present"
Paul Wouters 4c0de48
		p_config "num.query.edns.DO" "DO (DNSSEC OK) flag"
Paul Wouters 4c0de48
		echo "graph_info This graphs plots the flags inside incoming queries. For example, if QR, AA, TC, RA, Z flags are set, the query can be rejected. RD, AD, CD and DO are legitimately set by some software."
Paul Wouters 4c0de48
		;;
Paul Wouters 4c0de48
	histogram)
Paul Wouters 4c0de48
		echo "graph_title Unbound DNS histogram of reply time"
Paul Wouters 4c0de48
		echo "graph_args --base 1000 -l 0"
Paul Wouters 4c0de48
		echo "graph_vlabel queries / second"
Paul Wouters 4c0de48
		echo "graph_category DNS"
Paul Wouters 4c0de48
		echo hcache.label "cache hits"
Paul Wouters 4c0de48
		echo hcache.min 0
Paul Wouters 4c0de48
		echo hcache.draw AREA
Paul Wouters 4c0de48
		echo hcache.colour 999999
Paul Wouters 4c0de48
		echo h64ms.label "0 msec - 66 msec"
Paul Wouters 4c0de48
		echo h64ms.min 0
Paul Wouters 4c0de48
		echo h64ms.draw STACK
Paul Wouters 4c0de48
		echo h64ms.colour 0000FF
Paul Wouters 4c0de48
		echo h128ms.label "66 msec - 131 msec"
Paul Wouters 4c0de48
		echo h128ms.min 0
Paul Wouters 4c0de48
		echo h128ms.colour 1F00DF
Paul Wouters 4c0de48
		echo h128ms.draw STACK
Paul Wouters 4c0de48
		echo h256ms.label "131 msec - 262 msec"
Paul Wouters 4c0de48
		echo h256ms.min 0
Paul Wouters 4c0de48
		echo h256ms.draw STACK
Paul Wouters 4c0de48
		echo h256ms.colour 3F00BF
Paul Wouters 4c0de48
		echo h512ms.label "262 msec - 524 msec"
Paul Wouters 4c0de48
		echo h512ms.min 0
Paul Wouters 4c0de48
		echo h512ms.draw STACK
Paul Wouters 4c0de48
		echo h512ms.colour 5F009F
Paul Wouters 4c0de48
		echo h1s.label "524 msec - 1 sec"
Paul Wouters 4c0de48
		echo h1s.min 0
Paul Wouters 4c0de48
		echo h1s.draw STACK
Paul Wouters 4c0de48
		echo h1s.colour 7F007F
Paul Wouters 4c0de48
		echo h2s.label "1 sec - 2 sec"
Paul Wouters 4c0de48
		echo h2s.min 0
Paul Wouters 4c0de48
		echo h2s.draw STACK
Paul Wouters 4c0de48
		echo h2s.colour 9F005F
Paul Wouters 4c0de48
		echo h4s.label "2 sec - 4 sec"
Paul Wouters 4c0de48
		echo h4s.min 0
Paul Wouters 4c0de48
		echo h4s.draw STACK
Paul Wouters 4c0de48
		echo h4s.colour BF003F
Paul Wouters 4c0de48
		echo h8s.label "4 sec - 8 sec"
Paul Wouters 4c0de48
		echo h8s.min 0
Paul Wouters 4c0de48
		echo h8s.draw STACK
Paul Wouters 4c0de48
		echo h8s.colour DF001F
Paul Wouters 4c0de48
		echo h16s.label "8 sec - ..."
Paul Wouters 4c0de48
		echo h16s.min 0
Paul Wouters 4c0de48
		echo h16s.draw STACK
Paul Wouters 4c0de48
		echo h16s.colour FF0000
Paul Wouters 4c0de48
		echo "graph_info Histogram of the reply times for queries."
Paul Wouters 4c0de48
		;;
Paul Wouters 4c0de48
	esac
Paul Wouters 4c0de48
Paul Wouters 4c0de48
	exit 0
Paul Wouters 4c0de48
fi
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# do the stats itself
Paul Wouters 4c0de48
get_state
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# get the time elapsed
Paul Wouters 4c0de48
get_value "time.elapsed"
Paul Wouters 4c0de48
if test $value = 0 || test $value = "0.000000"; then
Paul Wouters 4c0de48
	echo "error: time elapsed 0 or could not retrieve data"
Paul Wouters 4c0de48
	exit 1
Paul Wouters 4c0de48
fi
Paul Wouters 4c0de48
elapsed="$value"
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# print value for $1 / elapsed
Paul Wouters 4c0de48
print_qps ( ) {
Paul Wouters 4c0de48
	mn=`echo $1 | sed $ABBREV | tr . _`
Paul Wouters 4c0de48
	get_value $1
Paul Wouters 4c0de48
	echo "$mn.value" `echo scale=6';' $value / $elapsed | bc `
Paul Wouters 4c0de48
}
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# print qps if line already found in $2
Paul Wouters 4c0de48
print_qps_line ( ) {
Paul Wouters 4c0de48
	mn=`echo $1 | sed $ABBREV | tr . _`
Paul Wouters 4c0de48
	value="`echo $2 | sed -e 's/^.*=//'`"
Paul Wouters 4c0de48
	echo "$mn.value" `echo scale=6';' $value / $elapsed | bc `
Paul Wouters 4c0de48
}
Paul Wouters 4c0de48
Paul Wouters 4c0de48
# print value for $1
Paul Wouters 4c0de48
print_value ( ) {
Paul Wouters 4c0de48
	mn=`echo $1 | sed $ABBREV | tr . _`
Paul Wouters 4c0de48
	get_value $1
Paul Wouters 4c0de48
	echo "$mn.value" $value
Paul Wouters 4c0de48
}
Paul Wouters 4c0de48
Paul Wouters 4c0de48
case $id in
Paul Wouters 4c0de48
hits)
Paul Wouters 4c0de48
	for x in thread0.num.queries thread1.num.queries thread2.num.queries \
Paul Wouters 4c0de48
		thread3.num.queries thread4.num.queries thread5.num.queries \
Paul Wouters 4c0de48
		thread6.num.queries thread7.num.queries total.num.queries \
Paul Wouters 4c0de48
		total.num.cachehits total.num.prefetch num.query.tcp \
Paul Wouters 4c0de48
		num.query.ipv6 unwanted.queries unwanted.replies; do
Paul Wouters 4c0de48
		if grep "^"$x"=" $state >/dev/null 2>&1; then
Paul Wouters 4c0de48
			print_qps $x
Paul Wouters 4c0de48
		fi
Paul Wouters 4c0de48
	done
Paul Wouters 4c0de48
	;;
Paul Wouters 4c0de48
queue)
Paul Wouters 4c0de48
	for x in total.requestlist.avg total.requestlist.max \
Paul Wouters 4c0de48
		total.requestlist.overwritten total.requestlist.exceeded; do
Paul Wouters 4c0de48
		print_value $x
Paul Wouters 4c0de48
	done
Paul Wouters 4c0de48
	;;
Paul Wouters 4c0de48
memory)
Paul Wouters 4c0de48
	mn=`echo mem.total.sbrk | sed $ABBREV | tr . _`
Paul Wouters 4c0de48
	get_value 'mem.total.sbrk'
Paul Wouters 4c0de48
	if test $value -eq 0; then
Paul Wouters 4c0de48
		chk=`echo $ctrl | sed -e 's/-control$/-checkconf/'`
Paul Wouters 4c0de48
		pidf=`$chk -o pidfile $conf 2>&1`
Paul Wouters 4c0de48
		pid=`cat $pidf 2>&1`
Paul Wouters 4c0de48
		value=`ps -p "$pid" -o rss= 2>&1`
Paul Wouters 4c0de48
		if test "`expr $value + 1 - 1 2>&1`" -eq "$value" 2>&1; then
Paul Wouters 4c0de48
			value=`expr $value \* 1024` 
Paul Wouters 4c0de48
		else
Paul Wouters 4c0de48
			value=0
Paul Wouters 4c0de48
		fi
Paul Wouters 4c0de48
	fi
Paul Wouters 4c0de48
	echo "$mn.value" $value
Paul Wouters 4c0de48
	for x in mem.cache.rrset mem.cache.message \
Paul Wouters 4c0de48
		mem.mod.iterator mem.mod.validator; do
Paul Wouters 4c0de48
		print_value $x
Paul Wouters 4c0de48
	done
Paul Wouters 4c0de48
	;;
Paul Wouters 4c0de48
by_type)
Paul Wouters 4c0de48
	for x in `grep "^num.query.type" $state`; do
Paul Wouters 4c0de48
		nm=`echo $x | sed -e 's/=.*$//'`
Paul Wouters 4c0de48
		print_qps_line $nm $x
Paul Wouters 4c0de48
	done
Paul Wouters 4c0de48
	;;
Paul Wouters 4c0de48
by_class)
Paul Wouters 4c0de48
	for x in `grep "^num.query.class" $state`; do
Paul Wouters 4c0de48
		nm=`echo $x | sed -e 's/=.*$//'`
Paul Wouters 4c0de48
		print_qps_line $nm $x
Paul Wouters 4c0de48
	done
Paul Wouters 4c0de48
	;;
Paul Wouters 4c0de48
by_opcode)
Paul Wouters 4c0de48
	for x in `grep "^num.query.opcode" $state`; do
Paul Wouters 4c0de48
		nm=`echo $x | sed -e 's/=.*$//'`
Paul Wouters 4c0de48
		print_qps_line $nm $x
Paul Wouters 4c0de48
	done
Paul Wouters 4c0de48
	;;
Paul Wouters 4c0de48
by_rcode)
Paul Wouters 4c0de48
	for x in `grep "^num.answer.rcode" $state`; do
Paul Wouters 4c0de48
		nm=`echo $x | sed -e 's/=.*$//'`
Paul Wouters 4c0de48
		print_qps_line $nm $x
Paul Wouters 4c0de48
	done
Paul Wouters 4c0de48
	print_qps "num.answer.secure"
Paul Wouters 4c0de48
	print_qps "num.answer.bogus"
Paul Wouters 4c0de48
	print_qps "num.rrset.bogus"
Paul Wouters 4c0de48
	;;
Paul Wouters 4c0de48
by_flags)
Paul Wouters 4c0de48
	for x in num.query.flags.QR num.query.flags.AA num.query.flags.TC num.query.flags.RD num.query.flags.RA num.query.flags.Z num.query.flags.AD num.query.flags.CD num.query.edns.present num.query.edns.DO; do
Paul Wouters 4c0de48
		print_qps $x
Paul Wouters 4c0de48
	done
Paul Wouters 4c0de48
	;;
Paul Wouters 4c0de48
histogram)
Paul Wouters 4c0de48
	get_value total.num.cachehits
Paul Wouters 4c0de48
	echo hcache.value `echo scale=6';' $value / $elapsed | bc `
Paul Wouters 4c0de48
	r=0
Paul Wouters 4c0de48
	for x in histogram.000000.000000.to.000000.000001 \
Paul Wouters 4c0de48
		histogram.000000.000001.to.000000.000002 \
Paul Wouters 4c0de48
		histogram.000000.000002.to.000000.000004 \
Paul Wouters 4c0de48
		histogram.000000.000004.to.000000.000008 \
Paul Wouters 4c0de48
		histogram.000000.000008.to.000000.000016 \
Paul Wouters 4c0de48
		histogram.000000.000016.to.000000.000032 \
Paul Wouters 4c0de48
		histogram.000000.000032.to.000000.000064 \
Paul Wouters 4c0de48
		histogram.000000.000064.to.000000.000128 \
Paul Wouters 4c0de48
		histogram.000000.000128.to.000000.000256 \
Paul Wouters 4c0de48
		histogram.000000.000256.to.000000.000512 \
Paul Wouters 4c0de48
		histogram.000000.000512.to.000000.001024 \
Paul Wouters 4c0de48
		histogram.000000.001024.to.000000.002048 \
Paul Wouters 4c0de48
		histogram.000000.002048.to.000000.004096 \
Paul Wouters 4c0de48
		histogram.000000.004096.to.000000.008192 \
Paul Wouters 4c0de48
		histogram.000000.008192.to.000000.016384 \
Paul Wouters 4c0de48
		histogram.000000.016384.to.000000.032768 \
Paul Wouters 4c0de48
		histogram.000000.032768.to.000000.065536; do
Paul Wouters 4c0de48
		get_value $x
Paul Wouters 4c0de48
		r=`expr $r + $value`
Paul Wouters 4c0de48
	done
Paul Wouters 4c0de48
	echo h64ms.value `echo scale=6';' $r / $elapsed | bc `
Paul Wouters 4c0de48
	get_value histogram.000000.065536.to.000000.131072
Paul Wouters 4c0de48
	echo h128ms.value `echo scale=6';' $value / $elapsed | bc `
Paul Wouters 4c0de48
	get_value histogram.000000.131072.to.000000.262144
Paul Wouters 4c0de48
	echo h256ms.value `echo scale=6';' $value / $elapsed | bc `
Paul Wouters 4c0de48
	get_value histogram.000000.262144.to.000000.524288
Paul Wouters 4c0de48
	echo h512ms.value `echo scale=6';' $value / $elapsed | bc `
Paul Wouters 4c0de48
	get_value histogram.000000.524288.to.000001.000000
Paul Wouters 4c0de48
	echo h1s.value `echo scale=6';' $value / $elapsed | bc `
Paul Wouters 4c0de48
	get_value histogram.000001.000000.to.000002.000000
Paul Wouters 4c0de48
	echo h2s.value `echo scale=6';' $value / $elapsed | bc `
Paul Wouters 4c0de48
	get_value histogram.000002.000000.to.000004.000000
Paul Wouters 4c0de48
	echo h4s.value `echo scale=6';' $value / $elapsed | bc `
Paul Wouters 4c0de48
	get_value histogram.000004.000000.to.000008.000000
Paul Wouters 4c0de48
	echo h8s.value `echo scale=6';' $value / $elapsed | bc `
Paul Wouters 4c0de48
	r=0
Paul Wouters 4c0de48
	for x in histogram.000008.000000.to.000016.000000 \
Paul Wouters 4c0de48
		histogram.000016.000000.to.000032.000000 \
Paul Wouters 4c0de48
		histogram.000032.000000.to.000064.000000 \
Paul Wouters 4c0de48
		histogram.000064.000000.to.000128.000000 \
Paul Wouters 4c0de48
		histogram.000128.000000.to.000256.000000 \
Paul Wouters 4c0de48
		histogram.000256.000000.to.000512.000000 \
Paul Wouters 4c0de48
		histogram.000512.000000.to.001024.000000 \
Paul Wouters 4c0de48
		histogram.001024.000000.to.002048.000000 \
Paul Wouters 4c0de48
		histogram.002048.000000.to.004096.000000 \
Paul Wouters 4c0de48
		histogram.004096.000000.to.008192.000000 \
Paul Wouters 4c0de48
		histogram.008192.000000.to.016384.000000 \
Paul Wouters 4c0de48
		histogram.016384.000000.to.032768.000000 \
Paul Wouters 4c0de48
		histogram.032768.000000.to.065536.000000 \
Paul Wouters 4c0de48
		histogram.065536.000000.to.131072.000000 \
Paul Wouters 4c0de48
		histogram.131072.000000.to.262144.000000 \
Paul Wouters 4c0de48
		histogram.262144.000000.to.524288.000000; do
Paul Wouters 4c0de48
		get_value $x
Paul Wouters 4c0de48
		r=`expr $r + $value`
Paul Wouters 4c0de48
	done
Paul Wouters 4c0de48
	echo h16s.value `echo scale=6';' $r / $elapsed | bc `
Paul Wouters 4c0de48
	;;
Paul Wouters 4c0de48
esac