diff --git a/nix/host-modules/swarm-otel.nix b/nix/host-modules/swarm-otel.nix index 525bac27..8f23d3ca 100644 --- a/nix/host-modules/swarm-otel.nix +++ b/nix/host-modules/swarm-otel.nix @@ -70,6 +70,12 @@ let }; caBundle = caTrust.bundlePathFor cfg.machine; + # `unknown` rather than omitting the label, copying `agent-modules/otel.nix` + # deliberately: a producer that cannot name its swarm should say so in the + # same vocabulary as every other producer, so a query never has to handle + # both "the label is absent" and "the label says unknown". + swarmDisplayName = if hyperhiveCfg.swarm.name == null then "unknown" else hyperhiveCfg.swarm.name; + # One list, read by every pipeline: the per-hive pipelines fan out to # exactly the same destinations as the single pipeline they replace. # Written once because "which exporters" is a property of this tier, not @@ -489,6 +495,24 @@ in value = h; action = "upsert"; } + # Stamped here rather than on a separate upstream-only + # pipeline, which would double the pipeline count to + # withhold one constant label from the local store. It + # is redundant there — one VictoriaMetrics per swarm, so + # every series in it already belongs to this swarm — but + # a constant label multiplies no series, and it means + # what LEAVES and what STAYS have the same shape. + # + # Upstream is where it stops being redundant: that is the + # one hop where several swarms can land in one store, and + # samples that cannot name their swarm collide there + # exactly as hives collided here before per-hive + # receivers existed. + { + key = "swarm"; + value = swarmDisplayName; + action = "upsert"; + } ]; } ) hivePorts;