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:
parent
2c5d9ed336
commit
cb0a66147a
3 changed files with 42 additions and 3 deletions
|
|
@ -666,6 +666,9 @@ struct OtelConfig {
|
||||||
extra_resource_attributes: Option<String>,
|
extra_resource_attributes: Option<String>,
|
||||||
headers_credential: Option<String>,
|
headers_credential: Option<String>,
|
||||||
metric_interval_ms: Option<u64>,
|
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.
|
/// Read the hive-wide OTEL config from env, or `None` when OTEL is off.
|
||||||
|
|
@ -692,12 +695,16 @@ fn otel_config() -> Option<OtelConfig> {
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|v| v.parse::<u64>().ok())
|
.and_then(|v| v.parse::<u64>().ok())
|
||||||
.filter(|v| *v > 0);
|
.filter(|v| *v > 0);
|
||||||
|
let debug = std::env::var("HYPERHIVE_OTEL_DEBUG")
|
||||||
|
.ok()
|
||||||
|
.is_some_and(|v| v == "1");
|
||||||
Some(OtelConfig {
|
Some(OtelConfig {
|
||||||
endpoint,
|
endpoint,
|
||||||
protocol,
|
protocol,
|
||||||
extra_resource_attributes,
|
extra_resource_attributes,
|
||||||
headers_credential,
|
headers_credential,
|
||||||
metric_interval_ms,
|
metric_interval_ms,
|
||||||
|
debug,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -982,6 +989,9 @@ where
|
||||||
// parsed u64, so it can't inject anything into the rendered nix.
|
// parsed u64, so it can't inject anything into the rendered nix.
|
||||||
let _ = writeln!(out, " hyperhive.otel.metricIntervalMs = {ms};");
|
let _ = writeln!(out, " hyperhive.otel.metricIntervalMs = {ms};");
|
||||||
}
|
}
|
||||||
|
if otel.debug {
|
||||||
|
out.push_str(" hyperhive.otel.debug = true;\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.push_str(
|
out.push_str(
|
||||||
r#" # The harness service inside the container runs as a
|
r#" # The harness service inside the container runs as a
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
metricIntervalMs = lib.mkOption {
|
||||||
type = lib.types.nullOr lib.types.ints.positive;
|
type = lib.types.nullOr lib.types.ints.positive;
|
||||||
default = null;
|
default = null;
|
||||||
|
|
@ -923,6 +935,9 @@ in
|
||||||
// lib.optionalAttrs (otel.metricIntervalMs != null) {
|
// lib.optionalAttrs (otel.metricIntervalMs != null) {
|
||||||
HYPERHIVE_OTEL_METRIC_INTERVAL_MS = toString otel.metricIntervalMs;
|
HYPERHIVE_OTEL_METRIC_INTERVAL_MS = toString otel.metricIntervalMs;
|
||||||
}
|
}
|
||||||
|
// lib.optionalAttrs otel.debug {
|
||||||
|
HYPERHIVE_OTEL_DEBUG = "1";
|
||||||
|
}
|
||||||
)
|
)
|
||||||
// {
|
// {
|
||||||
# In-cluster forge URL — the gateway vhost (`forge.<domain>`), which
|
# In-cluster forge URL — the gateway vhost (`forge.<domain>`), which
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,6 @@ let
|
||||||
CLAUDE_CODE_ENABLE_TELEMETRY = "1";
|
CLAUDE_CODE_ENABLE_TELEMETRY = "1";
|
||||||
# Attach feedback-survey data to the OTEL pipeline.
|
# Attach feedback-survey data to the OTEL pipeline.
|
||||||
CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL = "1";
|
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_METRICS_EXPORTER = "otlp";
|
||||||
OTEL_LOGS_EXPORTER = "otlp";
|
OTEL_LOGS_EXPORTER = "otlp";
|
||||||
OTEL_TRACES_EXPORTER = "otlp";
|
OTEL_TRACES_EXPORTER = "otlp";
|
||||||
|
|
@ -357,6 +355,16 @@ in
|
||||||
default. Host-driven via `services.hyperhive.otel.metricIntervalMs`.
|
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 {
|
options.hyperhive.allowedRecipients = lib.mkOption {
|
||||||
|
|
@ -1222,7 +1230,13 @@ in
|
||||||
# run — `baseClaudeEnv` contains per-agent values (e.g.
|
# run — `baseClaudeEnv` contains per-agent values (e.g.
|
||||||
# CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX) that can't live in the
|
# CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX) that can't live in the
|
||||||
# static store asset.
|
# 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
|
in
|
||||||
pkgs.runCommand "managed-settings.json" { nativeBuildInputs = [ pkgs.jq ]; } ''
|
pkgs.runCommand "managed-settings.json" { nativeBuildInputs = [ pkgs.jq ]; } ''
|
||||||
jq --argjson env ${lib.escapeShellArg (builtins.toJSON allEnv)} \
|
jq --argjson env ${lib.escapeShellArg (builtins.toJSON allEnv)} \
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue