# unbound_munin_by_opcode - incoming queries by opcode
# unbound_munin_by_rcode - answers by rcode, validation status
# unbound_munin_by_flags - incoming queries by flags
+# unbound_munin_histogram - histogram of query resolving times
#
# Magic markers - optional - used by installation scripts and
# munin-config:
unbound_munin_by_opcode - incoming queries by opcode
unbound_munin_by_rcode - answers by rcode, validation status
unbound_munin_by_flags - incoming queries by flags
+unbound_munin_histogram - histogram of query resolving times
=head1 AUTHOR
echo "by_opcode"
echo "by_rcode"
echo "by_flags"
+ echo "histogram"
exit 0
fi
p_config "num.query.edns.DO" "DO (DNSSEC OK) flag"
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."
;;
+ histogram)
+ echo "graph_title Unbound DNS histogram of reply time"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / second"
+ echo "graph_category DNS"
+ echo h64ms.label "0 msec - 66 msec"
+ echo h64ms.min 0
+ echo h64ms.draw AREA
+ echo h64ms.colour 0000FF
+ echo h128ms.label "66 msec - 131 msec"
+ echo h128ms.min 0
+ echo h128ms.colour 1F00DF
+ echo h128ms.draw STACK
+ echo h256ms.label "131 msec - 262 msec"
+ echo h256ms.min 0
+ echo h256ms.draw STACK
+ echo h256ms.colour 3F00BF
+ echo h512ms.label "262 msec - 524 msec"
+ echo h512ms.min 0
+ echo h512ms.draw STACK
+ echo h512ms.colour 5F009F
+ echo h1s.label "524 msec - 1 sec"
+ echo h1s.min 0
+ echo h1s.draw STACK
+ echo h1s.colour 7F007F
+ echo h2s.label "1 sec - 2 sec"
+ echo h2s.min 0
+ echo h2s.draw STACK
+ echo h2s.colour 9F005F
+ echo h4s.label "2 sec - 4 sec"
+ echo h4s.min 0
+ echo h4s.draw STACK
+ echo h4s.colour BF003F
+ echo h8s.label "4 sec - 8 sec"
+ echo h8s.min 0
+ echo h8s.draw STACK
+ echo h8s.colour DF001F
+ echo h16s.label "8 sec - ..."
+ echo h16s.min 0
+ echo h16s.draw STACK
+ echo h16s.colour FF0000
+ echo "graph_info Histogram of the reply times for queries."
+ ;;
esac
exit 0
print_qps $x
done
;;
+histogram)
+ r=0
+ for x in histogram.000000.000000.to.000000.000001 \
+ histogram.000000.000001.to.000000.000002 \
+ histogram.000000.000002.to.000000.000004 \
+ histogram.000000.000004.to.000000.000008 \
+ histogram.000000.000008.to.000000.000016 \
+ histogram.000000.000016.to.000000.000032 \
+ histogram.000000.000032.to.000000.000064 \
+ histogram.000000.000064.to.000000.000128 \
+ histogram.000000.000128.to.000000.000256 \
+ histogram.000000.000256.to.000000.000512 \
+ histogram.000000.000512.to.000000.001024 \
+ histogram.000000.001024.to.000000.002048 \
+ histogram.000000.002048.to.000000.004096 \
+ histogram.000000.004096.to.000000.008192 \
+ histogram.000000.008192.to.000000.016384 \
+ histogram.000000.016384.to.000000.032768 \
+ histogram.000000.032768.to.000000.065536; do
+ get_value $x
+ r=`expr $r + $value`
+ done
+ echo h64ms.value $r
+ get_value histogram.000000.065536.to.000000.131072
+ echo h128ms.value $value
+ get_value histogram.000000.131072.to.000000.262144
+ echo h256ms.value $value
+ get_value histogram.000000.262144.to.000000.524288
+ echo h512ms.value $value
+ get_value histogram.000000.524288.to.000001.000000
+ echo h1s.value $value
+ get_value histogram.000001.000000.to.000002.000000
+ echo h2s.value $value
+ get_value histogram.000002.000000.to.000004.000000
+ echo h4s.value $value
+ get_value histogram.000004.000000.to.000008.000000
+ echo h8s.value $value
+ r=0
+ for x in histogram.000008.000000.to.000016.000000 \
+ histogram.000016.000000.to.000032.000000 \
+ histogram.000032.000000.to.000064.000000 \
+ histogram.000064.000000.to.000128.000000 \
+ histogram.000128.000000.to.000256.000000 \
+ histogram.000256.000000.to.000512.000000 \
+ histogram.000512.000000.to.001024.000000 \
+ histogram.001024.000000.to.002048.000000 \
+ histogram.002048.000000.to.004096.000000 \
+ histogram.004096.000000.to.008192.000000 \
+ histogram.008192.000000.to.016384.000000 \
+ histogram.016384.000000.to.032768.000000 \
+ histogram.032768.000000.to.065536.000000 \
+ histogram.065536.000000.to.131072.000000 \
+ histogram.131072.000000.to.262144.000000 \
+ histogram.262144.000000.to.524288.000000; do
+ get_value $x
+ r=`expr $r + $value`
+ done
+ echo h16s.value $r
+ ;;
esac
return 1;
}
+/** print extended histogram */
+static int
+print_hist(SSL* ssl, struct stats_info* s)
+{
+ struct timehist* hist;
+ size_t i;
+ hist = timehist_setup();
+ if(!hist) {
+ log_err("out of memory");
+ return 0;
+ }
+ timehist_import(hist, s->svr.hist, NUM_BUCKETS_HIST);
+ for(i=0; i<hist->num; i++) {
+ if(!ssl_printf(ssl,
+ "histogram.%6.6d.%6.6d.to.%6.6d.%6.6d=%u\n",
+ (int)hist->buckets[i].lower.tv_sec,
+ (int)hist->buckets[i].lower.tv_usec,
+ (int)hist->buckets[i].upper.tv_sec,
+ (int)hist->buckets[i].upper.tv_usec,
+ (unsigned)hist->buckets[i].count)) {
+ timehist_delete(hist);
+ return 0;
+ }
+ }
+ timehist_delete(hist);
+ return 1;
+}
+
/** print extended stats */
static int
print_ext(SSL* ssl, struct stats_info* s)
if(daemon->cfg->stat_extended) {
if(!print_mem(ssl, rc->worker, daemon))
return;
+ if(!print_hist(ssl, &total))
+ return;
if(!print_ext(ssl, &total))
return;
}
s->svr.ans_rcode_nodata += worker->env.mesh->ans_nodata;
for(i=0; i<16; i++)
s->svr.ans_rcode[i] += worker->env.mesh->ans_rcode[i];
+ timehist_export(worker->env.mesh->histogram, s->svr.hist,
+ NUM_BUCKETS_HIST);
/* values from outside network */
s->svr.unwanted_replies = worker->back->unwanted_replies;
total->svr.qopcode[i] += a->svr.qopcode[i];
for(i=0; i<STATS_RCODE_NUM; i++)
total->svr.ans_rcode[i] += a->svr.ans_rcode[i];
+ for(i=0; i<NUM_BUCKETS_HIST; i++)
+ total->svr.hist[i] += a->svr.hist[i];
}
total->mesh_num_states += a->mesh_num_states;
#ifndef DAEMON_STATS_H
#define DAEMON_STATS_H
+#include "util/timehist.h"
struct worker;
struct config_file;
struct comm_point;
size_t unwanted_replies;
/** unwanted traffic received on client-facing ports */
size_t unwanted_queries;
+
+ /** histogram data exported to array
+ * if the array is the same size, no data is lost, and
+ * if all histograms are same size (is so by default) then
+ * adding up works well. */
+ size_t hist[NUM_BUCKETS_HIST];
};
/**
- munin plugin improvements.
- nicer abbreviations for high query types values (ixfr, axfr, any...)
- documented the statistics output in unbound-control man page.
+ - extended statistics prints out histogram, over unbound-control.
17 September 2008: Wouter
- locking for threadsafe bogus rrset counter.
Memory in bytes in use by the validator module. Includes the key cache and
negative cache.
.TP
+.I histogram.<sec>.<usec>.to.<sec>.<usec>
+Shows a histogram, summed over all threads. Every element counts the
+recursive queries whose reply time fit between the lower and upper bound.
+Times larger or equal to the lowerbound, and smaller than the upper bound.
+There are 40 buckets, with bucket sizes doubling.
+.TP
.I num.query.type.A
The total number of queries over all threads with query type A.
Printed for the other query types as well, but only for the types for which
sizeof(struct timehist));
if(!hist)
return NULL;
- hist->num = 40;
+ hist->num = NUM_BUCKETS_HIST;
hist->buckets = (struct th_buck*)calloc(hist->num,
sizeof(struct th_buck));
if(!hist->buckets) {
res = (lookfor - passed)*(up-low)/((double)hist->buckets[i].count);
return res;
}
+
+void
+timehist_export(struct timehist* hist, size_t* array, size_t sz)
+{
+ size_t i;
+ if(!hist) return;
+ if(sz > hist->num)
+ sz = hist->num;
+ for(i=0; i<sz; i++)
+ array[i] = hist->buckets[i].count;
+}
+
+void
+timehist_import(struct timehist* hist, size_t* array, size_t sz)
+{
+ size_t i;
+ if(!hist) return;
+ if(sz > hist->num)
+ sz = hist->num;
+ for(i=0; i<sz; i++)
+ hist->buckets[i].count = array[i];
+}
#ifndef UTIL_TIMEHIST_H
#define UTIL_TIMEHIST_H
+/** Number of buckets in a histogram */
+#define NUM_BUCKETS_HIST 40
+
/**
* Bucket of time history information
*/
*/
void timehist_log(struct timehist* hist, const char* name);
+/**
+ * Export histogram to an array.
+ * @param hist: histogram
+ * @param array: the array to export to.
+ * @param sz: number of items in array.
+ */
+void timehist_export(struct timehist* hist, size_t* array, size_t sz);
+
+/**
+ * Import histogram from an array.
+ * @param hist: histogram
+ * @param array: the array to import from.
+ * @param sz: number of items in array.
+ */
+void timehist_import(struct timehist* hist, size_t* array, size_t sz);
+
#endif /* UTIL_TIMEHIST_H */