]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Expose the incoming transfers' rates in the statistics channel
authorAram Sargsyan <aram@isc.org>
Wed, 27 Nov 2024 10:34:40 +0000 (10:34 +0000)
committerArаm Sаrgsyаn <aram@isc.org>
Thu, 20 Feb 2025 09:32:55 +0000 (09:32 +0000)
Expose the average transfer rate (in bytes-per-second) during the
last full 'min-transfer-rate-in <bytes> <minutes>' minutes interval.
If no such interval has passed yet, then the overall average rate is
reported instead.

bin/named/bind9.xsl
bin/named/statschannel.c
doc/arm/reference.rst
lib/dns/include/dns/xfrin.h
lib/dns/xfrin.c

index ac15b7c934257ec327ff6a2681f96d195f0f7c7b..ae1820de0d50669a9307aea7a05c45bbb18c0fc9 100644 (file)
                   <th>Messages Received</th>
                   <th>Records Received</th>
                   <th>Bytes Received</th>
+                  <th>Transfer Rate (B/s)</th>
                 </tr>
               </thead>
               <tbody>
                     <td><xsl:value-of select="nmsg"/></td>
                     <td><xsl:value-of select="nrecs"/></td>
                     <td><xsl:value-of select="nbytes"/></td>
+                    <td><xsl:value-of select="rate"/></td>
                   </tr>
                 </xsl:for-each>
               </tbody>
index 887f21a1ed11e6ba535226b5c3ae349cf515d6fc..8b1a1cd91ca092245479ca700693576bd83ecded 100644 (file)
@@ -1488,6 +1488,7 @@ xfrin_xmlrender(dns_zone_t *zone, void *arg) {
        unsigned int nmsg = 0;
        unsigned int nrecs = 0;
        uint64_t nbytes = 0;
+       uint64_t rate = 0;
 
        statlevel = dns_zone_getstatlevel(zone);
        if (statlevel == dns_zonestat_none) {
@@ -1701,7 +1702,7 @@ xfrin_xmlrender(dns_zone_t *zone, void *arg) {
        TRY0(xmlTextWriterEndElement(writer));
 
        if (is_running) {
-               dns_xfrin_getstats(xfr, &nmsg, &nrecs, &nbytes);
+               dns_xfrin_getstats(xfr, &nmsg, &nrecs, &nbytes, &rate);
        }
        TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "nmsg"));
        TRY0(xmlTextWriterWriteFormatString(writer, "%u", nmsg));
@@ -1712,6 +1713,9 @@ xfrin_xmlrender(dns_zone_t *zone, void *arg) {
        TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "nbytes"));
        TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, nbytes));
        TRY0(xmlTextWriterEndElement(writer));
