From 84f183b7ad072f74d5aa7a39709c8604b839ef8e Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 25 Apr 2026 12:42:00 -0700 Subject: [PATCH] test(diagnostics-otel): cover trace self-parent guard --- .../diagnostics-otel/src/service.test.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/extensions/diagnostics-otel/src/service.test.ts b/extensions/diagnostics-otel/src/service.test.ts index da854175d2a..5f7a26fe7b6 100644 --- a/extensions/diagnostics-otel/src/service.test.ts +++ b/extensions/diagnostics-otel/src/service.test.ts @@ -1449,6 +1449,50 @@ describe("diagnostics-otel service", () => { await service.stop?.(ctx); }); + test("does not self-parent trusted diagnostic lifecycle spans without parent ids", async () => { + const service = createDiagnosticsOtelService(); + const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { traces: true, metrics: true }); + await service.start(ctx); + + emitTrustedDiagnosticEvent({ + type: "run.completed", + runId: "run-1", + provider: "openai", + model: "gpt-5.4", + outcome: "completed", + durationMs: 100, + trace: { + traceId: TRACE_ID, + spanId: CHILD_SPAN_ID, + traceFlags: "01", + }, + }); + emitTrustedDiagnosticEvent({ + type: "model.call.completed", + runId: "run-1", + callId: "call-1", + provider: "openai", + model: "gpt-5.4", + durationMs: 80, + trace: { + traceId: TRACE_ID, + spanId: GRANDCHILD_SPAN_ID, + traceFlags: "01", + }, + }); + await flushDiagnosticEvents(); + + expect(telemetryState.tracer.setSpanContext).not.toHaveBeenCalled(); + const parentBySpanName = Object.fromEntries( + telemetryState.tracer.startSpan.mock.calls.map((call) => [call[0], call[2]]), + ); + expect(parentBySpanName).toMatchObject({ + "openclaw.run": undefined, + "openclaw.model.call": undefined, + }); + await service.stop?.(ctx); + }); + test("does not parent untrusted diagnostic lifecycle spans from injected trace ids", async () => { const service = createDiagnosticsOtelService(); const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { traces: true, metrics: true });