From a7b0ae7b8c122dd2ad44e952b49ca6bf374bb92b Mon Sep 17 00:00:00 2001 From: damocles Date: Sun, 30 Aug 2026 19:58:06 +0200 Subject: [PATCH] otel: add deltatocumulative processor to the hive collector pipeline hive-metric counters are delta by default; VictoriaMetrics has no delta-to-cumulative processor of its own and official guidance is to feed it cumulative. Converting at the hive tier, closest to the origin, means every downstream consumer (swarm tier, VictoriaMetrics, upstream) sees ordinary cumulative counters and existing PromQL idioms (rate()/increase()) keep working unchanged. Default config is a no-op passthrough for anything already cumulative (Claude Code's own export, hostmetrics, Prometheus scrapes) -- verified against the actual collector binary (otelcol-contrib validate), not assumed: an empty config validates clean, an invalid key is rejected. --- nix/host-modules/otel.nix | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/nix/host-modules/otel.nix b/nix/host-modules/otel.nix index 19a44f6a..2b6c32a1 100644 --- a/nix/host-modules/otel.nix +++ b/nix/host-modules/otel.nix @@ -489,6 +489,18 @@ in }; }; + # Converts any DELTA-temporality counter to CUMULATIVE before it + # leaves this hive. `hive-metric` counters are delta by default + # (agent ergonomics — see its own docs); the swarm's store + # (VictoriaMetrics) has no `deltatocumulative` of its own and + # official guidance is to feed it cumulative. Default config + # (`{ }`) is a no-op passthrough for anything already cumulative + # — Claude Code's own export, `hostmetrics`, and any Prometheus + # scrape all stay exactly as they were. Verified against the + # collector binary rather than assumed: an empty config validates + # clean, an invalid key is rejected (`otelcol-contrib validate`). + processors.deltatocumulative = { }; + service.pipelines.metrics = { # EXTENDED, not replaced. Assigning here instead of appending # would drop `otlp` — the hive would stop receiving from its @@ -512,8 +524,12 @@ in # samples scraped from a target both arrive at the store with # the identity of the machine that collected them, and a # reading is only comparable across hives once it says where - # it came from. - processors = [ "resourcedetection" ]; + # it came from. `deltatocumulative` first, so a delta counter is + # already fixed up by the time it picks up its host identity. + processors = [ + "deltatocumulative" + "resourcedetection" + ]; exporters = [ swarmName ]; }; }