diff --git a/test/e2e/qa-lab/runtime/qa-otel-smoke-runtime.ts b/test/e2e/qa-lab/runtime/qa-otel-smoke-runtime.ts index 1210e8a49dc..94462bf9691 100644 --- a/test/e2e/qa-lab/runtime/qa-otel-smoke-runtime.ts +++ b/test/e2e/qa-lab/runtime/qa-otel-smoke-runtime.ts @@ -159,6 +159,25 @@ const MAX_STDOUT_DIAGNOSTIC_LINE_BYTES = readPositiveIntegerEnv( 512 * 1024, ); const GATEWAY_STDOUT_ARTIFACT_READ_CHUNK_BYTES = 64 * 1024; +const QA_OTEL_ENV_TO_CLEAR = [ + "OTEL_SDK_DISABLED", + "OTEL_TRACES_EXPORTER", + "OTEL_METRICS_EXPORTER", + "OTEL_LOGS_EXPORTER", + "OTEL_EXPORTER_OTLP_ENDPOINT", + "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", + "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT", + "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT", + "OTEL_EXPORTER_OTLP_PROTOCOL", + "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", + "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL", + "OTEL_EXPORTER_OTLP_LOGS_PROTOCOL", + "OTEL_EXPORTER_OTLP_HEADERS", + "OTEL_EXPORTER_OTLP_TRACES_HEADERS", + "OTEL_EXPORTER_OTLP_METRICS_HEADERS", + "OTEL_EXPORTER_OTLP_LOGS_HEADERS", + "OTEL_RESOURCE_ATTRIBUTES", +] as const; function readPositiveIntegerEnv( name: string, @@ -1426,9 +1445,9 @@ function relayParentSignalsToChild(child: ChildProcess): () => void { function buildQaEnv(port: number): NodeJS.ProcessEnv { const env = { ...process.env }; - delete env.OTEL_SDK_DISABLED; - delete env.OTEL_TRACES_EXPORTER; - delete env.OTEL_EXPORTER_OTLP_ENDPOINT; + for (const key of QA_OTEL_ENV_TO_CLEAR) { + delete env[key]; + } env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = `http://127.0.0.1:${port}/v1/traces`; env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = `http://127.0.0.1:${port}/v1/metrics`; env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = `http://127.0.0.1:${port}/v1/logs`; @@ -1910,6 +1929,7 @@ export const testing = { appendGatewayStdoutArtifactLogs, appendCapturedBodyText, assertSmoke, + buildQaEnv, createBoundedTextAccumulator, createStdoutDiagnosticLogCapture, decodeRequestBody, diff --git a/test/e2e/qa-lab/runtime/qa-otel-smoke.e2e.test.ts b/test/e2e/qa-lab/runtime/qa-otel-smoke.e2e.test.ts index f3f26ae9881..085092133ba 100644 --- a/test/e2e/qa-lab/runtime/qa-otel-smoke.e2e.test.ts +++ b/test/e2e/qa-lab/runtime/qa-otel-smoke.e2e.test.ts @@ -7,9 +7,14 @@ import os from "node:os"; import path from "node:path"; import { setTimeout as delay } from "node:timers/promises"; import { gzipSync } from "node:zlib"; -import { beforeAll, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; import { testing } from "./qa-otel-smoke-runtime.js"; +afterEach(() => { + vi.unstubAllEnvs(); + vi.restoreAllMocks(); +}); + describe("qa-otel-smoke receiver bounds", () => { let configuredBodyLimitLoad: ReturnType; @@ -171,6 +176,40 @@ describe("qa-otel-smoke receiver bounds", () => { expect(configuredBodyLimitLoad.stderr).not.toContain("ReferenceError"); }); + it("scrubs inherited OpenTelemetry exporter env before running the QA suite", () => { + vi.stubEnv("OTEL_SDK_DISABLED", "true"); + vi.stubEnv("OTEL_TRACES_EXPORTER", "none"); + vi.stubEnv("OTEL_METRICS_EXPORTER", "none"); + vi.stubEnv("OTEL_LOGS_EXPORTER", "none"); + vi.stubEnv("OTEL_EXPORTER_OTLP_ENDPOINT", "http://collector.example.test:4318"); + vi.stubEnv("OTEL_EXPORTER_OTLP_PROTOCOL", "grpc"); + vi.stubEnv("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "grpc"); + vi.stubEnv("OTEL_EXPORTER_OTLP_METRICS_PROTOCOL", "grpc"); + vi.stubEnv("OTEL_EXPORTER_OTLP_LOGS_PROTOCOL", "grpc"); + vi.stubEnv("OTEL_EXPORTER_OTLP_HEADERS", "authorization=secret"); + vi.stubEnv("OTEL_EXPORTER_OTLP_LOGS_HEADERS", "authorization=logs-secret"); + vi.stubEnv("OTEL_RESOURCE_ATTRIBUTES", "deployment.environment=developer-laptop"); + + const env = testing.buildQaEnv(4318); + + expect(env.OTEL_SDK_DISABLED).toBeUndefined(); + expect(env.OTEL_TRACES_EXPORTER).toBeUndefined(); + expect(env.OTEL_METRICS_EXPORTER).toBeUndefined(); + expect(env.OTEL_LOGS_EXPORTER).toBeUndefined(); + expect(env.OTEL_EXPORTER_OTLP_ENDPOINT).toBeUndefined(); + expect(env.OTEL_EXPORTER_OTLP_PROTOCOL).toBeUndefined(); + expect(env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL).toBeUndefined(); + expect(env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL).toBeUndefined(); + expect(env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL).toBeUndefined(); + expect(env.OTEL_EXPORTER_OTLP_HEADERS).toBeUndefined(); + expect(env.OTEL_EXPORTER_OTLP_LOGS_HEADERS).toBeUndefined(); + expect(env.OTEL_RESOURCE_ATTRIBUTES).toBeUndefined(); + expect(env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT).toBe("http://127.0.0.1:4318/v1/traces"); + expect(env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT).toBe("http://127.0.0.1:4318/v1/metrics"); + expect(env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT).toBe("http://127.0.0.1:4318/v1/logs"); + expect(env.OTEL_SERVICE_NAME).toBe("openclaw-qa-lab-otel-smoke"); + }); + it("rejects identity OTLP bodies above the decoded byte ceiling", () => { expect(() => testing.decodeRequestBody(Buffer.alloc(65), undefined, 64)).toThrow( "OTLP request body exceeded 64 bytes: 65 bytes",