Fix tracing to use ServiceSettings API instead of dict access

The ServiceSettings refactor (PR #3714) changed self._settings from
dicts to dataclass subclasses, but tracing code still used .items(),
in containment, and subscript access, causing AttributeError on
every traced call. Use given_fields() for iteration and attribute
access for named fields.
This commit is contained in:
Mark Backman
2026-02-27 22:35:29 -05:00
parent 17205c1647
commit 9d4955054c
3 changed files with 16 additions and 18 deletions

View File

@@ -0,0 +1 @@
- Updated tracing code to use `ServiceSettings` dataclass API (`given_fields()`, attribute access) instead of dict-style access (`.items()`, `in`, subscript).

View File

@@ -17,6 +17,8 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional
if TYPE_CHECKING: if TYPE_CHECKING:
from opentelemetry.trace import Span from opentelemetry.trace import Span
from pipecat.services.settings import ServiceSettings
from pipecat.utils.tracing.setup import is_tracing_available from pipecat.utils.tracing.setup import is_tracing_available
if is_tracing_available(): if is_tracing_available():
@@ -68,7 +70,7 @@ def add_tts_span_attributes(
model: str, model: str,
voice_id: str, voice_id: str,
text: Optional[str] = None, text: Optional[str] = None,
settings: Optional[Dict[str, Any]] = None, settings: Optional["ServiceSettings"] = None,
character_count: Optional[int] = None, character_count: Optional[int] = None,
operation_name: str = "tts", operation_name: str = "tts",
ttfb: Optional[float] = None, ttfb: Optional[float] = None,
@@ -107,7 +109,7 @@ def add_tts_span_attributes(
# Add settings if provided # Add settings if provided
if settings: if settings:
for key, value in settings.items(): for key, value in settings.given_fields().items():
if isinstance(value, (str, int, float, bool)): if isinstance(value, (str, int, float, bool)):
span.set_attribute(f"settings.{key}", value) span.set_attribute(f"settings.{key}", value)
@@ -126,7 +128,7 @@ def add_stt_span_attributes(
is_final: Optional[bool] = None, is_final: Optional[bool] = None,
language: Optional[str] = None, language: Optional[str] = None,
user_id: Optional[str] = None, user_id: Optional[str] = None,
settings: Optional[Dict[str, Any]] = None, settings: Optional["ServiceSettings"] = None,
vad_enabled: bool = False, vad_enabled: bool = False,
ttfb: Optional[float] = None, ttfb: Optional[float] = None,
**kwargs, **kwargs,
@@ -171,7 +173,7 @@ def add_stt_span_attributes(
# Add settings if provided # Add settings if provided
if settings: if settings:
for key, value in settings.items(): for key, value in settings.given_fields().items():
if isinstance(value, (str, int, float, bool)): if isinstance(value, (str, int, float, bool)):
span.set_attribute(f"settings.{key}", value) span.set_attribute(f"settings.{key}", value)
@@ -282,7 +284,7 @@ def add_gemini_live_span_attributes(
voice_id: Optional[str] = None, voice_id: Optional[str] = None,
language: Optional[str] = None, language: Optional[str] = None,
modalities: Optional[str] = None, modalities: Optional[str] = None,
settings: Optional[Dict[str, Any]] = None, settings: Optional["ServiceSettings"] = None,
tools: Optional[List[Dict]] = None, tools: Optional[List[Dict]] = None,
tools_serialized: Optional[str] = None, tools_serialized: Optional[str] = None,
transcript: Optional[str] = None, transcript: Optional[str] = None,
@@ -359,7 +361,7 @@ def add_gemini_live_span_attributes(
# Add settings if provided # Add settings if provided
if settings: if settings:
for key, value in settings.items(): for key, value in settings.given_fields().items():
if isinstance(value, (str, int, float, bool)): if isinstance(value, (str, int, float, bool)):
span.set_attribute(f"settings.{key}", value) span.set_attribute(f"settings.{key}", value)
elif key == "vad" and value: elif key == "vad" and value:

View File

@@ -219,7 +219,7 @@ def traced_tts(func: Optional[Callable] = None, *, name: Optional[str] = None) -
tracer = trace.get_tracer("pipecat") tracer = trace.get_tracer("pipecat")
with tracer.start_as_current_span(span_name, context=parent_context) as span: with tracer.start_as_current_span(span_name, context=parent_context) as span:
try: try:
settings = getattr(self, "_settings", {}) settings = getattr(self, "_settings", None)
add_tts_span_attributes( add_tts_span_attributes(
span=span, span=span,
service_name=service_class_name, service_name=service_class_name,
@@ -338,7 +338,7 @@ def traced_stt(func: Optional[Callable] = None, *, name: Optional[str] = None) -
) )
# Use settings from the service if available # Use settings from the service if available
settings = getattr(self, "_settings", {}) settings = getattr(self, "_settings", None)
add_stt_span_attributes( add_stt_span_attributes(
span=current_span, span=current_span,
@@ -510,15 +510,10 @@ def traced_llm(func: Optional[Callable] = None, *, name: Optional[str] = None) -
# Get settings from the service # Get settings from the service
params = {} params = {}
if hasattr(self, "_settings"): if hasattr(self, "_settings"):
for key, value in self._settings.items(): for key, value in self._settings.given_fields().items():
if key == "extra":
continue
# Add value directly if it's a basic type
if isinstance(value, (int, float, bool, str)): if isinstance(value, (int, float, bool, str)):
params[key] = value params[key] = value
elif value is None or ( elif value is None:
hasattr(value, "__name__") and value.__name__ == "NOT_GIVEN"
):
params[key] = "NOT_GIVEN" params[key] = "NOT_GIVEN"
# Add all available attributes to the span # Add all available attributes to the span
@@ -627,12 +622,12 @@ def traced_gemini_live(operation: str) -> Callable:
model_name = _get_model_name(self) model_name = _get_model_name(self)
voice_id = getattr(self, "_voice_id", None) voice_id = getattr(self, "_voice_id", None)
language_code = getattr(self, "_language_code", None) language_code = getattr(self, "_language_code", None)
settings = getattr(self, "_settings", {}) settings = getattr(self, "_settings", None)
# Get modalities if available # Get modalities if available
modalities = None modalities = None
if hasattr(self, "_settings") and "modalities" in self._settings: if settings and hasattr(settings, "modalities"):
modality_obj = self._settings["modalities"] modality_obj = settings.modalities
if hasattr(modality_obj, "value"): if hasattr(modality_obj, "value"):
modalities = modality_obj.value modalities = modality_obj.value
else: else: