From 5671fdca876f6cd66e304920454be81b0097e54e Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 25 Apr 2026 12:02:48 -0700 Subject: [PATCH] feat(diagnostics-otel): add genai usage span identity --- CHANGELOG.md | 1 + extensions/diagnostics-otel/src/service.test.ts | 3 +++ extensions/diagnostics-otel/src/service.ts | 1 + 3 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23681779a2d..21963fd7abf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Docs: https://docs.openclaw.ai kept as a deprecated compatibility fallback. Thanks @vincentkoc. - Diagnostics/OTEL: add the GenAI `gen_ai.client.operation.duration` histogram for model-call latency in seconds with bounded provider/model/API and error attributes. Thanks @vincentkoc. - Diagnostics/OTEL: add GenAI usage token attributes to model-usage spans, including cache read/write input token counts without session identifiers or prompt/response content. Thanks @vincentkoc. +- Diagnostics/OTEL: include bounded GenAI operation, provider, and request-model attributes on model-usage spans so token usage remains self-describing without diagnostic identifiers. Thanks @vincentkoc. - Diagnostics/OTEL: add bounded outbound message delivery lifecycle diagnostics and export them as low-cardinality delivery spans/metrics without message body, recipient, room, or media-path data. (#71471) Thanks @vincentkoc and @jlapenna. - Diagnostics/OTEL: emit bounded exec-process diagnostics and export them as `openclaw.exec` spans without exposing command text, working directories, or container identifiers. (#71451) Thanks @vincentkoc and @jlapenna. - Diagnostics/OTEL: support `OPENCLAW_OTEL_PRELOADED=1` so the plugin can reuse an already-registered OpenTelemetry SDK while keeping OpenClaw diagnostic listeners wired. (#71450) Thanks @vincentkoc and @jlapenna. diff --git a/extensions/diagnostics-otel/src/service.test.ts b/extensions/diagnostics-otel/src/service.test.ts index 7804cd820df..da44730a996 100644 --- a/extensions/diagnostics-otel/src/service.test.ts +++ b/extensions/diagnostics-otel/src/service.test.ts @@ -768,6 +768,9 @@ describe("diagnostics-otel service", () => { ); expect(modelUsageCall?.[1]).toMatchObject({ attributes: { + "gen_ai.operation.name": "chat", + "gen_ai.provider.name": "anthropic", + "gen_ai.request.model": "claude-sonnet-4.6", "gen_ai.usage.input_tokens": 150, "gen_ai.usage.output_tokens": 40, "gen_ai.usage.cache_read.input_tokens": 30, diff --git a/extensions/diagnostics-otel/src/service.ts b/extensions/diagnostics-otel/src/service.ts index a7157857300..f97a62d4e8f 100644 --- a/extensions/diagnostics-otel/src/service.ts +++ b/extensions/diagnostics-otel/src/service.ts @@ -953,6 +953,7 @@ export function createDiagnosticsOtelService(): OpenClawPluginService { (usage.input ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0); const spanAttrs: Record = { ...attrs, + ...genAiAttrs, "openclaw.tokens.input": usage.input ?? 0, "openclaw.tokens.output": usage.output ?? 0, "openclaw.tokens.cache_read": usage.cacheRead ?? 0,