From cb0a66147a5f27891f575b3a147e03be356407d2 Mon Sep 17 00:00:00 2001 From: atlas Date: Fri, 3 Jul 2026 22:10:22 +0200 Subject: [PATCH] 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. --- hive-c0re/src/meta.rs | 10 ++++++++++ nix/modules/hive-c0re.nix | 15 +++++++++++++++ nix/templates/harness-base.nix | 20 +++++++++++++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/hive-c0re/src/meta.rs b/hive-c0re/src/meta.rs index 8f6b055d..ea79005b 100644 --- a/hive-c0re/src/meta.rs +++ b/hive-c0re/src/meta.rs @@ -666,6 +666,9 @@ struct OtelConfig { extra_resource_attributes: Option, headers_credential: Option, metric_interval_ms: Option, + /// `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 { .ok() .and_then(|v| v.parse::().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 diff --git a/nix/modules/hive-c0re.nix b/nix/modules/hive-c0re.nix index 04edb769..cc27dad6 100644 --- a/nix/modules/hive-c0re.nix +++ b/nix/modules/hive-c0re.nix @@ -279,6 +279,18 @@ in ''; }; + debug = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Emit OTEL SDK diagnostic messages to every agent's stderr by + setting `CLAUDE_CODE_OTEL_DIAG_STDERR=1`. Useful when + troubleshooting collector connectivity or endpoint config; + leave off in normal operation to avoid noise in agent logs. + Only meaningful when `enable` is true. + ''; + }; + metricIntervalMs = lib.mkOption { type = lib.types.nullOr lib.types.ints.positive; default = null; @@ -923,6 +935,9 @@ in // lib.optionalAttrs (otel.metricIntervalMs != null) { HYPERHIVE_OTEL_METRIC_INTERVAL_MS = toString otel.metricIntervalMs; } + // lib.optionalAttrs otel.debug { + HYPERHIVE_OTEL_DEBUG = "1"; + } ) // { # In-cluster forge URL — the gateway vhost (`forge.`), which diff --git a/nix/templates/harness-base.nix b/nix/templates/harness-base.nix index 39ac5684..f75c3343 100644 --- a/nix/templates/harness-base.nix +++ b/nix/templates/harness-base.nix @@ -67,8 +67,6 @@ let CLAUDE_CODE_ENABLE_TELEMETRY = "1"; # Attach feedback-survey data to the OTEL pipeline. CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL = "1"; - # Emit OTEL SDK diagnostics to stderr for easier log capture. - CLAUDE_CODE_OTEL_DIAG_STDERR = "1"; OTEL_METRICS_EXPORTER = "otlp"; OTEL_LOGS_EXPORTER = "otlp"; OTEL_TRACES_EXPORTER = "otlp"; @@ -357,6 +355,16 @@ in default. Host-driven via `services.hyperhive.otel.metricIntervalMs`. ''; }; + + debug = lib.mkOption { + type = lib.types.bool; + default = false; + internal = true; + description = '' + Emit OTEL SDK diagnostics to stderr (`CLAUDE_CODE_OTEL_DIAG_STDERR=1`). + Host-driven via `services.hyperhive.otel.debug`. + ''; + }; }; options.hyperhive.allowedRecipients = lib.mkOption { @@ -1222,7 +1230,13 @@ in # run — `baseClaudeEnv` contains per-agent values (e.g. # CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX) that can't live in the # static store asset. - allEnv = baseClaudeEnv // lib.optionalAttrs otelCfg.enable otelSettingsEnv; + allEnv = + baseClaudeEnv + // lib.optionalAttrs otelCfg.enable otelSettingsEnv + // lib.optionalAttrs (otelCfg.enable && otelCfg.debug) { + # SDK diagnostics — noisy; only on when services.hyperhive.otel.debug = true. + CLAUDE_CODE_OTEL_DIAG_STDERR = "1"; + }; in pkgs.runCommand "managed-settings.json" { nativeBuildInputs = [ pkgs.jq ]; } '' jq --argjson env ${lib.escapeShellArg (builtins.toJSON allEnv)} \