













@@ -297,10 +297,13 @@ function histogramCreateOptions(name: string) {
297297298298async function emitAndCaptureLog(
299299event: Omit<Extract<Parameters<typeof emitDiagnosticEvent>[0], { type: "log.record" }>, "type">,
300-options: { trusted?: boolean } = {},
300+options: { captureContent?: OtelContextFlags["captureContent"]; trusted?: boolean } = {},
301301) {
302302const service = createDiagnosticsOtelService();
303-const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { logs: true });
303+const ctx = createOtelContext(OTEL_TEST_ENDPOINT, {
304+logs: true,
305+ ...(options.captureContent !== undefined ? { captureContent: options.captureContent } : {}),
306+});
304307await service.start(ctx);
305308const emit = options.trusted ? emitTrustedDiagnosticEvent : emitDiagnosticEvent;
306309emit({
@@ -1060,12 +1063,33 @@ describe("diagnostics-otel service", () => {
10601063await service.stop?.(ctx);
10611064});
106210651063-test("redacts sensitive data from log messages before export", async () => {
1066+test("omits log message bodies from OTLP logs unless broad content capture is enabled", async () => {
10641067const emitCall = await emitAndCaptureLog({
10651068level: "INFO",
1066-message: "Using API key sk-1234567890abcdef1234567890abcdef",
1069+message: "model replied OTEL-QA-OK",
10671070});
106810711072+expect(emitCall?.body).toBe("log");
1073+});
1074+1075+test("keeps granular content capture from enabling OTLP log bodies", async () => {
1076+const emitCall = await emitAndCaptureLog(
1077+{
1078+level: "INFO",
1079+message: "model replied OTEL-QA-OK",
1080+},
1081+{ captureContent: { enabled: true, inputMessages: true } },
1082+);
1083+1084+expect(emitCall?.body).toBe("log");
1085+});
1086+1087+test("redacts sensitive data from log messages before export when broad content capture is enabled", async () => {
1088+const emitCall = await emitAndCaptureLog({
1089+level: "INFO",
1090+message: "Using API key sk-1234567890abcdef1234567890abcdef",
1091+}, { captureContent: true });
1092+10691093expect(emitCall?.body).not.toContain("sk-1234567890abcdef1234567890abcdef");
10701094expect(emitCall?.body).toContain("sk-123");
10711095expect(emitCall?.body).toContain("…");
@@ -1332,6 +1356,81 @@ describe("diagnostics-otel service", () => {
13321356await service.stop?.(ctx);
13331357});
133413581359+test("drops session-shaped agent identifiers from model usage metric attributes", async () => {
1360+const service = createDiagnosticsOtelService();
1361+const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { metrics: true });
1362+await service.start(ctx);
1363+1364+emitDiagnosticEvent({
1365+type: "model.usage",
1366+agentId: "Agent:qa:otel-trace-smoke",
1367+provider: "openai",
1368+model: "gpt-5.4",
1369+usage: { input: 2 },
1370+});
1371+await flushDiagnosticEvents();
1372+1373+expect(telemetryState.counters.get("openclaw.tokens")?.add).toHaveBeenCalledWith(2, {
1374+"openclaw.channel": "unknown",
1375+"openclaw.agent": "unknown",
1376+"openclaw.provider": "openai",
1377+"openclaw.model": "gpt-5.4",
1378+"openclaw.token": "input",
1379+});
1380+expect(
1381+JSON.stringify(telemetryState.counters.get("openclaw.tokens")?.add.mock.calls),
1382+).not.toContain("Agent:qa:otel-trace-smoke");
1383+await service.stop?.(ctx);
1384+});
1385+1386+test("drops session-shaped queue lane metric attributes", async () => {
1387+const service = createDiagnosticsOtelService();
1388+const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { metrics: true });
1389+await service.start(ctx);
1390+1391+emitDiagnosticEvent({
1392+type: "queue.lane.enqueue",
1393+lane: "session:Agent:qa:otel-trace-smoke",
1394+queueSize: 2,
1395+});
1396+await flushDiagnosticEvents();
1397+1398+expect(telemetryState.counters.get("openclaw.queue.lane.enqueue")?.add).toHaveBeenCalledWith(
1399+1,
1400+{
1401+"openclaw.lane": "session",
1402+},
1403+);
1404+expect(
1405+JSON.stringify(telemetryState.counters.get("openclaw.queue.lane.enqueue")?.add.mock.calls),
1406+).not.toContain("Agent:qa:otel-trace-smoke");
1407+await service.stop?.(ctx);
1408+});
1409+1410+test("keeps only the bounded prefix from scoped queue lane metric attributes", async () => {
1411+const service = createDiagnosticsOtelService();
1412+const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { metrics: true });
1413+await service.start(ctx);
1414+1415+emitDiagnosticEvent({
1416+type: "queue.lane.enqueue",
1417+lane: "dreaming-narrative:session-main",
1418+queueSize: 2,
1419+});
1420+await flushDiagnosticEvents();
1421+1422+expect(telemetryState.counters.get("openclaw.queue.lane.enqueue")?.add).toHaveBeenCalledWith(
1423+1,
1424+{
1425+"openclaw.lane": "dreaming-narrative",
1426+},
1427+);
1428+expect(
1429+JSON.stringify(telemetryState.counters.get("openclaw.queue.lane.enqueue")?.add.mock.calls),
1430+).not.toContain("session-main");
1431+await service.stop?.(ctx);
1432+});
1433+13351434test("keeps GenAI token usage metric model attribute present when model is unavailable", async () => {
13361435const service = createDiagnosticsOtelService();
13371436const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { metrics: true });
@@ -1677,6 +1776,26 @@ describe("diagnostics-otel service", () => {
16771776await service.stop?.(ctx);
16781777});
167917781779+test("drops session-shaped queue lanes from model failover spans", async () => {
1780+const service = createDiagnosticsOtelService();
1781+const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { traces: true });
1782+await service.start(ctx);
1783+1784+emitDiagnosticEvent({
1785+type: "model.failover",
1786+lane: "session:Agent:qa:otel-trace-smoke",
1787+reason: "overloaded",
1788+fromProvider: "anthropic",
1789+fromModel: "claude-opus-4-6",
1790+});
1791+await flushDiagnosticEvents();
1792+1793+const failoverOptions = startedSpanOptions("openclaw.model.failover");
1794+expect(failoverOptions?.attributes?.["openclaw.lane"]).toBe("session");
1795+expect(JSON.stringify(failoverOptions?.attributes)).not.toContain("Agent:qa:otel-trace-smoke");
1796+await service.stop?.(ctx);
1797+});
1798+16801799test("maps model call APIs to GenAI operation names and error type", async () => {
16811800const service = createDiagnosticsOtelService();
16821801const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { traces: true, metrics: true });
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。