#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 ",+", \
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)
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 ",/", \
.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,
+};