mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
new: usr: Provide response round-trip time (RTT) counters via statistics channel
Previously, :iscman:`named` provided RTT counters for outgoing queries performed by itself during name resolutions. Now this has been improved to provide more granular counters (histogram), and to also provide RTT counters for the incoming queries. Closes #5279 Merge branch '5279-query-rtt-isc_histo_t-statistics' into 'main' See merge request isc-projects/bind9!11508
This commit is contained in:
commit
e7b1a44b8c
19 changed files with 685 additions and 170 deletions
|
|
@ -941,6 +941,52 @@
|
|||
</table>
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
<xsl:for-each select="views/view">
|
||||
<xsl:if test="rtt/counters[@type="in-queries-rtt"]/counter[. > 0]">
|
||||
<h3>Incoming Queries Response Time for View <xsl:value-of select="@name"/></h3>
|
||||
<table class="counters">
|
||||
<tr>
|
||||
<th>Milliseconds</th>
|
||||
<th>Count</th>
|
||||
</tr>
|
||||
<xsl:for-each select="rtt/counters[@type="in-queries-rtt"]/counter">
|
||||
<xsl:variable name="css-class8">
|
||||
<xsl:choose>
|
||||
<xsl:when test="position() mod 2 = 0">even</xsl:when>
|
||||
<xsl:otherwise>odd</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<tr class="{$css-class8}">
|
||||
<td><xsl:value-of select="@name"/></td>
|
||||
<td><xsl:value-of select="."/></td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</table>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="views/view">
|
||||
<xsl:if test="rtt/counters[@type="out-queries-rtt"]/counter[. > 0]">
|
||||
<h3>Outgoing Queries Response Time for View <xsl:value-of select="@name"/></h3>
|
||||
<table class="counters">
|
||||
<tr>
|
||||
<th>Milliseconds</th>
|
||||
<th>Count</th>
|
||||
</tr>
|
||||
<xsl:for-each select="rtt/counters[@type="out-queries-rtt"]/counter">
|
||||
<xsl:variable name="css-class8">
|
||||
<xsl:choose>
|
||||
<xsl:when test="position() mod 2 = 0">even</xsl:when>
|
||||
<xsl:otherwise>odd</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<tr class="{$css-class8}">
|
||||
<td><xsl:value-of select="@name"/></td>
|
||||
<td><xsl:value-of select="."/></td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</table>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<xsl:if test="memory/summary">
|
||||
<h2>Memory Usage Summary</h2>
|
||||
<table class="counters">
|
||||
|
|
|
|||
|
|
@ -3678,6 +3678,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
const cfg_obj_t *disablelist = NULL;
|
||||
isc_stats_t *resstats = NULL;
|
||||
dns_stats_t *resquerystats = NULL;
|
||||
isc_histomulti_t *resqueryinrttstats = NULL;
|
||||
isc_histomulti_t *resqueryoutrttstats = NULL;
|
||||
bool auto_root = false;
|
||||
named_cache_t *nsc = NULL;
|
||||
bool zero_no_soattl;
|
||||
|
|
@ -4259,6 +4261,9 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
dns_resolver_getstats(pview->resolver, &resstats);
|
||||
dns_resolver_getquerystats(pview->resolver,
|
||||
&resquerystats);
|
||||
dns_resolver_getqueryrttstats(pview->resolver,
|
||||
&resqueryinrttstats,
|
||||
&resqueryoutrttstats);
|
||||
dns_view_detach(&pview);
|
||||
}
|
||||
}
|
||||
|
|
@ -4319,11 +4324,23 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
isc_stats_create(mctx, &resstats, dns_resstatscounter_max);
|
||||
}
|
||||
dns_resolver_setstats(view->resolver, resstats);
|
||||
|
||||
if (resquerystats == NULL) {
|
||||
dns_rdatatypestats_create(mctx, &resquerystats);
|
||||
}
|
||||
dns_resolver_setquerystats(view->resolver, resquerystats);
|
||||
|
||||
if (resqueryinrttstats == NULL) {
|
||||
isc_histomulti_create(mctx, DNS_RTTHISTO_SIGBITS,
|
||||
&resqueryinrttstats);
|
||||
}
|
||||
if (resqueryoutrttstats == NULL) {
|
||||
isc_histomulti_create(mctx, DNS_RTTHISTO_SIGBITS,
|
||||
&resqueryoutrttstats);
|
||||
}
|
||||
dns_resolver_setqueryrttstats(view->resolver, resqueryinrttstats,
|
||||
resqueryoutrttstats);
|
||||
|
||||
/*
|
||||
* Set the ADB cache size to 1/8th of the max-cache-size or
|
||||
* MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared.
|
||||
|
|
@ -5487,6 +5504,12 @@ cleanup:
|
|||
if (resquerystats != NULL) {
|
||||
dns_stats_detach(&resquerystats);
|
||||
}
|
||||
if (resqueryinrttstats != NULL) {
|
||||
isc_histomulti_detach(&resqueryinrttstats);
|
||||
}
|
||||
if (resqueryoutrttstats != NULL) {
|
||||
isc_histomulti_detach(&resqueryoutrttstats);
|
||||
}
|
||||
if (order != NULL) {
|
||||
dns_order_detach(&order);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ static const char *tcpinsizestats_xmldesc[dns_sizecounter_in_max];
|
|||
static const char *tcpoutsizestats_xmldesc[dns_sizecounter_out_max];
|
||||
static const char *dnstapstats_xmldesc[dns_dnstapcounter_max];
|
||||
static const char *gluecachestats_xmldesc[dns_gluecachestatscounter_max];
|
||||
static const char *queryrttinstats_xmldesc[dns_queryrttcounter_in_max];
|
||||
static const char *queryrttoutstats_xmldesc[dns_queryrttcounter_in_max];
|
||||
#else /* if defined(EXTENDED_STATS) */
|
||||
#define nsstats_xmldesc NULL
|
||||
#define resstats_xmldesc NULL
|
||||
|
|
@ -203,6 +205,8 @@ static int tcpinsizestats_index[dns_sizecounter_in_max];
|
|||
static int tcpoutsizestats_index[dns_sizecounter_out_max];
|
||||
static int dnstapstats_index[dns_dnstapcounter_max];
|
||||
static int gluecachestats_index[dns_gluecachestatscounter_max];
|
||||
static int queryrttinstats_index[dns_queryrttcounter_in_max];
|
||||
static int queryrttoutstats_index[dns_queryrttcounter_out_max];
|
||||
|
||||
static void
|
||||
set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs,
|
||||
|
|
@ -223,7 +227,7 @@ set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs,
|
|||
}
|
||||
|
||||
static const char *
|
||||
get_histo_desc(const char *prefix, int i, int inf, bool ext) {
|
||||
get_sizehisto_desc(const char *prefix, int i, int inf, bool ext) {
|
||||
static char buf[(DNS_SIZEHISTO_MAXIN + DNS_SIZEHISTO_MAXOUT) * 80];
|
||||
static size_t used = 0;
|
||||
char *desc = buf + used;
|
||||
|
|
@ -246,6 +250,51 @@ get_histo_desc(const char *prefix, int i, int inf, bool ext) {
|
|||
return desc;
|
||||
}
|
||||
|
||||
#if defined(EXTENDED_STATS)
|
||||
static const char *
|
||||
get_rtthisto_desc(const char *prefix, unsigned int i, unsigned int inf,
|
||||
uint64_t min, uint64_t max, bool ext) {
|
||||
static char buf[DNS_RTTHISTO_MAX * 80];
|
||||
static size_t used = 0;
|
||||
char *desc = buf + used;
|
||||
size_t space = sizeof(buf) - used;
|
||||
int len = 0;
|
||||
|
||||
if (!ext && i < inf) {
|
||||
if (min == max) {
|
||||
if (min == 0) {
|
||||
len = snprintf(desc, space, "%s ~0 ms", prefix);
|
||||
} else {
|
||||
len = snprintf(desc, space, "%s %" PRIu64 " ms",
|
||||
prefix, min);
|
||||
}
|
||||
} else {
|
||||
len = snprintf(desc, space,
|
||||
"%s %" PRIu64 "-%" PRIu64 " ms", prefix,
|
||||
min, max);
|
||||
}
|
||||
} else if (!ext && i >= inf) {
|
||||
len = snprintf(desc, space, "%s %" PRIu64 "+ ms", prefix, min);
|
||||
} else if (ext && i < inf) {
|
||||
if (min == max) {
|
||||
if (min == 0) {
|
||||
len = snprintf(desc, space, "~0");
|
||||
} else {
|
||||
len = snprintf(desc, space, "%" PRIu64, min);
|
||||
}
|
||||
} else {
|
||||
len = snprintf(desc, space, "%" PRIu64 "-%" PRIu64, min,
|
||||
max);
|
||||
}
|
||||
} else if (ext && i >= inf) {
|
||||
len = snprintf(desc, space, "%" PRIu64 "+", min);
|
||||
}
|
||||
INSIST(0 < len && (size_t)len < space);
|
||||
used += len + 1;
|
||||
return desc;
|
||||
}
|
||||
#endif /* if defined(EXTENDED_STATS) */
|
||||
|
||||
static void
|
||||
init_desc(void) {
|
||||
int i;
|
||||
|
|
@ -441,28 +490,6 @@ init_desc(void) {
|
|||
SET_RESSTATDESC(valnegsuccess, "DNSSEC NX validation succeeded",
|
||||
"ValNegOk");
|
||||
SET_RESSTATDESC(valfail, "DNSSEC validation failed", "ValFail");
|
||||
SET_RESSTATDESC(queryrtt0,
|
||||
"queries with RTT < " DNS_RESOLVER_QRYRTTCLASS0STR "ms",
|
||||
"QryRTT" DNS_RESOLVER_QRYRTTCLASS0STR);
|
||||
SET_RESSTATDESC(queryrtt1,
|
||||
"queries with RTT " DNS_RESOLVER_QRYRTTCLASS0STR
|
||||
"-" DNS_RESOLVER_QRYRTTCLASS1STR "ms",
|
||||
"QryRTT" DNS_RESOLVER_QRYRTTCLASS1STR);
|
||||
SET_RESSTATDESC(queryrtt2,
|
||||
"queries with RTT " DNS_RESOLVER_QRYRTTCLASS1STR
|
||||
"-" DNS_RESOLVER_QRYRTTCLASS2STR "ms",
|
||||
"QryRTT" DNS_RESOLVER_QRYRTTCLASS2STR);
|
||||
SET_RESSTATDESC(queryrtt3,
|
||||
"queries with RTT " DNS_RESOLVER_QRYRTTCLASS2STR
|
||||
"-" DNS_RESOLVER_QRYRTTCLASS3STR "ms",
|
||||
"QryRTT" DNS_RESOLVER_QRYRTTCLASS3STR);
|
||||
SET_RESSTATDESC(queryrtt4,
|
||||
"queries with RTT " DNS_RESOLVER_QRYRTTCLASS3STR
|
||||
"-" DNS_RESOLVER_QRYRTTCLASS4STR "ms",
|
||||
"QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR);
|
||||
SET_RESSTATDESC(queryrtt5,
|
||||
"queries with RTT > " DNS_RESOLVER_QRYRTTCLASS4STR "ms",
|
||||
"QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR "+");
|
||||
SET_RESSTATDESC(nfetch, "active fetches", "NumFetch");
|
||||
SET_RESSTATDESC(buckets, "bucket size", "BucketSize");
|
||||
SET_RESSTATDESC(refused, "REFUSED received", "REFUSED");
|
||||
|
|
@ -764,11 +791,11 @@ init_desc(void) {
|
|||
for (i = 0; i < DNS_SIZEHISTO_MAXOUT; i++) {
|
||||
udpoutsizestats_index[i] = i;
|
||||
tcpoutsizestats_index[i] = i;
|
||||
udpoutsizestats_desc[i] = get_histo_desc(
|
||||
udpoutsizestats_desc[i] = get_sizehisto_desc(
|
||||
"responses sent", i, DNS_SIZEHISTO_MAXOUT, false);
|
||||
tcpoutsizestats_desc[i] = udpoutsizestats_desc[i];
|
||||
#if defined(EXTENDED_STATS)
|
||||
udpoutsizestats_xmldesc[i] = get_histo_desc(
|
||||
udpoutsizestats_xmldesc[i] = get_sizehisto_desc(
|
||||
"responses sent", i, DNS_SIZEHISTO_MAXOUT, true);
|
||||
tcpoutsizestats_xmldesc[i] = udpoutsizestats_xmldesc[i];
|
||||
#endif /* if defined(EXTENDED_STATS) */
|
||||
|
|
@ -777,7 +804,7 @@ init_desc(void) {
|
|||
for (i = 0; i <= DNS_SIZEHISTO_MAXIN; i++) {
|
||||
udpinsizestats_index[i] = i;
|
||||
tcpinsizestats_index[i] = i;
|
||||
udpinsizestats_desc[i] = get_histo_desc(
|
||||
udpinsizestats_desc[i] = get_sizehisto_desc(
|
||||
"requests received", i, DNS_SIZEHISTO_MAXIN, false);
|
||||
tcpinsizestats_desc[i] = udpinsizestats_desc[i];
|
||||
#if defined(EXTENDED_STATS)
|
||||
|
|
@ -786,10 +813,25 @@ init_desc(void) {
|
|||
tcpinsizestats_xmldesc[i] = tcpoutsizestats_xmldesc[i];
|
||||
} else {
|
||||
udpinsizestats_xmldesc[i] =
|
||||
get_histo_desc("requests received", i,
|
||||
DNS_SIZEHISTO_MAXIN, true);
|
||||
get_sizehisto_desc("requests received", i,
|
||||
DNS_SIZEHISTO_MAXIN, true);
|
||||
tcpinsizestats_xmldesc[i] = udpinsizestats_xmldesc[i];
|
||||
}
|
||||
#endif /* if defined(EXTENDED_STATS) */
|
||||
}
|
||||
|
||||
for (i = 0; i <= DNS_RTTHISTO_MAX; i++) {
|
||||
queryrttinstats_index[i] = i;
|
||||
queryrttoutstats_index[i] = i;
|
||||
|
||||
#if defined(EXTENDED_STATS)
|
||||
/*
|
||||
* The descriptions are filled in during dumping (only once),
|
||||
* because we don't have the isc_histomulti_t objects here
|
||||
* to determine their non-linear minimum and maximum values.
|
||||
*/
|
||||
queryrttinstats_xmldesc[i] = NULL;
|
||||
queryrttoutstats_xmldesc[i] = NULL;
|
||||
#endif /* if defined(EXTENDED_STATS) */
|
||||
}
|
||||
}
|
||||
|
|
@ -832,13 +874,26 @@ dump_stats(isc_stats_t *stats, isc_statsformat_t type, void *arg,
|
|||
#if defined(EXTENDED_STATS)
|
||||
static isc_result_t
|
||||
dump_histo(isc_histomulti_t *hm, isc_statsformat_t type, void *arg,
|
||||
const char *category, const char **desc, int ncounters, int *indices,
|
||||
uint64_t *values, int options) {
|
||||
const char *category, const char **desc, const char *desc_prefix,
|
||||
int ncounters, int *indices, uint64_t *values, int options) {
|
||||
isc_histo_t *hg = NULL;
|
||||
uint64_t min, max;
|
||||
|
||||
isc_histomulti_merge(&hg, hm);
|
||||
for (int i = 0; i < ncounters; i++) {
|
||||
isc_histo_get(hg, i, NULL, NULL, &values[i]);
|
||||
isc_histo_get(hg, i, &min, &max, &values[i]);
|
||||
|
||||
/*
|
||||
* RTT descriptions are generated during the first call of
|
||||
* this function for the corresponding histogram, the other
|
||||
* descriptions are pregenerated and the caller shouldn't
|
||||
* provide a prefix.
|
||||
*/
|
||||
if (desc[i] == NULL && desc_prefix != NULL) {
|
||||
desc[i] = get_rtthisto_desc(desc_prefix, i,
|
||||
DNS_RTTHISTO_MAX, min, max,
|
||||
true);
|
||||
}
|
||||
}
|
||||
isc_histo_destroy(&hg);
|
||||
|
||||
|
|
@ -1765,6 +1820,8 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
uint64_t udpoutsizestat_values[DNS_SIZEHISTO_MAXOUT + 1];
|
||||
uint64_t tcpinsizestat_values[DNS_SIZEHISTO_MAXIN + 1];
|
||||
uint64_t tcpoutsizestat_values[DNS_SIZEHISTO_MAXOUT + 1];
|
||||
uint64_t queryrttinstat_values[DNS_RTTHISTO_MAX + 1];
|
||||
uint64_t queryrttoutstat_values[DNS_RTTHISTO_MAX + 1];
|
||||
#ifdef HAVE_DNSTAP
|
||||
uint64_t dnstapstat_values[dns_dnstapcounter_max];
|
||||
#endif /* ifdef HAVE_DNSTAP */
|
||||
|
|
@ -1921,7 +1978,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
ISC_XMLCHAR "request-size"));
|
||||
|
||||
CHECK(dump_histo(server->sctx->udpinstats4, isc_statsformat_xml,
|
||||
writer, NULL, udpinsizestats_xmldesc,
|
||||
writer, NULL, udpinsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_in_max, udpinsizestats_index,
|
||||
udpinsizestat_values, 0));
|
||||
|
||||
|
|
@ -1931,10 +1988,11 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
|
||||
ISC_XMLCHAR "response-size"));
|
||||
|
||||
CHECK(dump_histo(
|
||||
server->sctx->udpoutstats4, isc_statsformat_xml, writer,
|
||||
NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max,
|
||||
udpoutsizestats_index, udpoutsizestat_values, 0));
|
||||
CHECK(dump_histo(server->sctx->udpoutstats4,
|
||||
isc_statsformat_xml, writer, NULL,
|
||||
udpoutsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_out_max, udpoutsizestats_index,
|
||||
udpoutsizestat_values, 0));
|
||||
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </udp> */
|
||||
|
|
@ -1945,7 +2003,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
ISC_XMLCHAR "request-size"));
|
||||
|
||||
CHECK(dump_histo(server->sctx->tcpinstats4, isc_statsformat_xml,
|
||||
writer, NULL, tcpinsizestats_xmldesc,
|
||||
writer, NULL, tcpinsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_in_max, tcpinsizestats_index,
|
||||
tcpinsizestat_values, 0));
|
||||
|
||||
|
|
@ -1954,10 +2012,11 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
|
||||
ISC_XMLCHAR "response-size"));
|
||||
|
||||
CHECK(dump_histo(
|
||||
server->sctx->tcpoutstats4, isc_statsformat_xml, writer,
|
||||
NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max,
|
||||
tcpoutsizestats_index, tcpoutsizestat_values, 0));
|
||||
CHECK(dump_histo(server->sctx->tcpoutstats4,
|
||||
isc_statsformat_xml, writer, NULL,
|
||||
tcpoutsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_out_max, tcpoutsizestats_index,
|
||||
tcpoutsizestat_values, 0));
|
||||
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </tcp> */
|
||||
|
|
@ -1970,7 +2029,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
ISC_XMLCHAR "request-size"));
|
||||
|
||||
CHECK(dump_histo(server->sctx->udpinstats6, isc_statsformat_xml,
|
||||
writer, NULL, udpinsizestats_xmldesc,
|
||||
writer, NULL, udpinsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_in_max, udpinsizestats_index,
|
||||
udpinsizestat_values, 0));
|
||||
|
||||
|
|
@ -1980,10 +2039,11 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
|
||||
ISC_XMLCHAR "response-size"));
|
||||
|
||||
CHECK(dump_histo(
|
||||
server->sctx->udpoutstats6, isc_statsformat_xml, writer,
|
||||
NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max,
|
||||
udpoutsizestats_index, udpoutsizestat_values, 0));
|
||||
CHECK(dump_histo(server->sctx->udpoutstats6,
|
||||
isc_statsformat_xml, writer, NULL,
|
||||
udpoutsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_out_max, udpoutsizestats_index,
|
||||
udpoutsizestat_values, 0));
|
||||
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </udp> */
|
||||
|
|
@ -1994,7 +2054,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
ISC_XMLCHAR "request-size"));
|
||||
|
||||
CHECK(dump_histo(server->sctx->tcpinstats6, isc_statsformat_xml,
|
||||
writer, NULL, tcpinsizestats_xmldesc,
|
||||
writer, NULL, tcpinsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_in_max, tcpinsizestats_index,
|
||||
tcpinsizestat_values, 0));
|
||||
|
||||
|
|
@ -2004,10 +2064,11 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
|
||||
ISC_XMLCHAR "response-size"));
|
||||
|
||||
CHECK(dump_histo(
|
||||
server->sctx->tcpoutstats6, isc_statsformat_xml, writer,
|
||||
NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max,
|
||||
tcpoutsizestats_index, tcpoutsizestat_values, 0));
|
||||
CHECK(dump_histo(server->sctx->tcpoutstats6,
|
||||
isc_statsformat_xml, writer, NULL,
|
||||
tcpoutsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_out_max, tcpoutsizestats_index,
|
||||
tcpoutsizestat_values, 0));
|
||||
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </tcp> */
|
||||
|
|
@ -2027,6 +2088,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
isc_stats_t *istats = NULL;
|
||||
dns_stats_t *dstats = NULL;
|
||||
dns_adb_t *adb = NULL;
|
||||
isc_histomulti_t *hmpin = NULL, *hmpout = NULL;
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "view"));
|
||||
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
|
||||
|
|
@ -2120,6 +2182,40 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
TRY0(dns_cache_renderxml(view->cache, writer));
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </cachestats> */
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "rtt"));
|
||||
|
||||
dns_resolver_getqueryrttstats(view->resolver, &hmpin, &hmpout);
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
|
||||
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
|
||||
ISC_XMLCHAR "in-queries-rtt"));
|
||||
if (hmpin != NULL) {
|
||||
CHECK(dump_histo(hmpin, isc_statsformat_xml, writer,
|
||||
NULL, queryrttinstats_xmldesc,
|
||||
"RTT (in)", dns_queryrttcounter_in_max,
|
||||
queryrttinstats_index,
|
||||
queryrttinstat_values, 0));
|
||||
isc_histomulti_detach(&hmpin);
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters"));
|
||||
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
|
||||
ISC_XMLCHAR
|
||||
"out-queries-rtt"));
|
||||
if (hmpout != NULL) {
|
||||
CHECK(dump_histo(hmpout, isc_statsformat_xml, writer,
|
||||
NULL, queryrttoutstats_xmldesc,
|
||||
"RTT (out)",
|
||||
dns_queryrttcounter_out_max,
|
||||
queryrttoutstats_index,
|
||||
queryrttoutstat_values, 0));
|
||||
isc_histomulti_detach(&hmpout);
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </counters> */
|
||||
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* </rtt> */
|
||||
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* view */
|
||||
|
||||
view = ISC_LIST_NEXT(view, link);
|
||||
|
|
@ -2818,6 +2914,8 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
|
|||
uint64_t udpoutsizestat_values[dns_sizecounter_out_max];
|
||||
uint64_t tcpinsizestat_values[dns_sizecounter_in_max];
|
||||
uint64_t tcpoutsizestat_values[dns_sizecounter_out_max];
|
||||
uint64_t queryrttinstat_values[DNS_RTTHISTO_MAX + 1];
|
||||
uint64_t queryrttoutstat_values[DNS_RTTHISTO_MAX + 1];
|
||||
#ifdef HAVE_DNSTAP
|
||||
uint64_t dnstapstat_values[dns_dnstapcounter_max];
|
||||
#endif /* ifdef HAVE_DNSTAP */
|
||||
|
|
@ -3027,6 +3125,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
|
|||
ISC_LIST_FOREACH(server->viewlist, view, link) {
|
||||
json_object *za, *xa, *v = json_object_new_object();
|
||||
dns_adb_t *adb = NULL;
|
||||
isc_histomulti_t *hmpin = NULL, *hmpout = NULL;
|
||||
|
||||
CHECKMEM(v);
|
||||
json_object_object_add(viewlist, view->name, v);
|
||||
|
|
@ -3170,6 +3269,45 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
|
|||
json_object_object_add(res, "adb",
|
||||
counters);
|
||||
}
|
||||
|
||||
dns_resolver_getqueryrttstats(view->resolver,
|
||||
&hmpin, &hmpout);
|
||||
if (hmpin != NULL) {
|
||||
counters = json_object_new_object();
|
||||
CHECKMEM(counters);
|
||||
|
||||
CHECK(dump_histo(
|
||||
hmpin, isc_statsformat_json,
|
||||
counters, NULL,
|
||||
queryrttinstats_xmldesc,
|
||||
"RTT (in)",
|
||||
dns_queryrttcounter_in_max,
|
||||
queryrttinstats_index,
|
||||
queryrttinstat_values, 0));
|
||||
isc_histomulti_detach(&hmpin);
|
||||
|
||||
json_object_object_add(res,
|
||||
"in-queries-rtt",
|
||||
counters);
|
||||
}
|
||||
if (hmpout != NULL) {
|
||||
counters = json_object_new_object();
|
||||
CHECKMEM(counters);
|
||||
|
||||
CHECK(dump_histo(
|
||||
hmpout, isc_statsformat_json,
|
||||
counters, NULL,
|
||||
queryrttoutstats_xmldesc,
|
||||
"RTT (out)",
|
||||
dns_queryrttcounter_out_max,
|
||||
queryrttoutstats_index,
|
||||
queryrttoutstat_values, 0));
|
||||
isc_histomulti_detach(&hmpout);
|
||||
|
||||
json_object_object_add(
|
||||
res, "out-queries-rtt",
|
||||
counters);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3241,49 +3379,49 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
|
|||
|
||||
CHECK(dump_histo(server->sctx->udpinstats4,
|
||||
isc_statsformat_json, udpreq4, NULL,
|
||||
udpinsizestats_xmldesc, dns_sizecounter_in_max,
|
||||
udpinsizestats_index, udpinsizestat_values,
|
||||
0));
|
||||
udpinsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_in_max, udpinsizestats_index,
|
||||
udpinsizestat_values, 0));
|
||||
|
||||
CHECK(dump_histo(server->sctx->udpoutstats4,
|
||||
isc_statsformat_json, udpresp4, NULL,
|
||||
udpoutsizestats_xmldesc,
|
||||
udpoutsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_out_max, udpoutsizestats_index,
|
||||
udpoutsizestat_values, 0));
|
||||
|
||||
CHECK(dump_histo(server->sctx->tcpinstats4,
|
||||
isc_statsformat_json, tcpreq4, NULL,
|
||||
tcpinsizestats_xmldesc, dns_sizecounter_in_max,
|
||||
tcpinsizestats_index, tcpinsizestat_values,
|
||||
0));
|
||||
tcpinsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_in_max, tcpinsizestats_index,
|
||||
tcpinsizestat_values, 0));
|
||||
|
||||
CHECK(dump_histo(server->sctx->tcpoutstats4,
|
||||
isc_statsformat_json, tcpresp4, NULL,
|
||||
tcpoutsizestats_xmldesc,
|
||||
tcpoutsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_out_max, tcpoutsizestats_index,
|
||||
tcpoutsizestat_values, 0));
|
||||
|
||||
CHECK(dump_histo(server->sctx->udpinstats6,
|
||||
isc_statsformat_json, udpreq6, NULL,
|
||||
udpinsizestats_xmldesc, dns_sizecounter_in_max,
|
||||
udpinsizestats_index, udpinsizestat_values,
|
||||
0));
|
||||
udpinsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_in_max, udpinsizestats_index,
|
||||
udpinsizestat_values, 0));
|
||||
|
||||
CHECK(dump_histo(server->sctx->udpoutstats6,
|
||||
isc_statsformat_json, udpresp6, NULL,
|
||||
udpoutsizestats_xmldesc,
|
||||
udpoutsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_out_max, udpoutsizestats_index,
|
||||
udpoutsizestat_values, 0));
|
||||
|
||||
CHECK(dump_histo(server->sctx->tcpinstats6,
|
||||
isc_statsformat_json, tcpreq6, NULL,
|
||||
tcpinsizestats_xmldesc, dns_sizecounter_in_max,
|
||||
tcpinsizestats_index, tcpinsizestat_values,
|
||||
0));
|
||||
tcpinsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_in_max, tcpinsizestats_index,
|
||||
tcpinsizestat_values, 0));
|
||||
|
||||
CHECK(dump_histo(server->sctx->tcpoutstats6,
|
||||
isc_statsformat_json, tcpresp6, NULL,
|
||||
tcpoutsizestats_xmldesc,
|
||||
tcpoutsizestats_xmldesc, NULL,
|
||||
dns_sizecounter_out_max, tcpoutsizestats_index,
|
||||
tcpoutsizestat_values, 0));
|
||||
|
||||
|
|
|
|||
56
bin/tests/system/statschannel/ans5/ans.py
Normal file
56
bin/tests/system/statschannel/ans5/ans.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
"""
|
||||
Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
|
||||
SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
See the COPYRIGHT file distributed with this work for additional
|
||||
information regarding copyright ownership.
|
||||
"""
|
||||
|
||||
from collections.abc import AsyncGenerator
|
||||
|
||||
import dns.rcode
|
||||
import dns.rdatatype
|
||||
import dns.rrset
|
||||
|
||||
from isctest.asyncserver import (
|
||||
ControllableAsyncDnsServer,
|
||||
DnsResponseSend,
|
||||
QueryContext,
|
||||
ResponseHandler,
|
||||
)
|
||||
|
||||
|
||||
class DelayedAddressAnswerHandler(ResponseHandler):
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[DnsResponseSend, None]:
|
||||
if qctx.qtype in (dns.rdatatype.A, dns.rdatatype.AAAA):
|
||||
addr = "192.0.2.1" if qctx.qtype == dns.rdatatype.A else "2001:db8:beef::1"
|
||||
rrset = dns.rrset.from_text(qctx.qname, 300, qctx.qclass, qctx.qtype, addr)
|
||||
qctx.response.answer.append(rrset)
|
||||
|
||||
delay = 0
|
||||
if (
|
||||
len(qctx.qname.labels) >= 2
|
||||
and qctx.qname.labels[1] == b"latency"
|
||||
and qctx.qname.labels[0].isdigit()
|
||||
):
|
||||
delay = int(qctx.qname.labels[0]) / 1000
|
||||
yield DnsResponseSend(qctx.response, delay=delay)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server = ControllableAsyncDnsServer(
|
||||
default_aa=True, default_rcode=dns.rcode.NOERROR
|
||||
)
|
||||
server.install_response_handler(DelayedAddressAnswerHandler())
|
||||
server.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -58,6 +58,11 @@ def check_zone_timers(loaded, expires, refresh, loaded_exp):
|
|||
check_loaded(loaded, loaded_exp, now)
|
||||
|
||||
|
||||
def check_rtt(rtt, rtt_expected):
|
||||
for val in rtt_expected:
|
||||
assert rtt[val[0]] == val[1]
|
||||
|
||||
|
||||
#
|
||||
# The output is gibberish, but at least make sure it does not crash.
|
||||
#
|
||||
|
|
@ -225,3 +230,33 @@ def test_traffic(fetch_traffic, **kwargs):
|
|||
data = fetch_traffic(statsip, statsport)
|
||||
|
||||
check_traffic(data, exp)
|
||||
|
||||
|
||||
def test_rtt(fetch_views, **kwargs):
|
||||
statsip = kwargs["statsip"]
|
||||
statsport = kwargs["statsport"]
|
||||
|
||||
# auth query, 0 delay is expected, only for "in"
|
||||
msg = create_msg("a.example2.", "TXT")
|
||||
ans = isctest.query.tcp(msg, statsip, attempts=1)
|
||||
isctest.check.noerror(ans)
|
||||
|
||||
# resolver query with a 530ms delay for both "in" and "out"
|
||||
msg = create_msg("530.latency.example2.", "A")
|
||||
ans = isctest.query.tcp(msg, statsip, attempts=1)
|
||||
isctest.check.noerror(ans)
|
||||
|
||||
# resolver query with a 540ms delay for both "in" and "out"
|
||||
msg = create_msg("540.latency.example2.", "A")
|
||||
ans = isctest.query.tcp(msg, statsip, attempts=1)
|
||||
isctest.check.noerror(ans)
|
||||
|
||||
# resolver query with a 730ms delay for both "in" and "out"
|
||||
msg = create_msg("730.latency.example2.", "A")
|
||||
ans = isctest.query.tcp(msg, statsip, attempts=1)
|
||||
isctest.check.noerror(ans)
|
||||
|
||||
data = fetch_views(statsip, statsport)
|
||||
|
||||
check_rtt(data["in-queries-rtt"], [["~0", 1], ["512-575", 2], ["704-767", 1]])
|
||||
check_rtt(data["out-queries-rtt"], [["512-575", 2], ["704-767", 1]])
|
||||
|
|
|
|||
28
bin/tests/system/statschannel/ns4/example2.db
Normal file
28
bin/tests/system/statschannel/ns4/example2.db
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
$ORIGIN .
|
||||
$TTL 300 ; 5 minutes
|
||||
example2 IN SOA mname1. . (
|
||||
1 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
example2. NS ns4.example2.
|
||||
ns4.example2. A 10.53.0.4
|
||||
|
||||
$ORIGIN example2.
|
||||
a A 10.0.0.1
|
||||
|
||||
latency NS ns5.example2.
|
||||
ns5.example2. A 10.53.0.5
|
||||
44
bin/tests/system/statschannel/ns4/named.conf.j2
Normal file
44
bin/tests/system/statschannel/ns4/named.conf.j2
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.4;
|
||||
notify-source 10.53.0.4;
|
||||
transfer-source 10.53.0.4;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.4; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
dnssec-validation no;
|
||||
notify no;
|
||||
minimal-responses no;
|
||||
version none; // make statistics independent of the version number
|
||||
};
|
||||
|
||||
statistics-channels { inet 10.53.0.4 port @EXTRAPORT1@ allow { localhost; }; };
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "example2" {
|
||||
type primary;
|
||||
file "example2.db";
|
||||
allow-transfer { any; };
|
||||
};
|
||||
|
|
@ -24,6 +24,7 @@ pytestmark = [
|
|||
isctest.mark.with_json_c,
|
||||
pytest.mark.extra_artifacts(
|
||||
[
|
||||
"ans5/ans.run",
|
||||
"ns2/*.jnl",
|
||||
"ns2/*.signed",
|
||||
"ns2/dsset-*",
|
||||
|
|
@ -62,6 +63,19 @@ def fetch_traffic_json(statsip, statsport):
|
|||
return data["traffic"]
|
||||
|
||||
|
||||
def fetch_rtt_json(statsip, statsport):
|
||||
r = requests.get(f"http://{statsip}:{statsport}/json/v1", timeout=600)
|
||||
assert r.status_code == 200
|
||||
|
||||
views = r.json()["views"]
|
||||
data = {
|
||||
"in-queries-rtt": views["_default"]["resolver"]["in-queries-rtt"],
|
||||
"out-queries-rtt": views["_default"]["resolver"]["out-queries-rtt"],
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def load_timers_json(zone, primary=True):
|
||||
name = zone["name"]
|
||||
|
||||
|
|
@ -119,3 +133,8 @@ def test_zone_with_many_keys_json(statsport):
|
|||
@pytest.mark.flaky(max_runs=2)
|
||||
def test_traffic_json(statsport):
|
||||
generic.test_traffic(fetch_traffic_json, statsip="10.53.0.2", statsport=statsport)
|
||||
|
||||
|
||||
@pytest.mark.flaky(max_runs=2)
|
||||
def test_rtt_json(statsport):
|
||||
generic.test_rtt(fetch_rtt_json, statsip="10.53.0.4", statsport=statsport)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import pytest
|
|||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"K*",
|
||||
"ans5/ans.run",
|
||||
"bind9.xsl.1",
|
||||
"bind9.xsl.2",
|
||||
"compressed.headers",
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ pytestmark = [
|
|||
pytest.mark.extra_artifacts(
|
||||
[
|
||||
"ns2/K*",
|
||||
"ans5/ans.run",
|
||||
"ns2/*.jnl",
|
||||
"ns2/*.signed",
|
||||
"ns2/dsset-*",
|
||||
|
|
@ -91,6 +92,35 @@ def fetch_traffic_xml(statsip, statsport):
|
|||
return traffic
|
||||
|
||||
|
||||
def fetch_rtt_xml(statsip, statsport):
|
||||
def load_counters(data):
|
||||
out = {}
|
||||
for counter in data.findall("counter"):
|
||||
out[counter.attrib["name"]] = int(counter.text)
|
||||
|
||||
return out
|
||||
|
||||
r = requests.get(f"http://{statsip}:{statsport}/xml/v3", timeout=600)
|
||||
assert r.status_code == 200
|
||||
|
||||
root = ET.fromstring(r.text)
|
||||
|
||||
default_view = None
|
||||
for view in root.find("views").iter("view"):
|
||||
if view.attrib["name"] == "_default":
|
||||
default_view = view
|
||||
break
|
||||
assert default_view is not None
|
||||
|
||||
rtt = {}
|
||||
for counters in default_view.find("rtt").findall("counters"):
|
||||
key = counters.attrib["type"]
|
||||
values = load_counters(counters)
|
||||
rtt[key] = values
|
||||
|
||||
return rtt
|
||||
|
||||
|
||||
def load_timers_xml(zone, primary=True):
|
||||
name = zone.attrib["name"]
|
||||
|
||||
|
|
@ -149,3 +179,8 @@ def test_zone_with_many_keys_xml(statsport):
|
|||
@pytest.mark.flaky(max_runs=2)
|
||||
def test_traffic_xml(statsport):
|
||||
generic.test_traffic(fetch_traffic_xml, statsip="10.53.0.2", statsport=statsport)
|
||||
|
||||
|
||||
@pytest.mark.flaky(max_runs=2)
|
||||
def test_rtt_xml(statsport):
|
||||
generic.test_rtt(fetch_rtt_xml, statsip="10.53.0.4", statsport=statsport)
|
||||
|
|
|
|||
|
|
@ -8468,9 +8468,6 @@ Resolver Statistics Counters
|
|||
``ValFail``
|
||||
This indicates the number of failed DNSSEC validations.
|
||||
|
||||
``QryRTTnn``
|
||||
This provides a frequency table on query round-trip times (RTTs). Each ``nn`` specifies the corresponding frequency. In the sequence of ``nn_1``, ``nn_2``, ..., ``nn_m``, the value of ``nn_i`` is the number of queries whose RTTs are between ``nn_(i-1)`` (inclusive) and ``nn_i`` (exclusive) milliseconds. For the sake of convenience, we define ``nn_0`` to be 0. The last entry should be represented as ``nn_m+``, which means the number of queries whose RTTs are equal to or greater than ``nn_m`` milliseconds.
|
||||
|
||||
``NumFetch``
|
||||
This indicates the number of active fetches.
|
||||
|
||||
|
|
@ -8516,6 +8513,21 @@ Resolver Statistics Counters
|
|||
``Priming``
|
||||
This indicates the number of priming fetches performed by the resolver.
|
||||
|
||||
.. _resolver_rtt_stats:
|
||||
|
||||
Resolver Queries Response Time counters
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:iscman:`named` provides query response round-trip time (RTT) counters
|
||||
(histogram) both for incoming and outgoing queries in milliseconds. Response
|
||||
times which are lower than 1ms are calculated under the ``~0`` counter.
|
||||
Response times from 1ms to 15ms are calculated under their own counters, e.g. a
|
||||
response that took 5ms to complete is calculated under the ``5`` counter.
|
||||
Response times starting from 16ms are calculated under the ``MinMS-MaxMS``
|
||||
(inclusive) range counters. For example, a response that took 18ms to complete
|
||||
is calculated under the ``18-19`` counter, and a response that took 550ms to
|
||||
complete is calculated under the ``512-575`` counter.
|
||||
|
||||
.. _socket_stats:
|
||||
|
||||
Socket I/O Statistics Counters
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include <netinet/in.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <isc/histo.h>
|
||||
#include <isc/loop.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/stats.h>
|
||||
|
|
@ -143,21 +144,6 @@ enum {
|
|||
DNS_FETCHOPT_EDNSVERSIONMASK = 0xff000000,
|
||||
};
|
||||
|
||||
/*
|
||||
* Upper bounds of class of query RTT (ms). Corresponds to
|
||||
* dns_resstatscounter_queryrttX statistics counters.
|
||||
*/
|
||||
#define DNS_RESOLVER_QRYRTTCLASS0 10
|
||||
#define DNS_RESOLVER_QRYRTTCLASS0STR "10"
|
||||
#define DNS_RESOLVER_QRYRTTCLASS1 100
|
||||
#define DNS_RESOLVER_QRYRTTCLASS1STR "100"
|
||||
#define DNS_RESOLVER_QRYRTTCLASS2 500
|
||||
#define DNS_RESOLVER_QRYRTTCLASS2STR "500"
|
||||
#define DNS_RESOLVER_QRYRTTCLASS3 800
|
||||
#define DNS_RESOLVER_QRYRTTCLASS3STR "800"
|
||||
#define DNS_RESOLVER_QRYRTTCLASS4 1600
|
||||
#define DNS_RESOLVER_QRYRTTCLASS4STR "1600"
|
||||
|
||||
/*
|
||||
* XXXRTH Should this API be made semi-private? (I.e.
|
||||
* _dns_resolver_create()).
|
||||
|
|
@ -586,8 +572,7 @@ dns_resolver_setstats(dns_resolver_t *res, isc_stats_t *stats);
|
|||
*
|
||||
* Requires:
|
||||
* \li 'res' is valid.
|
||||
*
|
||||
*\li stats is a valid statistics supporting resolver statistics counters
|
||||
* \li stats is a valid statistics supporting resolver statistics counters
|
||||
* (see dns/stats.h).
|
||||
*/
|
||||
|
||||
|
|
@ -600,8 +585,7 @@ dns_resolver_getstats(dns_resolver_t *res, isc_stats_t **statsp);
|
|||
*
|
||||
* Requires:
|
||||
* \li 'res' is valid.
|
||||
*
|
||||
*\li 'statsp' != NULL && '*statsp' != NULL
|
||||
* \li 'statsp' != NULL && '*statsp' != NULL
|
||||
*/
|
||||
|
||||
void
|
||||
|
|
@ -623,8 +607,7 @@ dns_resolver_setquerystats(dns_resolver_t *res, dns_stats_t *stats);
|
|||
*
|
||||
* Requires:
|
||||
* \li 'res' is valid.
|
||||
*
|
||||
*\li stats is a valid statistics created by dns_rdatatypestats_create().
|
||||
* \li 'stats' is a valid statistics created by dns_rdatatypestats_create().
|
||||
*/
|
||||
|
||||
void
|
||||
|
|
@ -636,8 +619,36 @@ dns_resolver_getquerystats(dns_resolver_t *res, dns_stats_t **statsp);
|
|||
*
|
||||
* Requires:
|
||||
* \li 'res' is valid.
|
||||
* \li 'statsp' != NULL && '*statsp' != NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_resolver_setqueryrttstats(dns_resolver_t *res, isc_histomulti_t *hmin,
|
||||
isc_histomulti_t *hmout);
|
||||
/*%<
|
||||
* Set a query RTT statistics histograms 'hmin' and 'hmout' for 'res'. Once the
|
||||
* statistic histograms are installed, the resolver will start updating them
|
||||
* with the incoming and outgoing queries' RTT values accordingly.
|
||||
*
|
||||
*\li 'statsp' != NULL && '*statsp' != NULL
|
||||
* Requires:
|
||||
* \li 'res' is valid.
|
||||
* \li 'stats' is a valid statistics created by dns_rdatatypestats_create().
|
||||
* \li 'hmin' is a valid isc_histomulti_t object.
|
||||
* \li 'hmout' is a valid isc_histomulti_t object.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_resolver_getqueryrttstats(dns_resolver_t *res, isc_histomulti_t **hmpin,
|
||||
isc_histomulti_t **hmpout);
|
||||
/*%<
|
||||
* Get the query RTT statistics histograms for 'res'. If the histograms are set
|
||||
* then the corresponding '*hmp{in,out}' are attached to them; otherwise,
|
||||
* '*hmp{in,out}' are untouched.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'res' is valid.
|
||||
* \li 'hmpin' == NULL || '*hmpin' == NULL
|
||||
* \li 'hmpout' == NULL || '*hmpout' == NULL
|
||||
*/
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <isc/histo.h>
|
||||
|
||||
#include <dns/resolver.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
/*%
|
||||
|
|
@ -52,30 +53,24 @@ enum {
|
|||
dns_resstatscounter_dispabort = 21,
|
||||
dns_resstatscounter_dispsockfail = 22,
|
||||
dns_resstatscounter_querytimeout = 23,
|
||||
dns_resstatscounter_queryrtt0 = 24,
|
||||
dns_resstatscounter_queryrtt1 = 25,
|
||||
dns_resstatscounter_queryrtt2 = 26,
|
||||
dns_resstatscounter_queryrtt3 = 27,
|
||||
dns_resstatscounter_queryrtt4 = 28,
|
||||
dns_resstatscounter_queryrtt5 = 29,
|
||||
dns_resstatscounter_nfetch = 30,
|
||||
dns_resstatscounter_disprequdp = 31,
|
||||
dns_resstatscounter_dispreqtcp = 32,
|
||||
dns_resstatscounter_buckets = 33,
|
||||
dns_resstatscounter_refused = 34,
|
||||
dns_resstatscounter_cookienew = 35,
|
||||
dns_resstatscounter_cookieout = 36,
|
||||
dns_resstatscounter_cookiein = 37,
|
||||
dns_resstatscounter_cookieok = 38,
|
||||
dns_resstatscounter_badvers = 39,
|
||||
dns_resstatscounter_badcookie = 40,
|
||||
dns_resstatscounter_zonequota = 41,
|
||||
dns_resstatscounter_serverquota = 42,
|
||||
dns_resstatscounter_clientquota = 43,
|
||||
dns_resstatscounter_nextitem = 44,
|
||||
dns_resstatscounter_priming = 45,
|
||||
dns_resstatscounter_forwardonlyfail = 46,
|
||||
dns_resstatscounter_max = 47,
|
||||
dns_resstatscounter_nfetch = 24,
|
||||
dns_resstatscounter_disprequdp = 25,
|
||||
dns_resstatscounter_dispreqtcp = 26,
|
||||
dns_resstatscounter_buckets = 27,
|
||||
dns_resstatscounter_refused = 28,
|
||||
dns_resstatscounter_cookienew = 29,
|
||||
dns_resstatscounter_cookieout = 30,
|
||||
dns_resstatscounter_cookiein = 31,
|
||||
dns_resstatscounter_cookieok = 32,
|
||||
dns_resstatscounter_badvers = 33,
|
||||
dns_resstatscounter_badcookie = 34,
|
||||
dns_resstatscounter_zonequota = 35,
|
||||
dns_resstatscounter_serverquota = 36,
|
||||
dns_resstatscounter_clientquota = 37,
|
||||
dns_resstatscounter_nextitem = 38,
|
||||
dns_resstatscounter_priming = 39,
|
||||
dns_resstatscounter_forwardonlyfail = 40,
|
||||
dns_resstatscounter_max = 41,
|
||||
|
||||
/*
|
||||
* DNSSEC stats.
|
||||
|
|
@ -203,6 +198,24 @@ enum {
|
|||
dns_sizecounter_out_max = DNS_SIZEHISTO_MAXOUT + 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* This gives enough amount of buckets in the lower end of the values (which
|
||||
* are the values up to about 30000 milliseconds (MAXIMUM_QUERY_TIMEOUT) to make
|
||||
* sense for the resolver) to be useful and not to be too many. E.g. bucket
|
||||
* number 30 covers values between 56 and 59, while bucket number 102 covers the
|
||||
* values between 28672 and 30719.
|
||||
*/
|
||||
#define DNS_RTTHISTO_SIGBITS 3
|
||||
#define DNS_RTTHISTO_MAX 102
|
||||
|
||||
/*
|
||||
* For consistency with other stats counters
|
||||
*/
|
||||
enum {
|
||||
dns_queryrttcounter_in_max = DNS_RTTHISTO_MAX + 1,
|
||||
dns_queryrttcounter_out_max = DNS_RTTHISTO_MAX + 1,
|
||||
};
|
||||
|
||||
/*%
|
||||
* Attributes for statistics counters of RRset and Rdatatype types.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <isc/hash.h>
|
||||
#include <isc/hashmap.h>
|
||||
#include <isc/hex.h>
|
||||
#include <isc/histo.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/loop.h>
|
||||
|
|
@ -207,7 +208,11 @@
|
|||
#define DEFAULT_QUERY_TIMEOUT (MAX_SINGLE_QUERY_TIMEOUT + 1000U)
|
||||
#endif /* ifndef DEFAULT_QUERY_TIMEOUT */
|
||||
|
||||
/* The maximum time in seconds for the whole query to live. */
|
||||
/*
|
||||
* The maximum time in seconds for the whole query to live.
|
||||
*
|
||||
* Note: if increased, DNS_RTTHISTO_MAX should also be updated.
|
||||
*/
|
||||
#ifndef MAXIMUM_QUERY_TIMEOUT
|
||||
#define MAXIMUM_QUERY_TIMEOUT 30000
|
||||
#endif /* ifndef MAXIMUM_QUERY_TIMEOUT */
|
||||
|
|
@ -598,6 +603,8 @@ struct dns_resolver {
|
|||
isc_result_t quotaresp[2];
|
||||
isc_stats_t *stats;
|
||||
dns_stats_t *querystats;
|
||||
isc_histomulti_t *queryinrttstats;
|
||||
isc_histomulti_t *queryoutrttstats;
|
||||
|
||||
/* Additions for serve-stale feature. */
|
||||
unsigned int retryinterval; /* in milliseconds */
|
||||
|
|
@ -1255,31 +1262,17 @@ fctx_cancelquery(resquery_t **queryp, isc_time_t *finish, bool no_response,
|
|||
* We have both the start and finish times for this
|
||||
* packet, so we can compute a real RTT.
|
||||
*/
|
||||
unsigned int rttms;
|
||||
|
||||
rtt = (unsigned int)isc_time_microdiff(finish,
|
||||
&query->start);
|
||||
rttms = rtt / US_PER_MS;
|
||||
factor = DNS_ADB_RTTADJDEFAULT;
|
||||
|
||||
if (rttms < DNS_RESOLVER_QRYRTTCLASS0) {
|
||||
inc_stats(fctx->res,
|
||||
dns_resstatscounter_queryrtt0);
|
||||
} else if (rttms < DNS_RESOLVER_QRYRTTCLASS1) {
|
||||
inc_stats(fctx->res,
|
||||
dns_resstatscounter_queryrtt1);
|
||||
} else if (rttms < DNS_RESOLVER_QRYRTTCLASS2) {
|
||||
inc_stats(fctx->res,
|
||||
dns_resstatscounter_queryrtt2);
|
||||
} else if (rttms < DNS_RESOLVER_QRYRTTCLASS3) {
|
||||
inc_stats(fctx->res,
|
||||
dns_resstatscounter_queryrtt3);
|
||||
} else if (rttms < DNS_RESOLVER_QRYRTTCLASS4) {
|
||||
inc_stats(fctx->res,
|
||||
dns_resstatscounter_queryrtt4);
|
||||
} else {
|
||||
inc_stats(fctx->res,
|
||||
dns_resstatscounter_queryrtt5);
|
||||
if (fctx->res->queryoutrttstats != NULL) {
|
||||
const unsigned int rttms = rtt / US_PER_MS;
|
||||
isc_histomulti_inc(
|
||||
fctx->res->queryoutrttstats,
|
||||
rttms < MAXIMUM_QUERY_TIMEOUT
|
||||
? rttms
|
||||
: MAXIMUM_QUERY_TIMEOUT);
|
||||
}
|
||||
} else {
|
||||
uint32_t value;
|
||||
|
|
@ -9642,6 +9635,12 @@ dns_resolver__destroy(dns_resolver_t *res) {
|
|||
dns_nametree_detach(&res->algorithms);
|
||||
dns_nametree_detach(&res->digests);
|
||||
|
||||
if (res->queryoutrttstats != NULL) {
|
||||
isc_histomulti_detach(&res->queryoutrttstats);
|
||||
}
|
||||
if (res->queryinrttstats != NULL) {
|
||||
isc_histomulti_detach(&res->queryinrttstats);
|
||||
}
|
||||
if (res->querystats != NULL) {
|
||||
dns_stats_detach(&res->querystats);
|
||||
}
|
||||
|
|
@ -10884,6 +10883,32 @@ dns_resolver_getquerystats(dns_resolver_t *res, dns_stats_t **statsp) {
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_resolver_setqueryrttstats(dns_resolver_t *res, isc_histomulti_t *hmin,
|
||||
isc_histomulti_t *hmout) {
|
||||
REQUIRE(VALID_RESOLVER(res));
|
||||
REQUIRE(res->queryinrttstats == NULL);
|
||||
REQUIRE(res->queryoutrttstats == NULL);
|
||||
|
||||
isc_histomulti_attach(hmin, &res->queryinrttstats);
|
||||
isc_histomulti_attach(hmout, &res->queryoutrttstats);
|
||||
}
|
||||
|
||||
void
|
||||
dns_resolver_getqueryrttstats(dns_resolver_t *res, isc_histomulti_t **hmpin,
|
||||
isc_histomulti_t **hmpout) {
|
||||
REQUIRE(VALID_RESOLVER(res));
|
||||
REQUIRE(hmpin == NULL || *hmpin == NULL);
|
||||
REQUIRE(hmpout == NULL || *hmpout == NULL);
|
||||
|
||||
if (hmpin != NULL && res->queryinrttstats != NULL) {
|
||||
isc_histomulti_attach(res->queryinrttstats, hmpin);
|
||||
}
|
||||
if (hmpout != NULL && res->queryoutrttstats != NULL) {
|
||||
isc_histomulti_attach(res->queryoutrttstats, hmpout);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_resolver_freefresp(dns_fetchresponse_t **frespp) {
|
||||
REQUIRE(frespp != NULL);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ struct isc_histo {
|
|||
struct isc_histomulti {
|
||||
uint magic;
|
||||
uint size;
|
||||
isc_refcount_t references;
|
||||
isc_histo_t *hg[];
|
||||
};
|
||||
|
||||
|
|
@ -386,22 +387,23 @@ isc_histomulti_create(isc_mem_t *mctx, uint sigbits, isc_histomulti_t **hmp) {
|
|||
isc_histo_create(mctx, sigbits, &hm->hg[i]);
|
||||
}
|
||||
|
||||
isc_refcount_init(&hm->references, 1);
|
||||
|
||||
*hmp = hm;
|
||||
}
|
||||
|
||||
void
|
||||
isc_histomulti_destroy(isc_histomulti_t **hmp) {
|
||||
REQUIRE(hmp != NULL);
|
||||
REQUIRE(HISTOMULTI_VALID(*hmp));
|
||||
static void
|
||||
isc__histomulti_destroy(isc_histomulti_t *hm) {
|
||||
REQUIRE(HISTOMULTI_VALID(hm));
|
||||
|
||||
isc_histomulti_t *hm = *hmp;
|
||||
isc_mem_t *mctx = hm->hg[0]->mctx;
|
||||
*hmp = NULL;
|
||||
|
||||
for (uint i = 0; i < hm->size; i++) {
|
||||
isc_histo_destroy(&hm->hg[i]);
|
||||
}
|
||||
|
||||
isc_refcount_destroy(&hm->references);
|
||||
|
||||
isc_mem_put(mctx, hm, STRUCT_FLEX_SIZE(hm, hg, hm->size));
|
||||
}
|
||||
|
||||
|
|
@ -426,6 +428,12 @@ isc_histomulti_inc(isc_histomulti_t *hm, uint64_t value) {
|
|||
isc_histomulti_add(hm, value, 1);
|
||||
}
|
||||
|
||||
#ifdef ISC_HISTO_TRACE
|
||||
ISC_REFCOUNT_TRACE_IMPL(isc_histomulti, isc__histomulti_destroy);
|
||||
#else
|
||||
ISC_REFCOUNT_IMPL(isc_histomulti, isc__histomulti_destroy);
|
||||
#endif /* ISC_HISTO_TRACE */
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -278,20 +278,6 @@ isc_histomulti_create(isc_mem_t *mctx, uint sigbits, isc_histomulti_t **hmp);
|
|||
*\li `*hmp` is a pointer to a multithreaded sharded histogram.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_histomulti_destroy(isc_histomulti_t **hmp);
|
||||
/*%<
|
||||
* Destroy a multithreaded sharded histogram
|
||||
*
|
||||
* Requires:
|
||||
*\li `hmp != NULL`
|
||||
*\li `*hmp` is a pointer to a valid multithreaded sharded histogram
|
||||
*
|
||||
* Ensures:
|
||||
*\li all memory allocated by the histogram has been released
|
||||
*\li `*hmp == NULL`
|
||||
*/
|
||||
|
||||
void
|
||||
isc_histomulti_merge(isc_histo_t **targetp, const isc_histomulti_t *source);
|
||||
/*%<
|
||||
|
|
@ -326,6 +312,21 @@ isc_histomulti_add(isc_histomulti_t *hm, uint64_t value, uint64_t inc);
|
|||
*\li `hm` is a pointer to a valid histomulti
|
||||
*/
|
||||
|
||||
#ifdef ISC_HISTO_TRACE
|
||||
#define isc_histomulti_ref(ptr) \
|
||||
dns_histomulti__ref(ptr, __func__, __FILE__, __LINE__)
|
||||
#define isc_histomulti_unref(ptr) \
|
||||
isc_histomulti__unref(ptr, __func__, __FILE__, __LINE__)
|
||||
#define isc_histomulti_attach(ptr, ptrp) \
|
||||
isc_histomulti__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
|
||||
#define isc_histomulti_detach(ptrp) \
|
||||
isc_histomulti__detach(ptrp, __func__, __FILE__, __LINE__)
|
||||
|
||||
ISC_REFCOUNT_TRACE_DECL(isc_histomulti);
|
||||
#else
|
||||
ISC_REFCOUNT_DECL(isc_histomulti);
|
||||
#endif /* ISC_HISTO_TRACE */
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -325,7 +325,24 @@ client_senddone(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||
*/
|
||||
client->inner.sendhandle = NULL;
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_histomulti_t *hmpin = NULL;
|
||||
|
||||
if (client->inner.view != NULL &&
|
||||
client->inner.view->resolver != NULL)
|
||||
{
|
||||
dns_resolver_getqueryrttstats(
|
||||
client->inner.view->resolver, &hmpin, NULL);
|
||||
}
|
||||
if (hmpin != NULL) {
|
||||
const unsigned int rtt = (unsigned int)
|
||||
isc_time_microdiff(&client->inner.tnow,
|
||||
&client->inner.requesttime);
|
||||
const unsigned int rttms = rtt / US_PER_MS;
|
||||
isc_histomulti_inc(hmpin, rttms);
|
||||
isc_histomulti_detach(&hmpin);
|
||||
}
|
||||
} else {
|
||||
if (!TCP_CLIENT(client) && result == ISC_R_MAXSIZE) {
|
||||
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
|
||||
|
|
|
|||
|
|
@ -2703,7 +2703,8 @@ stale_refresh_aftermath(ns_client_t *client, isc_result_t result) {
|
|||
* database, starting the stale-refresh-time window for it.
|
||||
* This is a condensed form of query_lookup().
|
||||
*/
|
||||
client->inner.now = isc_stdtime_now();
|
||||
client->inner.tnow = isc_time_now();
|
||||
client->inner.now = isc_time_seconds(&client->inner.tnow);
|
||||
client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
|
||||
qctx_init(client, NULL, 0, &qctx);
|
||||
|
||||
|
|
@ -6076,7 +6077,8 @@ fetch_callback(void *arg) {
|
|||
/*
|
||||
* Update client->now.
|
||||
*/
|
||||
client->inner.now = isc_stdtime_now();
|
||||
client->inner.tnow = isc_time_now();
|
||||
client->inner.now = isc_time_seconds(&client->inner.tnow);
|
||||
} else {
|
||||
/*
|
||||
* This is a fetch completion event for a canceled fetch.
|
||||
|
|
@ -6538,7 +6540,8 @@ query_hookresume(void *arg) {
|
|||
INSIST(rev->ctx == client->query.hookasyncctx);
|
||||
client->query.hookasyncctx = NULL;
|
||||
canceled = false;
|
||||
client->inner.now = isc_stdtime_now();
|
||||
client->inner.tnow = isc_time_now();
|
||||
client->inner.now = isc_time_seconds(&client->inner.tnow);
|
||||
} else {
|
||||
canceled = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,29 +176,29 @@ ns_server_detach(ns_server_t **sctxp) {
|
|||
}
|
||||
|
||||
if (sctx->udpinstats4 != NULL) {
|
||||
isc_histomulti_destroy(&sctx->udpinstats4);
|
||||
isc_histomulti_detach(&sctx->udpinstats4);
|
||||
}
|
||||
if (sctx->tcpinstats4 != NULL) {
|
||||
isc_histomulti_destroy(&sctx->tcpinstats4);
|
||||
isc_histomulti_detach(&sctx->tcpinstats4);
|
||||
}
|
||||
if (sctx->udpoutstats4 != NULL) {
|
||||
isc_histomulti_destroy(&sctx->udpoutstats4);
|
||||
isc_histomulti_detach(&sctx->udpoutstats4);
|
||||
}
|
||||
if (sctx->tcpoutstats4 != NULL) {
|
||||
isc_histomulti_destroy(&sctx->tcpoutstats4);
|
||||
isc_histomulti_detach(&sctx->tcpoutstats4);
|
||||
}
|
||||
|
||||
if (sctx->udpinstats6 != NULL) {
|
||||
isc_histomulti_destroy(&sctx->udpinstats6);
|
||||
isc_histomulti_detach(&sctx->udpinstats6);
|
||||
}
|
||||
if (sctx->tcpinstats6 != NULL) {
|
||||
isc_histomulti_destroy(&sctx->tcpinstats6);
|
||||
isc_histomulti_detach(&sctx->tcpinstats6);
|
||||
}
|
||||
if (sctx->udpoutstats6 != NULL) {
|
||||
isc_histomulti_destroy(&sctx->udpoutstats6);
|
||||
isc_histomulti_detach(&sctx->udpoutstats6);
|
||||
}
|
||||
if (sctx->tcpoutstats6 != NULL) {
|
||||
isc_histomulti_destroy(&sctx->tcpoutstats6);
|
||||
isc_histomulti_detach(&sctx->tcpoutstats6);
|
||||
}
|
||||
|
||||
sctx->magic = 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue