






















@@ -1050,6 +1050,56 @@ describe("diagnostics-otel service", () => {
10501050await service.stop?.(ctx);
10511051});
105210521053+test("exports tool loop diagnostics without loop messages or session identifiers", async () => {
1054+const service = createDiagnosticsOtelService();
1055+const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { traces: true, metrics: true });
1056+await service.start(ctx);
1057+1058+emitDiagnosticEvent({
1059+type: "tool.loop",
1060+sessionKey: "session-key",
1061+sessionId: "session-id",
1062+toolName: "process",
1063+level: "critical",
1064+action: "block",
1065+detector: "known_poll_no_progress",
1066+count: 20,
1067+message: "CRITICAL: repeated secret-bearing tool output",
1068+pairedToolName: "read",
1069+});
1070+await flushDiagnosticEvents();
1071+1072+expect(telemetryState.counters.get("openclaw.tool.loop")?.add).toHaveBeenCalledWith(1, {
1073+"openclaw.toolName": "process",
1074+"openclaw.loop.level": "critical",
1075+"openclaw.loop.action": "block",
1076+"openclaw.loop.detector": "known_poll_no_progress",
1077+"openclaw.loop.count": 20,
1078+"openclaw.loop.paired_tool": "read",
1079+});
1080+const loopSpanCall = telemetryState.tracer.startSpan.mock.calls.find(
1081+(call) => call[0] === "openclaw.tool.loop",
1082+);
1083+expect(loopSpanCall?.[1]).toMatchObject({
1084+attributes: {
1085+"openclaw.toolName": "process",
1086+"openclaw.loop.level": "critical",
1087+"openclaw.loop.action": "block",
1088+"openclaw.loop.detector": "known_poll_no_progress",
1089+"openclaw.loop.count": 20,
1090+"openclaw.loop.paired_tool": "read",
1091+},
1092+});
1093+const loopSpan = telemetryState.spans.find((span) => span.name === "openclaw.tool.loop");
1094+expect(loopSpan?.setStatus).toHaveBeenCalledWith({
1095+code: 2,
1096+message: "known_poll_no_progress:block",
1097+});
1098+expect(JSON.stringify(loopSpanCall)).not.toContain("session-key");
1099+expect(JSON.stringify(loopSpanCall)).not.toContain("secret-bearing");
1100+await service.stop?.(ctx);
1101+});
1102+10531103test("parents trusted diagnostic lifecycle spans from explicit parent ids", async () => {
10541104const service = createDiagnosticsOtelService();
10551105const ctx = createOtelContext(OTEL_TEST_ENDPOINT, { traces: true, metrics: true });
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。