+       TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "rate"));
+       TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, rate));
+       TRY0(xmlTextWriterEndElement(writer));
 
        TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ixfr"));
        if (is_running && is_first_data_received) {
@@ -2559,6 +2563,7 @@ xfrin_jsonrender(dns_zone_t *zone, void *arg) {
        unsigned int nmsg = 0;
        unsigned int nrecs = 0;
        uint64_t nbytes = 0;
+       uint64_t rate = 0;
 
        statlevel = dns_zone_getstatlevel(zone);
        if (statlevel == dns_zonestat_none) {
@@ -2756,7 +2761,7 @@ xfrin_jsonrender(dns_zone_t *zone, void *arg) {
        }
 
        if (is_running) {
-               dns_xfrin_getstats(xfr, &nmsg, &nrecs, &nbytes);
+               dns_xfrin_getstats(xfr, &nmsg, &nrecs, &nbytes, &rate);
        }
        json_object_object_add(xfrinobj, "nmsg",
                               json_object_new_int64((int64_t)nmsg));
@@ -2766,6 +2771,10 @@ xfrin_jsonrender(dns_zone_t *zone, void *arg) {
                xfrinobj, "nbytes",
                json_object_new_int64(nbytes > INT64_MAX ? INT64_MAX
                                                         : (int64_t)nbytes));
+       json_object_object_add(xfrinobj, "rate",
+                              json_object_new_int64(rate > INT64_MAX
+                                                            ? INT64_MAX
+                                                            : (int64_t)rate));
 
        if (is_running && is_first_data_received) {
                json_object_object_add(
index d541d705d608c7117332a5a253d105449bbc136a..1af27775945a43677e47a1f8d54baecda85be3e6 100644 (file)
@@ -7835,6 +7835,12 @@ Incoming Zone Transfers
       64-bit unsigned Integer. This is the number of usable bytes
       of DNS data. It does not include transport overhead.
 
+   ``Transfer Rate (B/s)`` (``rate``)
+      64 bit unsigned Integer. This is the average zone transfer rate in
+      bytes-per-second during the latest full interval that is configured by the
+      :any:`min-transfer-rate-in` configuration option. If no such interval
+      has passed yet, then the overall average rate is reported instead.
+
    .. note::
       Depending on the current state of the transfer, some of the
       values may be empty or set to ``-`` (meaning "not available").
index 52c74ec91a0b603cbdd5f7cbf4e300fac15af329..161737abfa151196ebe58e18fcf4a16498dd594f 100644 (file)
@@ -140,10 +140,13 @@ dns_xfrin_getendserial(dns_xfrin_t *xfr);
 
 void
 dns_xfrin_getstats(dns_xfrin_t *xfr, unsigned int *nmsgp, unsigned int *nrecsp,
-                  uint64_t *nbytesp);
+                  uint64_t *nbytesp, uint64_t *ratep);
 /*%<
  * Get various statistics values of the xfrin object: number of the received
- * messages, number of the received records, number of the received bytes.
+ * messages, number of the received records, number of the received bytes,
+ * and the average transfer rate (in bytes-per-second) during the last full
+ * 'min-transfer-rate-in <bytes> <minutes>' minutes interval. If no such
+ * interval has passed yet, then the overall average rate is reported instead.
  *
  * Requires:
  *\li  'xfr' is a valid dns_xfrin_t.
index c6167900c4d0472bfd8ebd7d417ab4a8395f49ca..a352d93353a44cbaf7c424ebfe2213dae4dcd1e5 100644 (file)
@@ -154,6 +154,7 @@ struct dns_xfrin {
        atomic_uint nrecs;           /*%< Number of records recvd */
        atomic_uint_fast64_t nbytes; /*%< Number of bytes received */
        _Atomic(isc_time_t) start;   /*%< Start time of the transfer */
+       atomic_uint_fast64_t rate_bytes_per_second;
        _Atomic(dns_transport_type_t) soa_transport_type;
        atomic_uint_fast32_t end_serial;
 
@@ -975,13 +976,21 @@ xfrin_minratecheck(void *arg) {
 
        const uint64_t nbytes = atomic_load_relaxed(&xfr->nbytes);
        const uint64_t min = dns_zone_getminxfrratebytesin(xfr->zone);
+       uint64_t rate = nbytes - xfr->nbytes_saved;
 
-       if (nbytes - xfr->nbytes_saved < min) {
+       if (rate < min) {
                isc_timer_stop(xfr->min_rate_timer);
                xfrin_fail(xfr, ISC_R_TIMEDOUT,
                           "minimum transfer rate reached");
        } else {
                xfr->nbytes_saved = nbytes;
+
+               /*
+                * Calculate and store for the statistics channel the transfer
+                * rate in bytes-per-second for the latest interval.
+                */
+               rate /= dns_zone_getminxfrratesecondsin(xfr->zone);
+               atomic_store_relaxed(&xfr->rate_bytes_per_second, rate);
        }
 }
 
@@ -1046,13 +1055,29 @@ dns_xfrin_getendserial(dns_xfrin_t *xfr) {
 
 void
 dns_xfrin_getstats(dns_xfrin_t *xfr, unsigned int *nmsgp, unsigned int *nrecsp,
-                  uint64_t *nbytesp) {
+                  uint64_t *nbytesp, uint64_t *ratep) {
        REQUIRE(VALID_XFRIN(xfr));
        REQUIRE(nmsgp != NULL && nrecsp != NULL && nbytesp != NULL);
 
+       uint64_t rate = atomic_load_relaxed(&xfr->rate_bytes_per_second);
+       if (rate == 0) {
+               /*
+                * Likely the first 'min-transfer-rate-in <bytes> <minutes>'
+                * minutes interval hasn't passed yet. Calculate the overall
+                * average transfer rate instead.
+                */
+               isc_time_t now = isc_time_now();
+               isc_time_t start = atomic_load_relaxed(&xfr->start);
+               uint64_t sec = isc_time_microdiff(&now, &start) / US_PER_SEC;
+               if (sec > 0) {
+                       rate = atomic_load_relaxed(&xfr->nbytes) / sec;
+               }
+       }
+
        SET_IF_NOT_NULL(nmsgp, atomic_load_relaxed(&xfr->nmsg));
        SET_IF_NOT_NULL(nrecsp, atomic_load_relaxed(&xfr->nrecs));
        SET_IF_NOT_NULL(nbytesp, atomic_load_relaxed(&xfr->nbytes));
+       SET_IF_NOT_NULL(ratep, rate);
 }
 
 const isc_sockaddr_t *