deploy: move the metrics and log store toggles

Same move as grafana, and the three belong together: they derive from one
switch and a store with no UI is as useless as a UI with no store.

`victorialogs` is the case that shows why the option-path sweep is not
enough on its own. It has **zero** references spelled
`swarm.victorialogs.enable` anywhere in the tree, and four spelled
through `let` aliases (`vlCfg.enable` in the collector, `cfg.enable` in
its own module). A sweep for the path would have reported nothing to do
and left every reader broken.

Prose moved with the code rather than being left behind: the comments in
swarm-required-services.nix that explained why the pair derives together
now sit above the assignments that do it, instead of above the gap where
they used to be.
This commit is contained in:
atlas 2026-08-30 03:19:42 +02:00 committed by mara
commit 29647f963e
9 changed files with 77 additions and 61 deletions

View file

@ -33,6 +33,7 @@ let
otelCfg = config.services.hyperhive.otel;
vmCfg = config.services.hyperhive.swarm.victoriametrics;
vlCfg = config.services.hyperhive.swarm.victorialogs;
deployCfg = config.services.hyperhive.deploy;
hyperhiveCfg = config.services.hyperhive;
gatewayCfg = hyperhiveCfg.gateway;
swarmDomain = hyperhiveCfg.swarm.domain;
@ -162,13 +163,14 @@ let
# exactly the same destinations as the single pipeline they replace.
# Written once because "which exporters" is a property of this tier, not
# of which hive a sample came from.
exporterNames = upstreamExporters ++ lib.optional vmCfg.enable "otlphttp/victoriametrics";
exporterNames =
upstreamExporters ++ lib.optional deployCfg.victoriametrics "otlphttp/victoriametrics";
# The same fan-out for logs, and the local store is only ONE of its
# destinations. A deployment that turns the swarm's log store off and keeps
# an upstream endpoint still collects — the store is where logs may be kept,
# not the reason to read the journal at all.
logExporterNames = upstreamExporters ++ lib.optional vlCfg.enable "otlphttp/victorialogs";
logExporterNames = upstreamExporters ++ lib.optional deployCfg.victorialogs "otlphttp/victorialogs";
# Collect when there is anywhere to send it, and only then. A pipeline with
# an empty exporter list is not a quiet no-op — the collector rejects it —
@ -608,12 +610,12 @@ in
# The tier exists to hold the upstream credential and to write the
# swarm's store. With neither, it is a process that receives
# samples and drops them — which looks healthy and loses data.
assertion = otelCfg.endpoint != "" || vmCfg.enable;
assertion = otelCfg.endpoint != "" || deployCfg.victoriametrics;
message = ''
services.hyperhive.swarm.otel.enable is true but this collector
has nowhere to send what it receives:
services.hyperhive.otel.endpoint is empty and
services.hyperhive.swarm.victoriametrics.enable is false.
services.hyperhive.deploy.victoriametrics is false.
Set the endpoint to export upstream, or enable the swarm's
metrics store.
@ -780,7 +782,7 @@ in
cfg.producerPort
otelCfg.collector.port
]
++ lib.optional vmCfg.enable vmCfg.port;
++ lib.optional deployCfg.victoriametrics vmCfg.port;
all = derived ++ others;
in
lib.length (lib.unique all) == lib.length all;
@ -1015,7 +1017,7 @@ in
};
exporters =
lib.optionalAttrs vmCfg.enable {
lib.optionalAttrs deployCfg.victoriametrics {
# `metrics_endpoint`, NOT `endpoint`: the latter is a
# base that otlphttp appends `/v1/metrics` to, while
# VictoriaMetrics serves OTLP at
@ -1038,7 +1040,7 @@ in
}
// lib.optionalAttrs (otelCfg.protocol == "http/json") { encoding = "json"; };
}
// lib.optionalAttrs vlCfg.enable {
// lib.optionalAttrs deployCfg.victorialogs {
# `logs_endpoint`, NOT `endpoint`, for exactly the reason the
# metrics exporter above spells out — and the trap is worse
# here, because the two stores' OTLP routes differ. `endpoint`