From 94472e00829d5433a7eb8d013b19f0ee81a8589d Mon Sep 17 00:00:00 2001 From: ZxlDragonDoctor <152901610+ZxlDragonDoctor@users.noreply.github.com> Date: Sat, 12 Sep 2026 19:48:59 +0800 Subject: [PATCH 1/4] fix(semconv): dual-emit OTel GenAI input/output token usage names --- agentops/semconv/span_attributes.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/agentops/semconv/span_attributes.py b/agentops/semconv/span_attributes.py index 2c5f8ce1c..255980008 100644 --- a/agentops/semconv/span_attributes.py +++ b/agentops/semconv/span_attributes.py @@ -58,8 +58,12 @@ class SpanAttributes: LLM_RESPONSE_ID = "gen_ai.response.id" # Usage metrics + # Legacy GenAI names still emitted by AgentOps; current OTel GenAI names are + # dual-emitted during the transition (#1447). LLM_USAGE_COMPLETION_TOKENS = "gen_ai.usage.completion_tokens" LLM_USAGE_PROMPT_TOKENS = "gen_ai.usage.prompt_tokens" + LLM_USAGE_INPUT_TOKENS = "gen_ai.usage.input_tokens" + LLM_USAGE_OUTPUT_TOKENS = "gen_ai.usage.output_tokens" LLM_USAGE_TOTAL_TOKENS = "gen_ai.usage.total_tokens" LLM_USAGE_CACHE_CREATION_INPUT_TOKENS = "gen_ai.usage.cache_creation_input_tokens" LLM_USAGE_CACHE_READ_INPUT_TOKENS = "gen_ai.usage.cache_read_input_tokens" From 7bf5ec0f1b0f87f42b4e9e2c13393088e0197540 Mon Sep 17 00:00:00 2001 From: ZxlDragonDoctor <152901610+ZxlDragonDoctor@users.noreply.github.com> Date: Sat, 12 Sep 2026 19:49:00 +0800 Subject: [PATCH 2/4] fix(semconv): dual-emit OTel GenAI input/output token usage names --- agentops/instrumentation/common/token_counting.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/agentops/instrumentation/common/token_counting.py b/agentops/instrumentation/common/token_counting.py index 7d2f19f07..dd5b676dd 100644 --- a/agentops/instrumentation/common/token_counting.py +++ b/agentops/instrumentation/common/token_counting.py @@ -32,9 +32,12 @@ def to_attributes(self) -> Dict[str, int]: if self.prompt_tokens: attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] = self.prompt_tokens + # Dual-emit current OTel GenAI names so mixed-SDK collectors can sum either family. + attributes[SpanAttributes.LLM_USAGE_INPUT_TOKENS] = self.prompt_tokens if self.completion_tokens: attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] = self.completion_tokens + attributes[SpanAttributes.LLM_USAGE_OUTPUT_TOKENS] = self.completion_tokens if self.total_tokens: attributes[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] = self.total_tokens From db5a87495e678d4e0286461b26c8f15380c5863c Mon Sep 17 00:00:00 2001 From: ZxlDragonDoctor <152901610+ZxlDragonDoctor@users.noreply.github.com> Date: Sat, 12 Sep 2026 19:49:01 +0800 Subject: [PATCH 3/4] fix(semconv): dual-emit OTel GenAI input/output token usage names --- .../instrumentation/common/test_token_counting.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/unit/instrumentation/common/test_token_counting.py b/tests/unit/instrumentation/common/test_token_counting.py index 2f00561b9..2e5e28253 100644 --- a/tests/unit/instrumentation/common/test_token_counting.py +++ b/tests/unit/instrumentation/common/test_token_counting.py @@ -21,6 +21,18 @@ def test_includes_positive_values_only(self): attrs = usage.to_attributes() assert SpanAttributes.LLM_USAGE_PROMPT_TOKENS in attrs assert attrs[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 5 + assert SpanAttributes.LLM_USAGE_INPUT_TOKENS in attrs + assert attrs[SpanAttributes.LLM_USAGE_INPUT_TOKENS] == 5 assert SpanAttributes.LLM_USAGE_COMPLETION_TOKENS not in attrs + assert SpanAttributes.LLM_USAGE_OUTPUT_TOKENS not in attrs assert SpanAttributes.LLM_USAGE_TOTAL_TOKENS in attrs assert attrs[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 5 + + def test_dual_emits_current_otel_genai_names(self): + usage = TokenUsage(prompt_tokens=10, completion_tokens=4, total_tokens=14) + attrs = usage.to_attributes() + assert attrs[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] == 10 + assert attrs[SpanAttributes.LLM_USAGE_INPUT_TOKENS] == 10 + assert attrs[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] == 4 + assert attrs[SpanAttributes.LLM_USAGE_OUTPUT_TOKENS] == 4 + assert attrs[SpanAttributes.LLM_USAGE_TOTAL_TOKENS] == 14 From 76656c7fc7ea6bc216fad9532982e4cd354fc905 Mon Sep 17 00:00:00 2001 From: ZxlDragonDoctor <2252406579@qq.com> Date: Fri, 16 Oct 2026 18:11:17 +0800 Subject: [PATCH 4/4] docs(semconv): warn about dual-emitted token double counting --- agentops/instrumentation/common/token_counting.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/agentops/instrumentation/common/token_counting.py b/agentops/instrumentation/common/token_counting.py index dd5b676dd..3119044af 100644 --- a/agentops/instrumentation/common/token_counting.py +++ b/agentops/instrumentation/common/token_counting.py @@ -32,11 +32,14 @@ def to_attributes(self) -> Dict[str, int]: if self.prompt_tokens: attributes[SpanAttributes.LLM_USAGE_PROMPT_TOKENS] = self.prompt_tokens - # Dual-emit current OTel GenAI names so mixed-SDK collectors can sum either family. + # Legacy names are compatibility aliases: consumers should prefer the current OTel + # GenAI names; summing both families double-counts the same usage. attributes[SpanAttributes.LLM_USAGE_INPUT_TOKENS] = self.prompt_tokens if self.completion_tokens: attributes[SpanAttributes.LLM_USAGE_COMPLETION_TOKENS] = self.completion_tokens + # Legacy names are compatibility aliases: consumers should prefer the current OTel + # GenAI names; summing both families double-counts the same usage. attributes[SpanAttributes.LLM_USAGE_OUTPUT_TOKENS] = self.completion_tokens if self.total_tokens: