]> git.ipfire.org Git - telemetry.git/commitdiff
graphs: knot-resolver: Add a new latency graph
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 12 Jul 2026 11:59:20 +0000 (11:59 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 12 Jul 2026 11:59:20 +0000 (11:59 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/daemon/graphs.c
src/daemon/graphs/graph.h
src/daemon/graphs/knot-resolver.c
src/daemon/graphs/knot-resolver.h

index 2c0a6c1b6c04711c5c853774eeff06fffe6be2f9..071e06d3c9ae31dbe9c875c0bad47b6df5429b25 100644 (file)
@@ -99,6 +99,7 @@ static const td_graph_impl* graph_impls[] = {
        &knot_resolver_transports_graph,
        &knot_resolver_responses_graph,
        &knot_resolver_response_time_graph,
+       &knot_resolver_latency_graph,
 
        // Unbound
        &unbound_cache_performance_graph,
index 3c7b4a50cf162e4fd80fc03ee1ee4170c97f6a6a..e205fb86f35aba4003fbaaa36d620457c80941c5 100644 (file)
@@ -292,6 +292,15 @@ static inline int __DRAW(td_args* args, const char* what, const char* field,
 
 #define COMPUTE_CDEF(args, cdef, ...)                  SCRIPT(args, "CDEF:" cdef, ##__VA_ARGS__)
 
+#define COMPUTE_ADD(args, sum, object1, summand1, object2, summand2) \
+       do { \
+               COMPUTE_CDEF(args, FIELD "=" FIELD "," TOSTRING(summand2) ",+", \
+                       FIELD_AND_OBJECT(sum, object1), \
+                       FIELD_AND_OBJECT(summand1, object2) \
+               ); \
+               VALUE_ALL(args, sum, object1); \
+       } while (0)
+
 #define COMPUTE_SUM(args, sum, object1, summand1, object2, summand2, object3) \
        do { \
                COMPUTE_CDEF(args, FIELD "=" FIELD "," FIELD ",+", \
@@ -321,6 +330,25 @@ static inline int __DRAW(td_args* args, const char* what, const char* field,
                VALUE_ALL(args, product, object1); \
        } while (0)
 
+#define COMPUTE_DIVIDE(args, fraction, object1, dividend, object2, divisor) \
+       do { \
+               COMPUTE_CDEF(args, FIELD "=" FIELD "," TOSTRING(divisor) ",/", \
+                       FIELD_AND_OBJECT(fraction, object1), \
+                       FIELD_AND_OBJECT(dividend, object2) \
+               ); \
+               VALUE_ALL(args, fraction, object1); \
+       } while (0)
+
+#define COMPUTE_DIVIDE_BY(args, fraction, object1, dividend, object2, divisor, object3) \
+       do { \
+               COMPUTE_CDEF(args, FIELD "=" FIELD "," FIELD ",/", \
+                       FIELD_AND_OBJECT(fraction, object1), \
+                       FIELD_AND_OBJECT(dividend, object2), \
+                       FIELD_AND_OBJECT(divisor,  object3) \
+               ); \
+               VALUE_ALL(args, fraction, object1); \
+       } while (0)
+
 // Converts bytes to bits
 #define COMPUTE_BITS(args, bits, object, bytes)        \
        COMPUTE_MULTIPLY(args, bits, object, bytes, object, 8)
@@ -344,15 +372,6 @@ static inline int __DRAW(td_args* args, const char* what, const char* field,
                VALUE_ALL(args, FIELD_FAHRENHEIT(field), object); \
        } while (0)
 
-#define COMPUTE_DIVIDE(args, fraction, object1, dividend, object2, divisor) \
-       do { \
-               COMPUTE_CDEF(args, FIELD "=" FIELD "," TOSTRING(divisor) ",/", \
-                       FIELD_AND_OBJECT(fraction, object1), \
-                       FIELD_AND_OBJECT(dividend, object2) \
-               ); \
-               VALUE_ALL(args, fraction, object1); \
-       } while (0)
-
 #define COMPUTE_PERCENTAGE(args, field, object1, total, object2) \
        do { \
                COMPUTE_CDEF(args, FIELD "=100," FIELD ",*," FIELD ",/", \
index bb4e3224e1b5ebe68ddfe770edb64c3b963a5ec2..1ec08e501da9fd4a21c1f3e68e7f00da7868a467 100644 (file)
@@ -347,3 +347,51 @@ const td_graph_impl knot_resolver_response_time_graph = {
        .lower_limit = 0,
        .upper_limit = LONG_MAX,
 };
+
+// Latency
+
+static int knot_resolver_latency_title(td_ctx* ctx, td_graph* graph,
+               const char* object, char* title, size_t length) {
+       return __td_string_set(title, length, _("Latency"));
+}
+
+static int knot_resolver_latency_render(td_ctx* ctx, td_graph* graph,
+               const td_graph_render_options* options, td_args* args, const char* object) {
+       int r;
+
+       // Load all sources
+       r = td_graph_load_source(graph, args, "knot-resolver", NULL);
+       if (r < 0)
+               return r;
+
+       // Add one to the total so we won't divide by zero
+       COMPUTE_ADD(args, "answer_totalp1", NULL, "answer_total", NULL, 1);
+
+       // Compute average response time
+       COMPUTE_DIVIDE_BY(args, "latency_ms", NULL,
+               "answer_sum_ms", NULL, "answer_totalp1", NULL);
+
+       // Convert into seconds
+       COMPUTE_DIVIDE(args, "latency", NULL, "latency_ms", NULL, 1000);
+
+       // Header
+       PRINT_HEADER4(args, _("Current"), _("Average"), _("Minimum"), _("Maximum"));
+
+       // Draw the latency
+       DRAW_LINE_WITH_LABEL(args, 1, "latency", NULL, COLOR_LATENCY, 0, _("Latency"));
+       PRINT_CAMM(args, "latency", NULL, SECONDS_HIGHRES);
+
+       return 0;
+}
+
+const td_graph_impl knot_resolver_latency_graph = {
+       .name        = "KnotResolverLatency",
+       .can_render  = knot_resolver_can_render,
+       .render      = knot_resolver_latency_render,
+       .title       = knot_resolver_latency_title,
+       .vlabel      = td_graph_vlabel_seconds,
+
+       // Limits
+       .lower_limit = 0,
+       .upper_limit = LONG_MAX,
+};
index 849c4c01f70d75ba3222fd85027a761004890577..266cd2cd72d93e552bca7344b7cea4405b535fc1 100644 (file)
@@ -28,5 +28,6 @@ extern const td_graph_impl knot_resolver_cache_graph;
 extern const td_graph_impl knot_resolver_transports_graph;
 extern const td_graph_impl knot_resolver_responses_graph;
 extern const td_graph_impl knot_resolver_response_time_graph;
+extern const td_graph_impl knot_resolver_latency_graph;
 
 #endif /* TELEMETRY_GRAPH_KNOT_RESOLVER_H */