refactor: align tracing attributes with OpenTelemetry GenAI conventions

- gen_ai.system -> gen_ai.provider.name (deprecated)
- system / system_instructions -> gen_ai.system_instructions
- gen_ai.usage.cache_read_input_tokens -> gen_ai.usage.cache_read.input_tokens
- gen_ai.usage.cache_creation_input_tokens -> gen_ai.usage.cache_creation.input_tokens
This commit is contained in:
Mark Backman
2026-03-20 13:36:20 -04:00
parent 20a3ada916
commit e4a82ffcac
3 changed files with 16 additions and 16 deletions

View File

@@ -1 +1 @@
- Renamed tracing span attribute `system` to `system_instructions` to align with the OpenTelemetry GenAI semantic conventions. - Renamed tracing span attributes to align with OpenTelemetry GenAI semantic conventions: `gen_ai.system` to `gen_ai.provider.name`, `system` to `gen_ai.system_instructions`, `gen_ai.usage.cache_read_input_tokens` to `gen_ai.usage.cache_read.input_tokens`, and `gen_ai.usage.cache_creation_input_tokens` to `gen_ai.usage.cache_creation.input_tokens`.

View File

@@ -25,20 +25,20 @@ if is_tracing_available():
from opentelemetry.trace import Span from opentelemetry.trace import Span
def _get_gen_ai_system_from_service_name(service_name: str) -> str: def _get_provider_name_from_service_name(service_name: str) -> str:
"""Extract the standardized gen_ai.system value from a service class name. """Extract the standardized gen_ai.provider.name value from a service class name.
Source: Source:
https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/#gen-ai-system https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/
Uses standard OTel names where possible, with special case mappings for Uses standard OTel names where possible, with special case mappings for
service names that don't follow the pattern. service names that don't follow the pattern.
Args: Args:
service_name: The service class name to extract system name from. service_name: The service class name to extract provider name from.
Returns: Returns:
The standardized gen_ai.system value. The standardized gen_ai.provider.name value.
""" """
SPECIAL_CASE_MAPPINGS = { SPECIAL_CASE_MAPPINGS = {
# AWS # AWS
@@ -91,7 +91,7 @@ def add_tts_span_attributes(
**kwargs: Additional attributes to add. **kwargs: Additional attributes to add.
""" """
# Add standard attributes # Add standard attributes
span.set_attribute("gen_ai.system", service_name.replace("TTSService", "").lower()) span.set_attribute("gen_ai.provider.name", service_name.replace("TTSService", "").lower())
span.set_attribute("gen_ai.request.model", model) span.set_attribute("gen_ai.request.model", model)
span.set_attribute("gen_ai.operation.name", operation_name) span.set_attribute("gen_ai.operation.name", operation_name)
span.set_attribute("gen_ai.output.type", "speech") span.set_attribute("gen_ai.output.type", "speech")
@@ -150,7 +150,7 @@ def add_stt_span_attributes(
**kwargs: Additional attributes to add. **kwargs: Additional attributes to add.
""" """
# Add standard attributes # Add standard attributes
span.set_attribute("gen_ai.system", service_name.replace("STTService", "").lower()) span.set_attribute("gen_ai.provider.name", service_name.replace("STTService", "").lower())
span.set_attribute("gen_ai.request.model", model) span.set_attribute("gen_ai.request.model", model)
span.set_attribute("gen_ai.operation.name", operation_name) span.set_attribute("gen_ai.operation.name", operation_name)
span.set_attribute("vad_enabled", vad_enabled) span.set_attribute("vad_enabled", vad_enabled)
@@ -218,7 +218,7 @@ def add_llm_span_attributes(
**kwargs: Additional attributes to add. **kwargs: Additional attributes to add.
""" """
# Add standard attributes # Add standard attributes
span.set_attribute("gen_ai.system", _get_gen_ai_system_from_service_name(service_name)) span.set_attribute("gen_ai.provider.name", _get_provider_name_from_service_name(service_name))
span.set_attribute("gen_ai.request.model", model) span.set_attribute("gen_ai.request.model", model)
span.set_attribute("gen_ai.operation.name", "chat") span.set_attribute("gen_ai.operation.name", "chat")
span.set_attribute("gen_ai.output.type", "text") span.set_attribute("gen_ai.output.type", "text")
@@ -241,7 +241,7 @@ def add_llm_span_attributes(
span.set_attribute("tool_choice", tool_choice) span.set_attribute("tool_choice", tool_choice)
if system_instructions: if system_instructions:
span.set_attribute("system_instructions", system_instructions) span.set_attribute("gen_ai.system_instructions", system_instructions)
if ttfb is not None: if ttfb is not None:
span.set_attribute("metrics.ttfb", ttfb) span.set_attribute("metrics.ttfb", ttfb)
@@ -313,7 +313,7 @@ def add_gemini_live_span_attributes(
**kwargs: Additional attributes to add. **kwargs: Additional attributes to add.
""" """
# Add standard attributes # Add standard attributes
span.set_attribute("gen_ai.system", "gcp.gemini") span.set_attribute("gen_ai.provider.name", "gcp.gemini")
span.set_attribute("gen_ai.request.model", model) span.set_attribute("gen_ai.request.model", model)
span.set_attribute("gen_ai.operation.name", operation_name) span.set_attribute("gen_ai.operation.name", operation_name)
span.set_attribute("service.operation", operation_name) span.set_attribute("service.operation", operation_name)
@@ -414,7 +414,7 @@ def add_openai_realtime_span_attributes(
**kwargs: Additional attributes to add. **kwargs: Additional attributes to add.
""" """
# Add standard attributes # Add standard attributes
span.set_attribute("gen_ai.system", "openai") span.set_attribute("gen_ai.provider.name", "openai")
span.set_attribute("gen_ai.request.model", model) span.set_attribute("gen_ai.request.model", model)
span.set_attribute("gen_ai.operation.name", operation_name) span.set_attribute("gen_ai.operation.name", operation_name)
span.set_attribute("service.operation", operation_name) span.set_attribute("service.operation", operation_name)

View File

@@ -137,14 +137,14 @@ def _add_token_usage_to_span(span, token_usage):
and token_usage["cache_read_input_tokens"] is not None and token_usage["cache_read_input_tokens"] is not None
): ):
span.set_attribute( span.set_attribute(
"gen_ai.usage.cache_read_input_tokens", token_usage["cache_read_input_tokens"] "gen_ai.usage.cache_read.input_tokens", token_usage["cache_read_input_tokens"]
) )
if ( if (
"cache_creation_input_tokens" in token_usage "cache_creation_input_tokens" in token_usage
and token_usage["cache_creation_input_tokens"] is not None and token_usage["cache_creation_input_tokens"] is not None
): ):
span.set_attribute( span.set_attribute(
"gen_ai.usage.cache_creation_input_tokens", "gen_ai.usage.cache_creation.input_tokens",
token_usage["cache_creation_input_tokens"], token_usage["cache_creation_input_tokens"],
) )
if "reasoning_tokens" in token_usage and token_usage["reasoning_tokens"] is not None: if "reasoning_tokens" in token_usage and token_usage["reasoning_tokens"] is not None:
@@ -159,11 +159,11 @@ def _add_token_usage_to_span(span, token_usage):
# Add cached token metrics for LLMTokenUsage object # Add cached token metrics for LLMTokenUsage object
cache_read_tokens = getattr(token_usage, "cache_read_input_tokens", None) cache_read_tokens = getattr(token_usage, "cache_read_input_tokens", None)
if cache_read_tokens is not None: if cache_read_tokens is not None:
span.set_attribute("gen_ai.usage.cache_read_input_tokens", cache_read_tokens) span.set_attribute("gen_ai.usage.cache_read.input_tokens", cache_read_tokens)
cache_creation_tokens = getattr(token_usage, "cache_creation_input_tokens", None) cache_creation_tokens = getattr(token_usage, "cache_creation_input_tokens", None)
if cache_creation_tokens is not None: if cache_creation_tokens is not None:
span.set_attribute("gen_ai.usage.cache_creation_input_tokens", cache_creation_tokens) span.set_attribute("gen_ai.usage.cache_creation.input_tokens", cache_creation_tokens)
reasoning_tokens = getattr(token_usage, "reasoning_tokens", None) reasoning_tokens = getattr(token_usage, "reasoning_tokens", None)
if reasoning_tokens is not None: if reasoning_tokens is not None: