fix(#2172): gate CLAUDE_CODE_OTEL_DIAG_STDERR on hyperhive.otel.debug

CLAUDE_CODE_OTEL_DIAG_STDERR was always set when OTEL is enabled, making
OTEL SDK errors (e.g. 404 from a misconfigured collector endpoint) appear
in every agent's stderr unconditionally. Move it behind a new opt-in flag.

Changes:
- nix/modules/hive-c0re.nix: add services.hyperhive.otel.debug (bool,
  default false); wire to HYPERHIVE_OTEL_DEBUG env on hive-c0re unit.
- hive-c0re/src/meta.rs: add debug field to OtelConfig; read
  HYPERHIVE_OTEL_DEBUG; emit hyperhive.otel.debug = true when set.
- nix/templates/harness-base.nix: add hyperhive.otel.debug internal
  option; move CLAUDE_CODE_OTEL_DIAG_STDERR out of otelSettingsEnv into
  a debug-gated lib.optionalAttrs block.

Default behaviour: OTEL exports silently (no stderr noise). Operators
troubleshooting collector connectivity set services.hyperhive.otel.debug
= true to re-enable the diagnostic output.
This commit is contained in:
atlas 2026-07-03 22:10:22 +02:00 committed by mara
commit cb0a66147a
3 changed files with 42 additions and 3 deletions

View file

@ -666,6 +666,9 @@ struct OtelConfig {
extra_resource_attributes: Option<String>,
headers_credential: Option<String>,
metric_interval_ms: Option<u64>,
/// `HYPERHIVE_OTEL_DEBUG=1` → `hyperhive.otel.debug = true` →
/// `CLAUDE_CODE_OTEL_DIAG_STDERR=1` in every agent's env.
debug: bool,
}
/// Read the hive-wide OTEL config from env, or `None` when OTEL is off.
@ -692,12 +695,16 @@ fn otel_config() -> Option<OtelConfig> {
.ok()
.and_then(|v| v.parse::<u64>().ok())
.filter(|v| *v > 0);
let debug = std::env::var("HYPERHIVE_OTEL_DEBUG")
.ok()
.is_some_and(|v| v == "1");
Some(OtelConfig {
endpoint,
protocol,
extra_resource_attributes,
headers_credential,
metric_interval_ms,
debug,
})
}
@ -982,6 +989,9 @@ where
// parsed u64, so it can't inject anything into the rendered nix.
let _ = writeln!(out, " hyperhive.otel.metricIntervalMs = {ms};");
}
if otel.debug {
out.push_str(" hyperhive.otel.debug = true;\n");
}
}
out.push_str(
r#" # The harness service inside the container runs as a