



























@@ -296,6 +296,7 @@ describe("diagnostics-otel service", () => {
296296type: "webhook.processed",
297297channel: "telegram",
298298updateType: "telegram-post",
299+chatId: "chat-should-not-export",
299300durationMs: 120,
300301});
301302emitDiagnosticEvent({
@@ -307,7 +308,10 @@ describe("diagnostics-otel service", () => {
307308emitDiagnosticEvent({
308309type: "message.processed",
309310channel: "telegram",
311+chatId: "chat-should-not-export",
312+messageId: "message-should-not-export",
310313outcome: "completed",
314+reason: "progress draft / message tool 123",
311315durationMs: 55,
312316});
313317emitDiagnosticEvent({
@@ -348,6 +352,33 @@ describe("diagnostics-otel service", () => {
348352expect(spanNames).toContain("openclaw.webhook.processed");
349353expect(spanNames).toContain("openclaw.message.processed");
350354expect(spanNames).toContain("openclaw.session.stuck");
355+const webhookSpanCall = telemetryState.tracer.startSpan.mock.calls.find(
356+(call) => call[0] === "openclaw.webhook.processed",
357+);
358+expect(webhookSpanCall?.[1]).toEqual({
359+attributes: expect.not.objectContaining({
360+"openclaw.chatId": expect.anything(),
361+}),
362+startTime: expect.any(Number),
363+});
364+const messageSpanCall = telemetryState.tracer.startSpan.mock.calls.find(
365+(call) => call[0] === "openclaw.message.processed",
366+);
367+expect(messageSpanCall?.[1]).toEqual({
368+attributes: expect.objectContaining({
369+"openclaw.channel": "telegram",
370+"openclaw.outcome": "completed",
371+"openclaw.reason": "unknown",
372+}),
373+startTime: expect.any(Number),
374+});
375+expect(messageSpanCall?.[1]).toEqual({
376+attributes: expect.not.objectContaining({
377+"openclaw.chatId": expect.anything(),
378+"openclaw.messageId": expect.anything(),
379+}),
380+startTime: expect.any(Number),
381+});
351382352383emitDiagnosticEvent({
353384type: "log.record",
@@ -2387,6 +2418,7 @@ describe("diagnostics-otel service", () => {
23872418for (const call of deliverySpanCalls) {
23882419expect(call[1]).toEqual({
23892420attributes: expect.not.objectContaining({
2421+"openclaw.chatId": expect.anything(),
23902422"openclaw.sessionKey": expect.anything(),
23912423"openclaw.messageId": expect.anything(),
23922424"openclaw.conversationId": expect.anything(),
@@ -2406,6 +2438,46 @@ describe("diagnostics-otel service", () => {
24062438await service.stop?.(ctx);
24072439});
240824402441+test("bounds unsafe message delivery attributes before export", async () => {
2442+const service = createDiagnosticsOtelService();
2443+const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { traces: true, metrics: true });
2444+await service.start(ctx);
2445+2446+emitDiagnosticEvent({
2447+type: "message.delivery.completed",
2448+channel: "discord/custom",
2449+deliveryKind: "progress draft" as never,
2450+durationMs: 20,
2451+resultCount: 1,
2452+sessionKey: "session-secret",
2453+});
2454+await flushDiagnosticEvents();
2455+2456+expect(
2457+telemetryState.histograms.get("openclaw.message.delivery.duration_ms")?.record,
2458+).toHaveBeenCalledWith(
2459+20,
2460+expect.objectContaining({
2461+"openclaw.channel": "unknown",
2462+"openclaw.delivery.kind": "other",
2463+"openclaw.outcome": "completed",
2464+}),
2465+);
2466+const deliverySpanCall = telemetryState.tracer.startSpan.mock.calls.find(
2467+(call) => call[0] === "openclaw.message.delivery",
2468+);
2469+expect(deliverySpanCall?.[1]).toMatchObject({
2470+attributes: {
2471+"openclaw.channel": "unknown",
2472+"openclaw.delivery.kind": "other",
2473+"openclaw.outcome": "completed",
2474+"openclaw.delivery.result_count": 1,
2475+},
2476+startTime: expect.any(Number),
2477+});
2478+await service.stop?.(ctx);
2479+});
2480+24092481test("does not export model or tool content unless capture is explicitly enabled", async () => {
24102482const service = createDiagnosticsOtelService();
24112483const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { traces: true, metrics: true });
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。