Merge pull request #1859 from pipecat-ai/mb/otel-attribute-naming
Update OTel attribute names
This commit is contained in:
@@ -18,6 +18,39 @@ 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:
|
||||||
|
"""Extract the standardized gen_ai.system value from a service class name.
|
||||||
|
|
||||||
|
Source:
|
||||||
|
https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/#gen-ai-system
|
||||||
|
|
||||||
|
Uses standard OTel names where possible, with special case mappings for
|
||||||
|
service names that don't follow the pattern.
|
||||||
|
"""
|
||||||
|
SPECIAL_CASE_MAPPINGS = {
|
||||||
|
# AWS
|
||||||
|
"AWSBedrockLLMService": "aws.bedrock",
|
||||||
|
# Azure
|
||||||
|
"AzureLLMService": "az.ai.openai",
|
||||||
|
# Google
|
||||||
|
"GoogleLLMService": "gcp.gemini",
|
||||||
|
"GoogleLLMOpenAIBetaService": "gcp.gemini",
|
||||||
|
"GoogleVertexLLMService": "gcp.vertex_ai",
|
||||||
|
# Others
|
||||||
|
"GrokLLMService": "xai",
|
||||||
|
}
|
||||||
|
|
||||||
|
if service_name in SPECIAL_CASE_MAPPINGS:
|
||||||
|
return SPECIAL_CASE_MAPPINGS[service_name]
|
||||||
|
|
||||||
|
if service_name.endswith("LLMService"):
|
||||||
|
provider = service_name[:-10].lower()
|
||||||
|
else:
|
||||||
|
provider = service_name.lower()
|
||||||
|
|
||||||
|
return provider
|
||||||
|
|
||||||
|
|
||||||
def add_tts_span_attributes(
|
def add_tts_span_attributes(
|
||||||
span: "Span",
|
span: "Span",
|
||||||
service_name: str,
|
service_name: str,
|
||||||
@@ -45,17 +78,18 @@ def add_tts_span_attributes(
|
|||||||
**kwargs: Additional attributes to add
|
**kwargs: Additional attributes to add
|
||||||
"""
|
"""
|
||||||
# Add standard attributes
|
# Add standard attributes
|
||||||
span.set_attribute("service.name", service_name)
|
span.set_attribute("gen_ai.system", service_name.replace("TTSService", "").lower())
|
||||||
span.set_attribute("model", model)
|
span.set_attribute("gen_ai.request.model", model)
|
||||||
|
span.set_attribute("gen_ai.operation.name", operation_name)
|
||||||
|
span.set_attribute("gen_ai.output.type", "speech")
|
||||||
span.set_attribute("voice_id", voice_id)
|
span.set_attribute("voice_id", voice_id)
|
||||||
span.set_attribute("operation", operation_name)
|
|
||||||
|
|
||||||
# Add optional attributes
|
# Add optional attributes
|
||||||
if text:
|
if text:
|
||||||
span.set_attribute("text", text)
|
span.set_attribute("text", text)
|
||||||
|
|
||||||
if character_count is not None:
|
if character_count is not None:
|
||||||
span.set_attribute("metrics.tts.character_count", character_count)
|
span.set_attribute("metrics.character_count", character_count)
|
||||||
|
|
||||||
if ttfb_ms is not None:
|
if ttfb_ms is not None:
|
||||||
span.set_attribute("metrics.ttfb_ms", ttfb_ms)
|
span.set_attribute("metrics.ttfb_ms", ttfb_ms)
|
||||||
@@ -76,6 +110,7 @@ def add_stt_span_attributes(
|
|||||||
span: "Span",
|
span: "Span",
|
||||||
service_name: str,
|
service_name: str,
|
||||||
model: str,
|
model: str,
|
||||||
|
operation_name: str = "stt",
|
||||||
transcript: Optional[str] = None,
|
transcript: Optional[str] = None,
|
||||||
is_final: Optional[bool] = None,
|
is_final: Optional[bool] = None,
|
||||||
language: Optional[str] = None,
|
language: Optional[str] = None,
|
||||||
@@ -90,6 +125,7 @@ def add_stt_span_attributes(
|
|||||||
span: The span to add attributes to
|
span: The span to add attributes to
|
||||||
service_name: Name of the STT service (e.g., "deepgram")
|
service_name: Name of the STT service (e.g., "deepgram")
|
||||||
model: Model name/identifier
|
model: Model name/identifier
|
||||||
|
operation_name: Name of the operation (default: "stt")
|
||||||
transcript: The transcribed text
|
transcript: The transcribed text
|
||||||
is_final: Whether this is a final transcript
|
is_final: Whether this is a final transcript
|
||||||
language: Detected or configured language
|
language: Detected or configured language
|
||||||
@@ -99,8 +135,9 @@ def add_stt_span_attributes(
|
|||||||
**kwargs: Additional attributes to add
|
**kwargs: Additional attributes to add
|
||||||
"""
|
"""
|
||||||
# Add standard attributes
|
# Add standard attributes
|
||||||
span.set_attribute("service.name", service_name)
|
span.set_attribute("gen_ai.system", service_name.replace("STTService", "").lower())
|
||||||
span.set_attribute("model", model)
|
span.set_attribute("gen_ai.request.model", model)
|
||||||
|
span.set_attribute("gen_ai.operation.name", operation_name)
|
||||||
span.set_attribute("vad_enabled", vad_enabled)
|
span.set_attribute("vad_enabled", vad_enabled)
|
||||||
|
|
||||||
# Add optional attributes
|
# Add optional attributes
|
||||||
@@ -161,13 +198,15 @@ def add_llm_span_attributes(
|
|||||||
**kwargs: Additional attributes to add
|
**kwargs: Additional attributes to add
|
||||||
"""
|
"""
|
||||||
# Add standard attributes
|
# Add standard attributes
|
||||||
span.set_attribute("service.name", service_name)
|
span.set_attribute("gen_ai.system", _get_gen_ai_system_from_service_name(service_name))
|
||||||
span.set_attribute("model", model)
|
span.set_attribute("gen_ai.request.model", model)
|
||||||
|
span.set_attribute("gen_ai.operation.name", "chat")
|
||||||
|
span.set_attribute("gen_ai.output.type", "text")
|
||||||
span.set_attribute("stream", stream)
|
span.set_attribute("stream", stream)
|
||||||
|
|
||||||
# Add optional attributes
|
# Add optional attributes
|
||||||
if messages:
|
if messages:
|
||||||
span.set_attribute("messages", messages)
|
span.set_attribute("input", messages)
|
||||||
|
|
||||||
if tools:
|
if tools:
|
||||||
span.set_attribute("tools", tools)
|
span.set_attribute("tools", tools)
|
||||||
@@ -188,7 +227,19 @@ def add_llm_span_attributes(
|
|||||||
if parameters:
|
if parameters:
|
||||||
for key, value in parameters.items():
|
for key, value in parameters.items():
|
||||||
if isinstance(value, (str, int, float, bool)):
|
if isinstance(value, (str, int, float, bool)):
|
||||||
span.set_attribute(f"param.{key}", value)
|
if key in [
|
||||||
|
"temperature",
|
||||||
|
"max_tokens",
|
||||||
|
"max_completion_tokens",
|
||||||
|
"top_p",
|
||||||
|
"top_k",
|
||||||
|
"frequency_penalty",
|
||||||
|
"presence_penalty",
|
||||||
|
"seed",
|
||||||
|
]:
|
||||||
|
span.set_attribute(f"gen_ai.request.{key}", value)
|
||||||
|
else:
|
||||||
|
span.set_attribute(f"param.{key}", value)
|
||||||
|
|
||||||
# Add extra parameters if provided
|
# Add extra parameters if provided
|
||||||
if extra_parameters:
|
if extra_parameters:
|
||||||
|
|||||||
@@ -67,20 +67,6 @@ def _get_parent_service_context(self):
|
|||||||
return context_api.get_current()
|
return context_api.get_current()
|
||||||
|
|
||||||
|
|
||||||
def _get_service_name(self, service_prefix: str) -> str:
|
|
||||||
"""Generate a default span name using service type and class name.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
self: The service instance.
|
|
||||||
service_prefix: The service type (e.g., 'llm', 'stt', 'tts').
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A default span name string like "type_classname" (e.g. llm_openaillmservice).
|
|
||||||
"""
|
|
||||||
service_class_name = self.__class__.__name__.lower()
|
|
||||||
return f"{service_prefix}_{service_class_name}"
|
|
||||||
|
|
||||||
|
|
||||||
def _add_token_usage_to_span(span, token_usage):
|
def _add_token_usage_to_span(span, token_usage):
|
||||||
"""Add token usage metrics to a span (internal use only).
|
"""Add token usage metrics to a span (internal use only).
|
||||||
|
|
||||||
@@ -93,13 +79,15 @@ def _add_token_usage_to_span(span, token_usage):
|
|||||||
|
|
||||||
if isinstance(token_usage, dict):
|
if isinstance(token_usage, dict):
|
||||||
if "prompt_tokens" in token_usage:
|
if "prompt_tokens" in token_usage:
|
||||||
span.set_attribute("llm.prompt_tokens", token_usage["prompt_tokens"])
|
span.set_attribute("gen_ai.usage.input_tokens", token_usage["prompt_tokens"])
|
||||||
if "completion_tokens" in token_usage:
|
if "completion_tokens" in token_usage:
|
||||||
span.set_attribute("llm.completion_tokens", token_usage["completion_tokens"])
|
span.set_attribute("gen_ai.usage.output_tokens", token_usage["completion_tokens"])
|
||||||
else:
|
else:
|
||||||
# Handle LLMTokenUsage object
|
# Handle LLMTokenUsage object
|
||||||
span.set_attribute("llm.prompt_tokens", getattr(token_usage, "prompt_tokens", 0))
|
span.set_attribute("gen_ai.usage.input_tokens", getattr(token_usage, "prompt_tokens", 0))
|
||||||
span.set_attribute("llm.completion_tokens", getattr(token_usage, "completion_tokens", 0))
|
span.set_attribute(
|
||||||
|
"gen_ai.usage.output_tokens", getattr(token_usage, "completion_tokens", 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def traced_tts(func: Optional[Callable] = None, *, name: Optional[str] = None) -> Callable:
|
def traced_tts(func: Optional[Callable] = None, *, name: Optional[str] = None) -> Callable:
|
||||||
@@ -134,7 +122,7 @@ def traced_tts(func: Optional[Callable] = None, *, name: Optional[str] = None) -
|
|||||||
return
|
return
|
||||||
|
|
||||||
service_class_name = self.__class__.__name__
|
service_class_name = self.__class__.__name__
|
||||||
span_name = name or _get_service_name(self, "tts")
|
span_name = "tts"
|
||||||
|
|
||||||
# Get parent context
|
# Get parent context
|
||||||
turn_context = get_current_turn_context()
|
turn_context = get_current_turn_context()
|
||||||
@@ -237,7 +225,7 @@ def traced_stt(func: Optional[Callable] = None, *, name: Optional[str] = None) -
|
|||||||
return await f(self, transcript, is_final, language)
|
return await f(self, transcript, is_final, language)
|
||||||
|
|
||||||
service_class_name = self.__class__.__name__
|
service_class_name = self.__class__.__name__
|
||||||
span_name = name or _get_service_name(self, "stt")
|
span_name = "stt"
|
||||||
|
|
||||||
# Get the turn context first, then fall back to service context
|
# Get the turn context first, then fall back to service context
|
||||||
turn_context = get_current_turn_context()
|
turn_context = get_current_turn_context()
|
||||||
@@ -313,7 +301,7 @@ def traced_llm(func: Optional[Callable] = None, *, name: Optional[str] = None) -
|
|||||||
return await f(self, context, *args, **kwargs)
|
return await f(self, context, *args, **kwargs)
|
||||||
|
|
||||||
service_class_name = self.__class__.__name__
|
service_class_name = self.__class__.__name__
|
||||||
span_name = name or _get_service_name(self, "llm")
|
span_name = "llm"
|
||||||
|
|
||||||
# Get the parent context - turn context if available, otherwise service context
|
# Get the parent context - turn context if available, otherwise service context
|
||||||
turn_context = get_current_turn_context()
|
turn_context = get_current_turn_context()
|
||||||
|
|||||||
Reference in New Issue
Block a user