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