From 4f51cfef051925eee7ecfdd31180d7adbd73e8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Dosko=C4=8Dil?= Date: Tue, 20 Jan 2026 16:55:35 +0100 Subject: [PATCH] stats: extend base server metrics --- src/knot/common/stats.c | 27 +++++++++++++++++++++++++++ src/knot/common/stats.h | 21 +++++++++++++++++++++ src/knot/server/tcp-handler.c | 13 +++++++++---- src/knot/server/udp-handler.c | 2 ++ 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/knot/common/stats.c b/src/knot/common/stats.c index 66c9009bd..2f432d641 100644 --- a/src/knot/common/stats.c +++ b/src/knot/common/stats.c @@ -17,6 +17,8 @@ #include "knot/nameserver/query_module.h" #include "libknot/xdp.h" +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + static uint64_t stats_get_counter(knot_atomic_uint64_t **stats_vals, uint32_t offset, unsigned threads) { @@ -109,6 +111,26 @@ int stats_xdp(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx) return KNOT_EOK; } +const char *server_stat_names[] = { + "udp_received", + "udp_async_done", + "udp_no_req_obj", + "udp_req_batch_limited", + "tcp_accept", + "tcp_received", + "tcp_async_done", + "tcp_no_req_obj", + "tcp_multiple_req", +}; + +static knot_atomic_uint64_t server_stat_counters[ARRAY_SIZE(server_stat_names)]; + +void server_stats_increment_counter(server_stats_counter_t counter, uint64_t value) +{ + assert(counter < server_stats_max); + ATOMIC_ADD(server_stat_counters[counter], value); +} + #define DUMP_VAL(params, it, val) { \ (params).item = (it); \ (params).value = (val); \ @@ -130,6 +152,9 @@ int stats_server(stats_dump_ctr_f fcn, stats_dump_ctx_t *ctx) DUMP_VAL(params, "zone-update-error", ATOMIC_GET(ctx->server->stats.zone_update_error)); DUMP_VAL(params, "tcp-io-timeout", ATOMIC_GET(ctx->server->stats.tcp_io_timeout)); DUMP_VAL(params, "tcp-idle-timeout", ATOMIC_GET(ctx->server->stats.tcp_idle_timeout)); + for (size_t i = 0; i < ARRAY_SIZE(server_stat_names); i++) { + DUMP_VAL(params, server_stat_names[i], ATOMIC_GET(server_stat_counters[i])); + } return KNOT_EOK; } @@ -450,6 +475,8 @@ static void *dumper(void *data) void stats_reconfigure(conf_t *conf, server_t *server) { + _Static_assert(server_stats_max == ARRAY_SIZE(server_stat_names), ""); // Ensure enum and names are setup consistently. + if (conf == NULL || server == NULL) { return; } diff --git a/src/knot/common/stats.h b/src/knot/common/stats.h index 757fa8b92..44e5ec7bd 100644 --- a/src/knot/common/stats.h +++ b/src/knot/common/stats.h @@ -49,6 +49,27 @@ typedef struct { */ typedef int (*stats_dump_ctr_f)(stats_dump_params_t *, stats_dump_ctx_t *); +/*! + * \brief Statistics metrics item. + */ +typedef enum { + server_stats_udp_received, + server_stats_udp_async_done, + server_stats_udp_no_req_obj, + server_stats_udp_req_batch_limited, + server_stats_tcp_accept, + server_stats_tcp_received, + server_stats_tcp_async_done, + server_stats_tcp_no_req_obj, + server_stats_tcp_multiple_req, + server_stats_max, +} server_stats_counter_t; + +/*! + * \brief Increment the server stats. + */ +void server_stats_increment_counter(server_stats_counter_t counter, uint64_t value); + /*! * \brief XDP metrics. */ diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c index 402f54db3..084b74260 100644 --- a/src/knot/server/tcp-handler.c +++ b/src/knot/server/tcp-handler.c @@ -33,6 +33,7 @@ #include "contrib/sockaddr.h" #include "contrib/time.h" #include "contrib/ucw/mempool.h" +#include "knot/common/stats.h" /*! \brief TCP context data. */ typedef struct tcp_context { @@ -338,12 +339,16 @@ static void tcp_wait_for_events(tcp_context_t *tcp) if (idx < tcp->client_threshold) { /* Don't accept more clients than configured. */ if (fdset_get_length(set) < tcp->max_worker_fds) { + server_stats_increment_counter(server_stats_tcp_accept, 1); tcp_event_accept(tcp, idx, iface); } - /* Client sockets - already accepted connection or - closed connection :-( */ - } else if (tcp_event_serve(tcp, idx, iface) != KNOT_EOK) { - should_close = true; + } else { + server_stats_increment_counter(server_stats_tcp_received, 1); + /* Client sockets - already accepted connection or + closed connection :-( */ + if (tcp_event_serve(tcp, idx, iface) != KNOT_EOK) { + should_close = true; + } } } diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c index df249fa9f..60d8f075a 100644 --- a/src/knot/server/udp-handler.c +++ b/src/knot/server/udp-handler.c @@ -27,6 +27,7 @@ #include "contrib/ucw/mempool.h" #include "knot/common/fdset.h" #include "knot/common/log.h" +#include "knot/common/stats.h" #include "knot/nameserver/process_query.h" #include "knot/query/layer.h" #include "knot/server/handler.h" @@ -618,6 +619,7 @@ int udp_master(dthread_t *thread) if (!fdset_it_is_pollin(&it)) { continue; } + server_stats_increment_counter(server_stats_udp_received, 1); if (api->udp_recv(fdset_it_get_fd(&it), api_ctx) > 0) { const iface_t *iface = fdset_it_get_ctx(&it); assert(iface);