swarm-otel: the operator chooses which signals go upstream
Adds services.hyperhive.otel.upstreamSignals, a list of "metrics" and/or "logs" naming the signals the swarm collector sends to otel.endpoint. The swarm's own stores always receive everything. The upstream exporter is only defined when at least one signal uses it, since otelcol refuses an exporter no pipeline references. On deploy: nothing changes until the option is set; the default is [ "metrics" "logs" ], today's behaviour. To stop the 404 flood from an upstream that has no /v1/logs, set services.hyperhive.otel.upstreamSignals = [ "metrics" ].
This commit is contained in:
parent
9a65643769
commit
2977dc91d1
4 changed files with 114 additions and 20 deletions
|
|
@ -88,6 +88,32 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
upstreamSignals = lib.mkOption {
|
||||
type = lib.types.listOf (
|
||||
lib.types.enum [
|
||||
"metrics"
|
||||
"logs"
|
||||
]
|
||||
);
|
||||
default = [
|
||||
"metrics"
|
||||
"logs"
|
||||
];
|
||||
example = [ "metrics" ];
|
||||
description = ''
|
||||
Which signals the swarm's collector sends to
|
||||
{option}`services.hyperhive.otel.endpoint`. The swarm's own metrics
|
||||
and log stores always receive everything, whatever this lists.
|
||||
|
||||
Use it when the upstream does not accept a signal, for example one
|
||||
that answers 404 on `/v1/logs`: list only `"metrics"` and the logs
|
||||
pipelines stop exporting upstream. An empty list defines no upstream
|
||||
exporter at all. No pipeline exports traces, so they have no entry.
|
||||
|
||||
Has no effect while {option}`services.hyperhive.otel.endpoint` is empty.
|
||||
'';
|
||||
};
|
||||
|
||||
protocol = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"http/protobuf"
|
||||
|
|
|
|||
|
|
@ -273,10 +273,17 @@ let
|
|||
storeSecretPath = "secret/swarm/services/${cfg.clientId}/oidc/client";
|
||||
|
||||
# The operator-configured upstream, named once: the same exporter carries
|
||||
# every signal, so metrics and logs both reach it without a second
|
||||
# definition.
|
||||
# every signal listed in `upstreamSignals`, so metrics and logs both reach
|
||||
# it without a second definition.
|
||||
upstreamExporterName = if otelCfg.protocol == "grpc" then "otlp" else "otlphttp";
|
||||
upstreamExporters = lib.optional (otelCfg.endpoint != "") upstreamExporterName;
|
||||
upstreamFor =
|
||||
signal:
|
||||
lib.optional (
|
||||
otelCfg.endpoint != "" && builtins.elem signal otelCfg.upstreamSignals
|
||||
) upstreamExporterName;
|
||||
# The collector refuses an exporter that no pipeline uses, so the exporter
|
||||
# is only defined when at least one signal goes to it.
|
||||
haveUpstream = upstreamFor "metrics" ++ upstreamFor "logs" != [ ];
|
||||
|
||||
# One list, read by every pipeline: the per-hive pipelines fan out to
|
||||
# exactly the same destinations as the single pipeline they replace.
|
||||
|
|
@ -285,10 +292,10 @@ let
|
|||
# ⚠️ Unconditional: `deploy.victoriametrics.enable` says "this host RUNS the
|
||||
# store", and a swarm has one either way. Gating on it left a collector
|
||||
# elsewhere with no exporter at all, dropping everything silently.
|
||||
exporterNames = upstreamExporters ++ [ "otlphttp/victoriametrics" ];
|
||||
exporterNames = upstreamFor "metrics" ++ [ "otlphttp/victoriametrics" ];
|
||||
|
||||
# Same fan-out for logs, unconditional for the same reason.
|
||||
logExporterNames = upstreamExporters ++ [ "otlphttp/victorialogs" ];
|
||||
logExporterNames = upstreamFor "logs" ++ [ "otlphttp/victorialogs" ];
|
||||
|
||||
# An empty exporter list is not a quiet no-op — the collector rejects it.
|
||||
# Now always satisfied, as a consequence of the log store always existing.
|
||||
|
|
@ -1068,7 +1075,7 @@ in
|
|||
auth.authenticator = pushAuthenticator "victoriametrics";
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs (otelCfg.endpoint != "") {
|
||||
// lib.optionalAttrs haveUpstream {
|
||||
${if otelCfg.protocol == "grpc" then "otlp" else "otlphttp"} = {
|
||||
endpoint = otelCfg.endpoint;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue