Home | History | Annotate | Line # | Download | only in contrib
unbound_munin_ revision 1.1.1.3
      1      1.1  christos #!/bin/sh
      2      1.1  christos #
      3      1.1  christos # plugin for munin to monitor usage of unbound servers.
      4      1.1  christos # To install copy this to /usr/local/share/munin/plugins/unbound_munin_
      5      1.1  christos # and use munin-node-configure (--suggest, --shell).
      6      1.1  christos #
      7      1.1  christos # (C) 2008 W.C.A. Wijngaards.  BSD Licensed.
      8      1.1  christos #
      9      1.1  christos # To install; enable statistics and unbound-control in unbound.conf
     10      1.1  christos #	server:		extended-statistics: yes
     11      1.1  christos #			statistics-cumulative: no
     12      1.1  christos #			statistics-interval: 0
     13      1.1  christos #	remote-control:	control-enable: yes
     14      1.1  christos # Run the command unbound-control-setup to generate the key files.
     15      1.1  christos #
     16      1.1  christos # Environment variables for this script
     17      1.1  christos #	statefile	- where to put temporary statefile.
     18      1.1  christos #	unbound_conf	- where the unbound.conf file is located.
     19      1.1  christos #	unbound_control	- where to find unbound-control executable.
     20      1.1  christos #	spoof_warn	- what level to warn about spoofing
     21      1.1  christos #	spoof_crit	- what level to crit about spoofing
     22      1.1  christos #
     23      1.1  christos # You can set them in your munin/plugin-conf.d/plugins.conf file
     24      1.1  christos # with:
     25      1.1  christos # [unbound*]
     26      1.1  christos # user root
     27      1.1  christos # env.statefile /usr/local/var/munin/plugin-state/unbound-state
     28      1.1  christos # env.unbound_conf /usr/local/etc/unbound/unbound.conf
     29      1.1  christos # env.unbound_control /usr/local/sbin/unbound-control
     30      1.1  christos # env.spoof_warn 1000
     31      1.1  christos # env.spoof_crit 100000
     32      1.1  christos #
     33      1.1  christos # This plugin can create different graphs depending on what name
     34      1.1  christos # you link it as (with ln -s) into the plugins directory
     35      1.1  christos # You can link it multiple times.
     36      1.1  christos # If you are only a casual user, the _hits and _by_type are most interesting,
     37      1.1  christos # possibly followed by _by_rcode.
     38      1.1  christos #
     39      1.1  christos #	unbound_munin_hits	- base volume, cache hits, unwanted traffic
     40      1.1  christos #	unbound_munin_queue	- to monitor the internal requestlist
     41      1.1  christos #	unbound_munin_memory	- memory usage
     42      1.1  christos #	unbound_munin_by_type	- incoming queries by type
     43      1.1  christos #	unbound_munin_by_class	- incoming queries by class
     44      1.1  christos #	unbound_munin_by_opcode	- incoming queries by opcode
     45      1.1  christos #	unbound_munin_by_rcode	- answers by rcode, validation status
     46      1.1  christos #	unbound_munin_by_flags	- incoming queries by flags
     47      1.1  christos #	unbound_munin_histogram	- histogram of query resolving times
     48      1.1  christos #
     49      1.1  christos # Magic markers - optional - used by installation scripts and
     50      1.1  christos # munin-config:  (originally contrib family but munin-node-configure ignores it)
     51      1.1  christos #
     52      1.1  christos #%# family=auto
     53      1.1  christos #%# capabilities=autoconf suggest
     54      1.1  christos 
     55      1.1  christos # POD documentation
     56      1.1  christos : <<=cut
     57      1.1  christos =head1 NAME
     58      1.1  christos 
     59      1.1  christos unbound_munin_ - Munin plugin to monitor the Unbound DNS resolver.
     60      1.1  christos 
     61      1.1  christos =head1 APPLICABLE SYSTEMS
     62      1.1  christos 
     63      1.1  christos System with unbound daemon.
     64      1.1  christos 
     65      1.1  christos =head1 CONFIGURATION
     66      1.1  christos 
     67      1.1  christos   [unbound*]
     68      1.1  christos   user root
     69      1.1  christos   env.statefile /usr/local/var/munin/plugin-state/unbound-state
     70      1.1  christos   env.unbound_conf /usr/local/etc/unbound/unbound.conf
     71      1.1  christos   env.unbound_control /usr/local/sbin/unbound-control
     72      1.1  christos   env.spoof_warn 1000
     73      1.1  christos   env.spoof_crit 100000
     74      1.1  christos 
     75      1.1  christos Use the .env settings to override the defaults.
     76      1.1  christos 
     77      1.1  christos =head1 USAGE
     78      1.1  christos 
     79      1.1  christos Can be used to present different graphs. Use ln -s for that name in
     80      1.1  christos the plugins directory to enable the graph.
     81      1.1  christos unbound_munin_hits	- base volume, cache hits, unwanted traffic
     82      1.1  christos unbound_munin_queue	- to monitor the internal requestlist
     83      1.1  christos unbound_munin_memory	- memory usage
     84      1.1  christos unbound_munin_by_type	- incoming queries by type
     85      1.1  christos unbound_munin_by_class	- incoming queries by class
     86      1.1  christos unbound_munin_by_opcode	- incoming queries by opcode
     87      1.1  christos unbound_munin_by_rcode	- answers by rcode, validation status
     88      1.1  christos unbound_munin_by_flags	- incoming queries by flags
     89      1.1  christos unbound_munin_histogram - histogram of query resolving times
     90      1.1  christos 
     91      1.1  christos =head1 AUTHOR
     92      1.1  christos 
     93      1.1  christos Copyright 2008 W.C.A. Wijngaards
     94      1.1  christos 
     95      1.1  christos =head1 LICENSE
     96      1.1  christos 
     97      1.1  christos BSD
     98      1.1  christos 
     99      1.1  christos =cut
    100      1.1  christos 
    101      1.1  christos state=${statefile:-/usr/local/var/munin/plugin-state/unbound-state}
    102      1.1  christos conf=${unbound_conf:-/usr/local/etc/unbound/unbound.conf}
    103      1.1  christos ctrl=${unbound_control:-/usr/local/sbin/unbound-control}
    104      1.1  christos warn=${spoof_warn:-1000}
    105      1.1  christos crit=${spoof_crit:-100000}
    106      1.1  christos lock=$state.lock
    107      1.1  christos 
    108      1.1  christos # number of seconds between polling attempts.
    109      1.1  christos # makes the statefile hang around for at least this many seconds,
    110      1.1  christos # so that multiple links of this script can share the results.
    111      1.1  christos lee=55
    112      1.1  christos 
    113      1.1  christos # to keep things within 19 characters
    114      1.1  christos 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/"
    115      1.1  christos 
    116      1.1  christos # get value from $1 into return variable $value
    117      1.1  christos get_value ( ) {
    118      1.1  christos 	value="`grep '^'$1'=' $state | sed -e 's/^.*=//'`"
    119      1.1  christos 	if test "$value"x = ""x; then
    120      1.1  christos 		value="0"
    121      1.1  christos 	fi
    122      1.1  christos }
    123      1.1  christos 
    124      1.1  christos # download the state from the unbound server.
    125      1.1  christos get_state ( ) {
    126      1.1  christos 	# obtain lock for fetching the state
    127      1.1  christos 	# because there is a race condition in fetching and writing to file
    128      1.1  christos 
    129      1.1  christos 	# see if the lock is stale, if so, take it 
    130      1.1  christos 	if test -f $lock ; then
    131      1.1  christos 		pid="`cat $lock 2>&1`"
    132      1.1  christos 		kill -0 "$pid" >/dev/null 2>&1
    133      1.1  christos 		if test $? -ne 0 -a "$pid" != $$ ; then
    134      1.1  christos 			echo $$ >$lock
    135      1.1  christos 		fi
    136      1.1  christos 	fi
    137      1.1  christos 
    138      1.1  christos 	i=0
    139      1.1  christos 	while test ! -f $lock || test "`cat $lock 2>&1`" != $$; do
    140      1.1  christos 		while test -f $lock; do
    141      1.1  christos 			# wait
    142      1.1  christos 			i=`expr $i + 1`
    143      1.1  christos 			if test $i -gt 1000; then
    144      1.1  christos 				sleep 1;
    145      1.1  christos 			fi
    146      1.1  christos 			if test $i -gt 1500; then
    147      1.1  christos 				echo "error locking $lock" "=" `cat $lock`
    148      1.1  christos 				rm -f $lock
    149      1.1  christos 				exit 1
    150      1.1  christos 			fi
    151      1.1  christos 		done
    152      1.1  christos 		# try to get it
    153  1.1.1.2  christos 		if echo $$ >$lock ; then : ; else break; fi
    154      1.1  christos 	done
    155      1.1  christos 	# do not refetch if the file exists and only LEE seconds old
    156      1.1  christos 	if test -f $state; then
    157      1.1  christos 		now=`date +%s`
    158      1.1  christos 		get_value "time.now"
    159      1.1  christos 		value="`echo $value | sed -e 's/\..*$//'`"
    160      1.1  christos 		if test $now -lt `expr $value + $lee`; then
    161      1.1  christos 			rm -f $lock
    162      1.1  christos 			return
    163      1.1  christos 		fi
    164      1.1  christos 	fi
    165      1.1  christos 	$ctrl -c $conf stats > $state
    166      1.1  christos 	if test $? -ne 0; then
    167      1.1  christos 		echo "error retrieving data from unbound server"
    168      1.1  christos 		rm -f $lock
    169      1.1  christos 		exit 1
    170      1.1  christos 	fi
    171      1.1  christos 	rm -f $lock
    172      1.1  christos }
    173      1.1  christos 
    174      1.1  christos if test "$1" = "autoconf" ; then
    175      1.1  christos 	if test ! -f $conf; then
    176      1.1  christos 		echo no "($conf does not exist)"
    177  1.1.1.3  christos 		exit 0
    178      1.1  christos 	fi
    179      1.1  christos 	if test ! -d `dirname $state`; then
    180      1.1  christos 		echo no "(`dirname $state` directory does not exist)"
    181  1.1.1.3  christos 		exit 0
    182      1.1  christos 	fi
    183      1.1  christos 	echo yes
    184      1.1  christos 	exit 0
    185      1.1  christos fi
    186      1.1  christos 
    187      1.1  christos if test "$1" = "suggest" ; then
    188      1.1  christos 	echo "hits"
    189      1.1  christos 	echo "queue"
    190      1.1  christos 	echo "memory"
    191      1.1  christos 	echo "by_type"
    192      1.1  christos 	echo "by_class"
    193      1.1  christos 	echo "by_opcode"
    194      1.1  christos 	echo "by_rcode"
    195      1.1  christos 	echo "by_flags"
    196      1.1  christos 	echo "histogram"
    197      1.1  christos 	exit 0
    198      1.1  christos fi
    199      1.1  christos 
    200      1.1  christos # determine my type, by name
    201      1.1  christos id=`echo $0 | sed -e 's/^.*unbound_munin_//'`
    202      1.1  christos if test "$id"x = ""x; then
    203      1.1  christos 	# some default to keep people sane.
    204      1.1  christos 	id="hits"
    205      1.1  christos fi
    206      1.1  christos 
    207      1.1  christos # if $1 exists in statefile, config is echoed with label $2
    208      1.1  christos exist_config ( ) {
    209      1.1  christos 	mn=`echo $1 | sed $ABBREV | tr . _`
    210      1.1  christos 	if grep '^'$1'=' $state >/dev/null 2>&1; then
    211      1.1  christos 		echo "$mn.label $2"
    212      1.1  christos 		echo "$mn.min 0"
    213      1.1  christos 		echo "$mn.type ABSOLUTE"
    214      1.1  christos 	fi
    215      1.1  christos }
    216      1.1  christos 
    217      1.1  christos # print label and min 0 for a name $1 in unbound format
    218      1.1  christos p_config ( ) {
    219      1.1  christos 	mn=`echo $1 | sed $ABBREV | tr . _`
    220      1.1  christos 	echo $mn.label "$2"
    221      1.1  christos 	echo $mn.min 0
    222      1.1  christos 	echo $mn.type $3
    223      1.1  christos }
    224      1.1  christos 
    225      1.1  christos if test "$1" = "config" ; then
    226      1.1  christos 	if test ! -f $state; then
    227      1.1  christos 		get_state
    228      1.1  christos 	fi
    229      1.1  christos 	case $id in
    230      1.1  christos 	hits)
    231      1.1  christos 		echo "graph_title Unbound DNS traffic and cache hits"
    232      1.1  christos 		echo "graph_args --base 1000 -l 0"
    233      1.1  christos 		echo "graph_vlabel queries / \${graph_period}"
    234      1.1  christos 		echo "graph_scale no"
    235      1.1  christos 		echo "graph_category DNS"
    236      1.1  christos 		for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
    237      1.1  christos 			sed -e 's/=.*//'`; do
    238      1.1  christos 			exist_config $x "queries handled by `basename $x .num.queries`"
    239      1.1  christos 		done
    240      1.1  christos 		p_config "total.num.queries" "total queries from clients" "ABSOLUTE"
    241      1.1  christos 		p_config "total.num.cachehits" "cache hits" "ABSOLUTE"
    242      1.1  christos 		p_config "total.num.prefetch" "cache prefetch" "ABSOLUTE"
    243      1.1  christos 		p_config "num.query.tcp" "TCP queries" "ABSOLUTE"
    244      1.1  christos 		p_config "num.query.tcpout" "TCP out queries" "ABSOLUTE"
    245  1.1.1.3  christos 		p_config "num.query.tls" "TLS queries" "ABSOLUTE"
    246  1.1.1.3  christos 		p_config "num.query.tls.resume" "TLS resumes" "ABSOLUTE"
    247      1.1  christos 		p_config "num.query.ipv6" "IPv6 queries" "ABSOLUTE"
    248      1.1  christos 		p_config "unwanted.queries" "queries that failed acl" "ABSOLUTE"
    249      1.1  christos 		p_config "unwanted.replies" "unwanted or unsolicited replies" "ABSOLUTE"
    250      1.1  christos 		echo "u_replies.warning $warn"
    251      1.1  christos 		echo "u_replies.critical $crit"
    252      1.1  christos 		echo "graph_info DNS queries to the recursive resolver. The unwanted replies could be innocent duplicate packets, late replies, or spoof threats."
    253      1.1  christos 		;;
    254      1.1  christos 	queue)
    255      1.1  christos 		echo "graph_title Unbound requestlist size"
    256      1.1  christos 		echo "graph_args --base 1000 -l 0"
    257      1.1  christos 		echo "graph_vlabel number of queries"
    258      1.1  christos 		echo "graph_scale no"
    259      1.1  christos 		echo "graph_category DNS"
    260      1.1  christos 		p_config "total.requestlist.avg" "Average size of queue on insert" "GAUGE"
    261      1.1  christos 		p_config "total.requestlist.max" "Max size of queue (in 5 min)" "GAUGE"
    262      1.1  christos 		p_config "total.requestlist.overwritten" "Number of queries replaced by new ones" "GAUGE"
    263      1.1  christos 		p_config "total.requestlist.exceeded" "Number of queries dropped due to lack of space" "GAUGE"
    264      1.1  christos 		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."
    265      1.1  christos 		;;
    266      1.1  christos 	memory)
    267      1.1  christos 		echo "graph_title Unbound memory usage"
    268      1.1  christos 		echo "graph_args --base 1024 -l 0"
    269      1.1  christos 		echo "graph_vlabel memory used in bytes"
    270      1.1  christos 		echo "graph_category DNS"
    271      1.1  christos 		p_config "mem.cache.rrset" "RRset cache memory" "GAUGE"
    272      1.1  christos 		p_config "mem.cache.message" "Message cache memory" "GAUGE"
    273      1.1  christos 		p_config "mem.mod.iterator" "Iterator module memory" "GAUGE"
    274      1.1  christos 		p_config "mem.mod.validator" "Validator module and key cache memory" "GAUGE"
    275      1.1  christos 		p_config "msg.cache.count" "msg cache count" "GAUGE"
    276      1.1  christos 		p_config "rrset.cache.count" "rrset cache count" "GAUGE"
    277      1.1  christos 		p_config "infra.cache.count" "infra cache count" "GAUGE"
    278      1.1  christos 		p_config "key.cache.count" "key cache count" "GAUGE"
    279      1.1  christos 		echo "graph_info The memory used by unbound."
    280      1.1  christos 		;;
    281      1.1  christos 	by_type)
    282      1.1  christos 		echo "graph_title Unbound DNS queries by type"
    283      1.1  christos 		echo "graph_args --base 1000 -l 0"
    284      1.1  christos 		echo "graph_vlabel queries / \${graph_period}"
    285      1.1  christos 		echo "graph_scale no"
    286      1.1  christos 		echo "graph_category DNS"
    287      1.1  christos 		for x in `grep "^num.query.type" $state`; do
    288      1.1  christos 			nm=`echo $x | sed -e 's/=.*$//'`
    289      1.1  christos 			tp=`echo $nm | sed -e s/num.query.type.//`
    290      1.1  christos 			p_config "$nm" "$tp" "ABSOLUTE"
    291      1.1  christos 		done
    292      1.1  christos 		echo "graph_info queries by DNS RR type queried for"
    293      1.1  christos 		;;
    294      1.1  christos 	by_class)
    295      1.1  christos 		echo "graph_title Unbound DNS queries by class"
    296      1.1  christos 		echo "graph_args --base 1000 -l 0"
    297      1.1  christos 		echo "graph_vlabel queries / \${graph_period}"
    298      1.1  christos 		echo "graph_scale no"
    299      1.1  christos 		echo "graph_category DNS"
    300      1.1  christos 		for x in `grep "^num.query.class" $state`; do
    301      1.1  christos 			nm=`echo $x | sed -e 's/=.*$//'`
    302      1.1  christos 			tp=`echo $nm | sed -e s/num.query.class.//`
    303      1.1  christos 			p_config "$nm" "$tp" "ABSOLUTE"
    304      1.1  christos 		done
    305      1.1  christos 		echo "graph_info queries by DNS RR class queried for."
    306      1.1  christos 		;;
    307      1.1  christos 	by_opcode)
    308      1.1  christos 		echo "graph_title Unbound DNS queries by opcode"
    309      1.1  christos 		echo "graph_args --base 1000 -l 0"
    310      1.1  christos 		echo "graph_vlabel queries / \${graph_period}"
    311      1.1  christos 		echo "graph_scale no"
    312      1.1  christos 		echo "graph_category DNS"
    313      1.1  christos 		for x in `grep "^num.query.opcode" $state`; do
    314      1.1  christos 			nm=`echo $x | sed -e 's/=.*$//'`
    315      1.1  christos 			tp=`echo $nm | sed -e s/num.query.opcode.//`
    316      1.1  christos 			p_config "$nm" "$tp" "ABSOLUTE"
    317      1.1  christos 		done
    318      1.1  christos 		echo "graph_info queries by opcode in the query packet."
    319      1.1  christos 		;;
    320      1.1  christos 	by_rcode)
    321      1.1  christos 		echo "graph_title Unbound DNS answers by return code"
    322      1.1  christos 		echo "graph_args --base 1000 -l 0"
    323      1.1  christos 		echo "graph_vlabel answer packets / \${graph_period}"
    324      1.1  christos 		echo "graph_scale no"
    325      1.1  christos 		echo "graph_category DNS"
    326      1.1  christos 		for x in `grep "^num.answer.rcode" $state`; do
    327      1.1  christos 			nm=`echo $x | sed -e 's/=.*$//'`
    328      1.1  christos 			tp=`echo $nm | sed -e s/num.answer.rcode.//`
    329      1.1  christos 			p_config "$nm" "$tp" "ABSOLUTE"
    330      1.1  christos 		done
    331      1.1  christos 		p_config "num.answer.secure" "answer secure" "ABSOLUTE"
    332      1.1  christos 		p_config "num.answer.bogus" "answer bogus" "ABSOLUTE"
    333      1.1  christos 		p_config "num.rrset.bogus" "num rrsets marked bogus" "ABSOLUTE"
    334      1.1  christos 		echo "graph_info answers sorted by return value. rrsets bogus is the number of rrsets marked bogus per \${graph_period} by the validator"
    335      1.1  christos 		;;
    336      1.1  christos 	by_flags)
    337      1.1  christos 		echo "graph_title Unbound DNS incoming queries by flags"
    338      1.1  christos 		echo "graph_args --base 1000 -l 0"
    339      1.1  christos 		echo "graph_vlabel queries / \${graph_period}"
    340      1.1  christos 		echo "graph_scale no"
    341      1.1  christos 		echo "graph_category DNS"
    342      1.1  christos 		p_config "num.query.flags.QR" "QR (query reply) flag" "ABSOLUTE"
    343      1.1  christos 		p_config "num.query.flags.AA" "AA (auth answer) flag" "ABSOLUTE"
    344      1.1  christos 		p_config "num.query.flags.TC" "TC (truncated) flag" "ABSOLUTE"
    345      1.1  christos 		p_config "num.query.flags.RD" "RD (recursion desired) flag" "ABSOLUTE"
    346      1.1  christos 		p_config "num.query.flags.RA" "RA (rec avail) flag" "ABSOLUTE"
    347      1.1  christos 		p_config "num.query.flags.Z" "Z (zero) flag" "ABSOLUTE"
    348      1.1  christos 		p_config "num.query.flags.AD" "AD (auth data) flag" "ABSOLUTE"
    349      1.1  christos 		p_config "num.query.flags.CD" "CD (check disabled) flag" "ABSOLUTE"
    350      1.1  christos 		p_config "num.query.edns.present" "EDNS OPT present" "ABSOLUTE"
    351      1.1  christos 		p_config "num.query.edns.DO" "DO (DNSSEC OK) flag" "ABSOLUTE"
    352      1.1  christos 		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."
    353      1.1  christos 		;;
    354      1.1  christos 	histogram)
    355      1.1  christos 		echo "graph_title Unbound DNS histogram of reply time"
    356      1.1  christos 		echo "graph_args --base 1000 -l 0"
    357      1.1  christos 		echo "graph_vlabel queries / \${graph_period}"
    358      1.1  christos 		echo "graph_scale no"
    359      1.1  christos 		echo "graph_category DNS"
    360      1.1  christos 		echo hcache.label "cache hits"
    361      1.1  christos 		echo hcache.min 0
    362      1.1  christos 		echo hcache.type ABSOLUTE
    363      1.1  christos 		echo hcache.draw AREA
    364      1.1  christos 		echo hcache.colour 999999
    365      1.1  christos 		echo h64ms.label "0 msec - 66 msec"
    366      1.1  christos 		echo h64ms.min 0
    367      1.1  christos 		echo h64ms.type ABSOLUTE
    368      1.1  christos 		echo h64ms.draw STACK
    369      1.1  christos 		echo h64ms.colour 0000FF
    370      1.1  christos 		echo h128ms.label "66 msec - 131 msec"
    371      1.1  christos 		echo h128ms.min 0
    372      1.1  christos 		echo h128ms.type ABSOLUTE
    373      1.1  christos 		echo h128ms.colour 1F00DF
    374      1.1  christos 		echo h128ms.draw STACK
    375      1.1  christos 		echo h256ms.label "131 msec - 262 msec"
    376      1.1  christos 		echo h256ms.min 0
    377      1.1  christos 		echo h256ms.type ABSOLUTE
    378      1.1  christos 		echo h256ms.draw STACK
    379      1.1  christos 		echo h256ms.colour 3F00BF
    380      1.1  christos 		echo h512ms.label "262 msec - 524 msec"
    381      1.1  christos 		echo h512ms.min 0
    382      1.1  christos 		echo h512ms.type ABSOLUTE
    383      1.1  christos 		echo h512ms.draw STACK
    384      1.1  christos 		echo h512ms.colour 5F009F
    385      1.1  christos 		echo h1s.label "524 msec - 1 sec"
    386      1.1  christos 		echo h1s.min 0
    387      1.1  christos 		echo h1s.type ABSOLUTE
    388      1.1  christos 		echo h1s.draw STACK
    389      1.1  christos 		echo h1s.colour 7F007F
    390      1.1  christos 		echo h2s.label "1 sec - 2 sec"
    391      1.1  christos 		echo h2s.min 0
    392      1.1  christos 		echo h2s.type ABSOLUTE
    393      1.1  christos 		echo h2s.draw STACK
    394      1.1  christos 		echo h2s.colour 9F005F
    395      1.1  christos 		echo h4s.label "2 sec - 4 sec"
    396      1.1  christos 		echo h4s.min 0
    397      1.1  christos 		echo h4s.type ABSOLUTE
    398      1.1  christos 		echo h4s.draw STACK
    399      1.1  christos 		echo h4s.colour BF003F
    400      1.1  christos 		echo h8s.label "4 sec - 8 sec"
    401      1.1  christos 		echo h8s.min 0
    402      1.1  christos 		echo h8s.type ABSOLUTE
    403      1.1  christos 		echo h8s.draw STACK
    404      1.1  christos 		echo h8s.colour DF001F
    405      1.1  christos 		echo h16s.label "8 sec - ..."
    406      1.1  christos 		echo h16s.min 0
    407      1.1  christos 		echo h16s.type ABSOLUTE
    408      1.1  christos 		echo h16s.draw STACK
    409      1.1  christos 		echo h16s.colour FF0000
    410      1.1  christos 		echo "graph_info Histogram of the reply times for queries."
    411      1.1  christos 		;;
    412      1.1  christos 	esac
    413      1.1  christos 
    414      1.1  christos 	exit 0
    415      1.1  christos fi
    416      1.1  christos 
    417      1.1  christos # do the stats itself
    418      1.1  christos get_state
    419      1.1  christos 
    420      1.1  christos # get the time elapsed
    421      1.1  christos get_value "time.elapsed"
    422      1.1  christos if test $value = 0 || test $value = "0.000000"; then
    423      1.1  christos 	echo "error: time elapsed 0 or could not retrieve data"
    424      1.1  christos 	exit 1
    425      1.1  christos fi
    426      1.1  christos elapsed="$value"
    427      1.1  christos 
    428      1.1  christos # print value for $1
    429      1.1  christos print_value ( ) {
    430      1.1  christos 	mn=`echo $1 | sed $ABBREV | tr . _`
    431      1.1  christos 	get_value $1
    432      1.1  christos 	echo "$mn.value" $value
    433      1.1  christos }
    434      1.1  christos 
    435      1.1  christos # print value if line already found in $2
    436      1.1  christos print_value_line ( ) {
    437      1.1  christos 	mn=`echo $1 | sed $ABBREV | tr . _`
    438      1.1  christos 	value="`echo $2 | sed -e 's/^.*=//'`"
    439      1.1  christos 	echo "$mn.value" $value
    440      1.1  christos }
    441      1.1  christos 
    442      1.1  christos 
    443      1.1  christos case $id in
    444      1.1  christos hits)
    445      1.1  christos 	for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
    446      1.1  christos 		sed -e 's/=.*//'` total.num.queries \
    447      1.1  christos 		total.num.cachehits total.num.prefetch num.query.tcp \
    448  1.1.1.3  christos 		num.query.tcpout num.query.tls num.query.tls.resume \
    449  1.1.1.3  christos 		num.query.ipv6 unwanted.queries \
    450      1.1  christos 		unwanted.replies; do
    451      1.1  christos 		if grep "^"$x"=" $state >/dev/null 2>&1; then
    452      1.1  christos 			print_value $x
    453      1.1  christos 		fi
    454      1.1  christos 	done
    455      1.1  christos 	;;
    456      1.1  christos queue)
    457      1.1  christos 	for x in total.requestlist.avg total.requestlist.max \
    458      1.1  christos 		total.requestlist.overwritten total.requestlist.exceeded; do
    459      1.1  christos 		print_value $x
    460      1.1  christos 	done
    461      1.1  christos 	;;
    462      1.1  christos memory)
    463      1.1  christos 	for x in mem.cache.rrset mem.cache.message mem.mod.iterator \
    464      1.1  christos 		mem.mod.validator msg.cache.count rrset.cache.count \
    465      1.1  christos 		infra.cache.count key.cache.count; do
    466      1.1  christos 		print_value $x
    467      1.1  christos 	done
    468      1.1  christos 	;;
    469      1.1  christos by_type)
    470      1.1  christos 	for x in `grep "^num.query.type" $state`; do
    471      1.1  christos 		nm=`echo $x | sed -e 's/=.*$//'`
    472      1.1  christos 		print_value_line $nm $x
    473      1.1  christos 	done
    474      1.1  christos 	;;
    475      1.1  christos by_class)
    476      1.1  christos 	for x in `grep "^num.query.class" $state`; do
    477      1.1  christos 		nm=`echo $x | sed -e 's/=.*$//'`
    478      1.1  christos 		print_value_line $nm $x
    479      1.1  christos 	done
    480      1.1  christos 	;;
    481      1.1  christos by_opcode)
    482      1.1  christos 	for x in `grep "^num.query.opcode" $state`; do
    483      1.1  christos 		nm=`echo $x | sed -e 's/=.*$//'`
    484      1.1  christos 		print_value_line $nm $x
    485      1.1  christos 	done
    486      1.1  christos 	;;
    487      1.1  christos by_rcode)
    488      1.1  christos 	for x in `grep "^num.answer.rcode" $state`; do
    489      1.1  christos 		nm=`echo $x | sed -e 's/=.*$//'`
    490      1.1  christos 		print_value_line $nm $x
    491      1.1  christos 	done
    492      1.1  christos 	print_value "num.answer.secure"
    493      1.1  christos 	print_value "num.answer.bogus"
    494      1.1  christos 	print_value "num.rrset.bogus"
    495      1.1  christos 	;;
    496      1.1  christos by_flags)
    497      1.1  christos 	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
    498      1.1  christos 		print_value $x
    499      1.1  christos 	done
    500      1.1  christos 	;;
    501      1.1  christos histogram)
    502      1.1  christos 	get_value total.num.cachehits
    503      1.1  christos 	echo hcache.value $value
    504      1.1  christos 	r=0
    505      1.1  christos 	for x in histogram.000000.000000.to.000000.000001 \
    506      1.1  christos 		histogram.000000.000001.to.000000.000002 \
    507      1.1  christos 		histogram.000000.000002.to.000000.000004 \
    508      1.1  christos 		histogram.000000.000004.to.000000.000008 \
    509      1.1  christos 		histogram.000000.000008.to.000000.000016 \
    510      1.1  christos 		histogram.000000.000016.to.000000.000032 \
    511      1.1  christos 		histogram.000000.000032.to.000000.000064 \
    512      1.1  christos 		histogram.000000.000064.to.000000.000128 \
    513      1.1  christos 		histogram.000000.000128.to.000000.000256 \
    514      1.1  christos 		histogram.000000.000256.to.000000.000512 \
    515      1.1  christos 		histogram.000000.000512.to.000000.001024 \
    516      1.1  christos 		histogram.000000.001024.to.000000.002048 \
    517      1.1  christos 		histogram.000000.002048.to.000000.004096 \
    518      1.1  christos 		histogram.000000.004096.to.000000.008192 \
    519      1.1  christos 		histogram.000000.008192.to.000000.016384 \
    520      1.1  christos 		histogram.000000.016384.to.000000.032768 \
    521      1.1  christos 		histogram.000000.032768.to.000000.065536; do
    522      1.1  christos 		get_value $x
    523      1.1  christos 		r=`expr $r + $value`
    524      1.1  christos 	done
    525      1.1  christos 	echo h64ms.value $r
    526      1.1  christos 	get_value histogram.000000.065536.to.000000.131072
    527      1.1  christos 	echo h128ms.value $value
    528      1.1  christos 	get_value histogram.000000.131072.to.000000.262144
    529      1.1  christos 	echo h256ms.value $value
    530      1.1  christos 	get_value histogram.000000.262144.to.000000.524288
    531      1.1  christos 	echo h512ms.value $value
    532      1.1  christos 	get_value histogram.000000.524288.to.000001.000000
    533      1.1  christos 	echo h1s.value $value
    534      1.1  christos 	get_value histogram.000001.000000.to.000002.000000
    535      1.1  christos 	echo h2s.value $value
    536      1.1  christos 	get_value histogram.000002.000000.to.000004.000000
    537      1.1  christos 	echo h4s.value $value
    538      1.1  christos 	get_value histogram.000004.000000.to.000008.000000
    539      1.1  christos 	echo h8s.value $value
    540      1.1  christos 	r=0
    541      1.1  christos 	for x in histogram.000008.000000.to.000016.000000 \
    542      1.1  christos 		histogram.000016.000000.to.000032.000000 \
    543      1.1  christos 		histogram.000032.000000.to.000064.000000 \
    544      1.1  christos 		histogram.000064.000000.to.000128.000000 \
    545      1.1  christos 		histogram.000128.000000.to.000256.000000 \
    546      1.1  christos 		histogram.000256.000000.to.000512.000000 \
    547      1.1  christos 		histogram.000512.000000.to.001024.000000 \
    548      1.1  christos 		histogram.001024.000000.to.002048.000000 \
    549      1.1  christos 		histogram.002048.000000.to.004096.000000 \
    550      1.1  christos 		histogram.004096.000000.to.008192.000000 \
    551      1.1  christos 		histogram.008192.000000.to.016384.000000 \
    552      1.1  christos 		histogram.016384.000000.to.032768.000000 \
    553      1.1  christos 		histogram.032768.000000.to.065536.000000 \
    554      1.1  christos 		histogram.065536.000000.to.131072.000000 \
    555      1.1  christos 		histogram.131072.000000.to.262144.000000 \
    556      1.1  christos 		histogram.262144.000000.to.524288.000000; do
    557      1.1  christos 		get_value $x
    558      1.1  christos 		r=`expr $r + $value`
    559      1.1  christos 	done
    560      1.1  christos 	echo h16s.value $r
    561      1.1  christos 	;;
    562      1.1  christos esac
    563