



























@@ -205,9 +205,15 @@ function createTraceOnlyContext(endpoint: string): OpenClawPluginServiceContext
205205return createOtelContext(endpoint, { traces: true });
206206}
207207208+function startedSpanCall(name: string) {
209+const calls = telemetryState.tracer.startSpan.mock.calls as unknown as Array<
210+[string, { attributes?: Record<string, unknown>; startTime?: unknown }?, unknown?]
211+>;
212+return calls.find(([spanName]) => spanName === name);
213+}
214+208215function startedSpanOptions(name: string) {
209-const call = telemetryState.tracer.startSpan.mock.calls.find(([spanName]) => spanName === name);
210-return call?.[1] as { attributes?: Record<string, unknown>; startTime?: unknown } | undefined;
216+return startedSpanCall(name)?.[1];
211217}
212218213219function lastHistogramRecord(name: string) {
@@ -1263,109 +1269,68 @@ describe("diagnostics-otel service", () => {
12631269await flushDiagnosticEvents();
1264127012651271const spanNames = telemetryState.tracer.startSpan.mock.calls.map((call) => call[0]);
1266-expect(spanNames).toEqual(
1267-expect.arrayContaining([
1268-"openclaw.run",
1269-"openclaw.model.call",
1270-"openclaw.harness.run",
1271-"openclaw.tool.execution",
1272-]),
1273-);
1274-1275-const runCall = telemetryState.tracer.startSpan.mock.calls.find(
1276-(call) => call[0] === "openclaw.run",
1277-);
1278-expect(runCall?.[1]).toMatchObject({
1279-attributes: {
1280-"openclaw.outcome": "completed",
1281-"openclaw.provider": "openai",
1282-"openclaw.model": "gpt-5.4",
1283-"openclaw.channel": "webchat",
1284-},
1285-startTime: expect.any(Number),
1286-});
1287-expect(runCall?.[1]).toEqual({
1288-attributes: expect.not.objectContaining({
1289-"gen_ai.system": expect.anything(),
1290-"gen_ai.request.model": expect.anything(),
1291-"openclaw.runId": expect.anything(),
1292-"openclaw.sessionKey": expect.anything(),
1293-"openclaw.traceId": expect.anything(),
1294-}),
1295-startTime: expect.any(Number),
1296-});
1297-1298-const modelCall = telemetryState.tracer.startSpan.mock.calls.find(
1299-(call) => call[0] === "openclaw.model.call",
1300-);
1301-expect(modelCall?.[1]).toMatchObject({
1302-attributes: {
1303-"gen_ai.system": "openai",
1304-"gen_ai.request.model": "gpt-5.4",
1305-"gen_ai.operation.name": "text_completion",
1306-},
1307-});
1308-expect(modelCall?.[1]).toEqual({
1309-attributes: expect.not.objectContaining({
1310-"gen_ai.provider.name": expect.anything(),
1311-"openclaw.callId": expect.anything(),
1312-"openclaw.runId": expect.anything(),
1313-"openclaw.sessionKey": expect.anything(),
1314-}),
1315-startTime: expect.any(Number),
1316-});
1272+expect(spanNames).toContain("openclaw.run");
1273+expect(spanNames).toContain("openclaw.model.call");
1274+expect(spanNames).toContain("openclaw.harness.run");
1275+expect(spanNames).toContain("openclaw.tool.execution");
1276+1277+const runOptions = startedSpanOptions("openclaw.run");
1278+expect(runOptions?.attributes?.["openclaw.outcome"]).toBe("completed");
1279+expect(runOptions?.attributes?.["openclaw.provider"]).toBe("openai");
1280+expect(runOptions?.attributes?.["openclaw.model"]).toBe("gpt-5.4");
1281+expect(runOptions?.attributes?.["openclaw.channel"]).toBe("webchat");
1282+expect(Object.hasOwn(runOptions?.attributes ?? {}, "gen_ai.system")).toBe(false);
1283+expect(Object.hasOwn(runOptions?.attributes ?? {}, "gen_ai.request.model")).toBe(false);
1284+expect(Object.hasOwn(runOptions?.attributes ?? {}, "openclaw.runId")).toBe(false);
1285+expect(Object.hasOwn(runOptions?.attributes ?? {}, "openclaw.sessionKey")).toBe(false);
1286+expect(Object.hasOwn(runOptions?.attributes ?? {}, "openclaw.traceId")).toBe(false);
1287+expect(runOptions?.startTime).toBeTypeOf("number");
1288+1289+const modelCall = startedSpanCall("openclaw.model.call");
1290+const modelOptions = modelCall?.[1];
1291+expect(modelOptions?.attributes?.["gen_ai.system"]).toBe("openai");
1292+expect(modelOptions?.attributes?.["gen_ai.request.model"]).toBe("gpt-5.4");
1293+expect(modelOptions?.attributes?.["gen_ai.operation.name"]).toBe("text_completion");
1294+expect(Object.hasOwn(modelOptions?.attributes ?? {}, "gen_ai.provider.name")).toBe(false);
1295+expect(Object.hasOwn(modelOptions?.attributes ?? {}, "openclaw.callId")).toBe(false);
1296+expect(Object.hasOwn(modelOptions?.attributes ?? {}, "openclaw.runId")).toBe(false);
1297+expect(Object.hasOwn(modelOptions?.attributes ?? {}, "openclaw.sessionKey")).toBe(false);
1298+expect(modelOptions?.startTime).toBeTypeOf("number");
13171299expect(modelCall?.[2]).toBeUndefined();
131813001319-const harnessCall = telemetryState.tracer.startSpan.mock.calls.find(
1320-(call) => call[0] === "openclaw.harness.run",
1301+const harnessCall = startedSpanCall("openclaw.harness.run");
1302+const harnessOptions = harnessCall?.[1];
1303+expect(harnessOptions?.attributes?.["openclaw.harness.id"]).toBe("codex");
1304+expect(harnessOptions?.attributes?.["openclaw.harness.plugin"]).toBe("codex-plugin");
1305+expect(harnessOptions?.attributes?.["openclaw.outcome"]).toBe("completed");
1306+expect(harnessOptions?.attributes?.["openclaw.provider"]).toBe("codex");
1307+expect(harnessOptions?.attributes?.["openclaw.model"]).toBe("gpt-5.4");
1308+expect(harnessOptions?.attributes?.["openclaw.channel"]).toBe("qa");
1309+expect(harnessOptions?.attributes?.["openclaw.harness.result_classification"]).toBe(
1310+"reasoning-only",
13211311);
1322-expect(harnessCall?.[1]).toMatchObject({
1323-attributes: {
1324-"openclaw.harness.id": "codex",
1325-"openclaw.harness.plugin": "codex-plugin",
1326-"openclaw.outcome": "completed",
1327-"openclaw.provider": "codex",
1328-"openclaw.model": "gpt-5.4",
1329-"openclaw.channel": "qa",
1330-"openclaw.harness.result_classification": "reasoning-only",
1331-"openclaw.harness.yield_detected": true,
1332-"openclaw.harness.items.started": 3,
1333-"openclaw.harness.items.completed": 2,
1334-"openclaw.harness.items.active": 1,
1335-},
1336-startTime: expect.any(Number),
1337-});
1338-expect(harnessCall?.[1]).toEqual({
1339-attributes: expect.not.objectContaining({
1340-"openclaw.runId": expect.anything(),
1341-"openclaw.sessionId": expect.anything(),
1342-"openclaw.sessionKey": expect.anything(),
1343-"openclaw.traceId": expect.anything(),
1344-}),
1345-startTime: expect.any(Number),
1346-});
1312+expect(harnessOptions?.attributes?.["openclaw.harness.yield_detected"]).toBe(true);
1313+expect(harnessOptions?.attributes?.["openclaw.harness.items.started"]).toBe(3);
1314+expect(harnessOptions?.attributes?.["openclaw.harness.items.completed"]).toBe(2);
1315+expect(harnessOptions?.attributes?.["openclaw.harness.items.active"]).toBe(1);
1316+expect(Object.hasOwn(harnessOptions?.attributes ?? {}, "openclaw.runId")).toBe(false);
1317+expect(Object.hasOwn(harnessOptions?.attributes ?? {}, "openclaw.sessionId")).toBe(false);
1318+expect(Object.hasOwn(harnessOptions?.attributes ?? {}, "openclaw.sessionKey")).toBe(false);
1319+expect(Object.hasOwn(harnessOptions?.attributes ?? {}, "openclaw.traceId")).toBe(false);
1320+expect(harnessOptions?.startTime).toBeTypeOf("number");
13471321expect(harnessCall?.[2]).toBeUndefined();
134813221349-const toolCall = telemetryState.tracer.startSpan.mock.calls.find(
1350-(call) => call[0] === "openclaw.tool.execution",
1351-);
1352-expect(toolCall?.[1]).toMatchObject({
1353-attributes: {
1354-"openclaw.toolName": "read",
1355-"openclaw.errorCategory": "TypeError",
1356-"openclaw.errorCode": "429",
1357-"openclaw.tool.params.kind": "object",
1358-"gen_ai.tool.name": "read",
1359-},
1360-});
1361-expect(toolCall?.[1]).toEqual({
1362-attributes: expect.not.objectContaining({
1363-"openclaw.toolCallId": expect.anything(),
1364-"openclaw.runId": expect.anything(),
1365-"openclaw.sessionKey": expect.anything(),
1366-}),
1367-startTime: expect.any(Number),
1368-});
1323+const toolCall = startedSpanCall("openclaw.tool.execution");
1324+const toolOptions = toolCall?.[1];
1325+expect(toolOptions?.attributes?.["openclaw.toolName"]).toBe("read");
1326+expect(toolOptions?.attributes?.["openclaw.errorCategory"]).toBe("TypeError");
1327+expect(toolOptions?.attributes?.["openclaw.errorCode"]).toBe("429");
1328+expect(toolOptions?.attributes?.["openclaw.tool.params.kind"]).toBe("object");
1329+expect(toolOptions?.attributes?.["gen_ai.tool.name"]).toBe("read");
1330+expect(Object.hasOwn(toolOptions?.attributes ?? {}, "openclaw.toolCallId")).toBe(false);
1331+expect(Object.hasOwn(toolOptions?.attributes ?? {}, "openclaw.runId")).toBe(false);
1332+expect(Object.hasOwn(toolOptions?.attributes ?? {}, "openclaw.sessionKey")).toBe(false);
1333+expect(toolOptions?.startTime).toBeTypeOf("number");
13691334expect(toolCall?.[2]).toBeUndefined();
1370133513711336expect(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。