From a9fb5b4e3fcb9f2848df84d8c8239cf92abc86fe Mon Sep 17 00:00:00 2001 From: Wynne668 Date: Sun, 19 Jul 2026 04:38:44 +0800 Subject: [PATCH] fix(diagnostics-otel): ignore blank protocol env overrides (#110674) --- .../diagnostics-otel/src/service.test.ts | 45 +++++++++++++++++++ extensions/diagnostics-otel/src/service.ts | 3 +- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/extensions/diagnostics-otel/src/service.test.ts b/extensions/diagnostics-otel/src/service.test.ts index 99ca3073116c..a389cb1ffe43 100644 --- a/extensions/diagnostics-otel/src/service.test.ts +++ b/extensions/diagnostics-otel/src/service.test.ts @@ -210,6 +210,7 @@ const PROTO_KEY = "__proto__"; const MAX_TEST_OTEL_CONTENT_ATTRIBUTE_CHARS = 128 * 1024; const OTEL_TRUNCATED_SUFFIX_MAX_CHARS = 20; const ORIGINAL_OPENCLAW_OTEL_PRELOADED = process.env.OPENCLAW_OTEL_PRELOADED; +const ORIGINAL_OTEL_EXPORTER_OTLP_PROTOCOL = process.env.OTEL_EXPORTER_OTLP_PROTOCOL; const ORIGINAL_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT; const ORIGINAL_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT; @@ -563,6 +564,7 @@ describe("diagnostics-otel service", () => { beforeEach(() => { resetDiagnosticEventsForTest(); delete process.env.OPENCLAW_OTEL_PRELOADED; + delete process.env.OTEL_EXPORTER_OTLP_PROTOCOL; delete process.env.OTEL_SEMCONV_STABILITY_OPT_IN; telemetryState.counters.clear(); telemetryState.histograms.clear(); @@ -598,6 +600,11 @@ describe("diagnostics-otel service", () => { } else { process.env.OPENCLAW_OTEL_PRELOADED = ORIGINAL_OPENCLAW_OTEL_PRELOADED; } + if (ORIGINAL_OTEL_EXPORTER_OTLP_PROTOCOL === undefined) { + delete process.env.OTEL_EXPORTER_OTLP_PROTOCOL; + } else { + process.env.OTEL_EXPORTER_OTLP_PROTOCOL = ORIGINAL_OTEL_EXPORTER_OTLP_PROTOCOL; + } if (ORIGINAL_OTEL_SEMCONV_STABILITY_OPT_IN === undefined) { delete process.env.OTEL_SEMCONV_STABILITY_OPT_IN; } else { @@ -1224,6 +1231,44 @@ describe("diagnostics-otel service", () => { } }); + test("ignores blank OTLP protocol env overrides", async () => { + process.env.OTEL_EXPORTER_OTLP_PROTOCOL = " "; + const service = createDiagnosticsOtelService(); + const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { traces: true, metrics: true }); + if (ctx.config.diagnostics?.otel) { + delete ctx.config.diagnostics.otel.protocol; + } + + try { + await service.start(ctx); + + expect(traceExporterCtor).toHaveBeenCalledOnce(); + expect(metricExporterCtor).toHaveBeenCalledOnce(); + expect(ctx.logger.warn).not.toHaveBeenCalledWith( + "diagnostics-otel: unsupported protocol ", + ); + } finally { + await service.stop?.(ctx); + } + }); + + test("preserves nonblank OTLP protocol env overrides", async () => { + process.env.OTEL_EXPORTER_OTLP_PROTOCOL = " http/protobuf "; + const service = createDiagnosticsOtelService(); + const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { traces: true, metrics: true }); + if (ctx.config.diagnostics?.otel) { + delete ctx.config.diagnostics.otel.protocol; + } + + await service.start(ctx); + + expect(traceExporterCtor).not.toHaveBeenCalled(); + expect(metricExporterCtor).not.toHaveBeenCalled(); + expect(ctx.logger.warn).toHaveBeenCalledWith( + "diagnostics-otel: unsupported protocol http/protobuf ", + ); + }); + test("exports trusted security events as stdout JSONL logs", async () => { const service = createDiagnosticsOtelService(); const ctx = createOtelContext("", { logs: true, logsExporter: "stdout" }); diff --git a/extensions/diagnostics-otel/src/service.ts b/extensions/diagnostics-otel/src/service.ts index 6f318fe407af..9363fb124e65 100644 --- a/extensions/diagnostics-otel/src/service.ts +++ b/extensions/diagnostics-otel/src/service.ts @@ -129,7 +129,8 @@ export function createDiagnosticsOtelService(): OpenClawPluginService { return; } - const protocol = otel.protocol ?? process.env.OTEL_EXPORTER_OTLP_PROTOCOL ?? "http/protobuf"; + const envProtocol = process.env.OTEL_EXPORTER_OTLP_PROTOCOL; + const protocol = otel.protocol ?? (envProtocol?.trim() ? envProtocol : "http/protobuf"); if (otlpSignals.length > 0 && protocol !== "http/protobuf") { emitForSignals(otlpSignals, { exporter: "diagnostics-otel",