Merge pull request #1811 from pipecat-ai/mb/dont-require-tracing-dep

Fix: Resolve an issue where tracing imports were required
This commit is contained in:
Mark Backman
2025-05-14 12:35:47 -04:00
committed by GitHub
7 changed files with 61 additions and 34 deletions

View File

@@ -18,10 +18,10 @@ import functools
import inspect import inspect
from typing import Callable, Optional, TypeVar from typing import Callable, Optional, TypeVar
from pipecat.utils.tracing.setup import OPENTELEMETRY_AVAILABLE from pipecat.utils.tracing.setup import is_tracing_available
# Import OpenTelemetry if available # Import OpenTelemetry if available
if OPENTELEMETRY_AVAILABLE: if is_tracing_available():
import opentelemetry.trace import opentelemetry.trace
from opentelemetry import metrics, trace from opentelemetry import metrics, trace
@@ -59,7 +59,7 @@ class Traceable:
""" """
super().__init__(**kwargs) super().__init__(**kwargs)
if not OPENTELEMETRY_AVAILABLE: if not is_tracing_available():
self._tracer = self._meter = self._parent_span_id = self._span = None self._tracer = self._meter = self._parent_span_id = self._span = None
return return
@@ -177,7 +177,7 @@ def traced(
RuntimeError: If used in a class not inheriting from Traceable. RuntimeError: If used in a class not inheriting from Traceable.
ValueError: If used on a non-async function. ValueError: If used on a non-async function.
""" """
if not OPENTELEMETRY_AVAILABLE: if not is_tracing_available():
# Just return the original function or a simple decorator # Just return the original function or a simple decorator
def decorator(f): def decorator(f):
return f return f
@@ -204,7 +204,7 @@ def traceable(cls: C) -> C:
Returns: Returns:
A new class with tracing capabilities. A new class with tracing capabilities.
""" """
if not OPENTELEMETRY_AVAILABLE: if not is_tracing_available():
return cls return cls
@functools.wraps(cls, updated=()) @functools.wraps(cls, updated=())

View File

@@ -5,7 +5,12 @@
# #
import uuid import uuid
from typing import Optional from typing import TYPE_CHECKING, Optional
# Import types for type checking only
if TYPE_CHECKING:
from opentelemetry.context import Context
from opentelemetry.trace import SpanContext
from pipecat.utils.tracing.setup import is_tracing_available from pipecat.utils.tracing.setup import is_tracing_available
@@ -22,7 +27,7 @@ class ConversationContextProvider:
""" """
_instance = None _instance = None
_current_conversation_context: Optional[Context] = None _current_conversation_context: Optional["Context"] = None
_conversation_id: Optional[str] = None _conversation_id: Optional[str] = None
@classmethod @classmethod
@@ -33,7 +38,7 @@ class ConversationContextProvider:
return cls._instance return cls._instance
def set_current_conversation_context( def set_current_conversation_context(
self, span_context: Optional[SpanContext], conversation_id: Optional[str] = None self, span_context: Optional["SpanContext"], conversation_id: Optional[str] = None
): ):
"""Set the current conversation context. """Set the current conversation context.
@@ -53,7 +58,7 @@ class ConversationContextProvider:
else: else:
self._current_conversation_context = None self._current_conversation_context = None
def get_current_conversation_context(self) -> Optional[Context]: def get_current_conversation_context(self) -> Optional["Context"]:
"""Get the OpenTelemetry context for the current conversation. """Get the OpenTelemetry context for the current conversation.
Returns: Returns:
@@ -79,7 +84,7 @@ class ConversationContextProvider:
# Create a simple helper function to get the current conversation context # Create a simple helper function to get the current conversation context
def get_current_conversation_context() -> Optional[Context]: def get_current_conversation_context() -> Optional["Context"]:
"""Get the OpenTelemetry context for the current conversation. """Get the OpenTelemetry context for the current conversation.
Returns: Returns:

View File

@@ -6,13 +6,20 @@
"""Functions for adding attributes to OpenTelemetry spans.""" """Functions for adding attributes to OpenTelemetry spans."""
from typing import Any, Dict, Optional from typing import TYPE_CHECKING, Any, Dict, Optional
from opentelemetry.trace import Span # Import for type checking only
if TYPE_CHECKING:
from opentelemetry.trace import Span
from pipecat.utils.tracing.setup import is_tracing_available
if is_tracing_available():
from opentelemetry.trace import Span
def add_tts_span_attributes( def add_tts_span_attributes(
span: Span, span: "Span",
service_name: str, service_name: str,
model: str, model: str,
voice_id: str, voice_id: str,
@@ -66,7 +73,7 @@ def add_tts_span_attributes(
def add_stt_span_attributes( def add_stt_span_attributes(
span: Span, span: "Span",
service_name: str, service_name: str,
model: str, model: str,
transcript: Optional[str] = None, transcript: Optional[str] = None,
@@ -122,7 +129,7 @@ def add_stt_span_attributes(
def add_llm_span_attributes( def add_llm_span_attributes(
span: Span, span: "Span",
service_name: str, service_name: str,
model: str, model: str,
stream: bool = True, stream: bool = True,

View File

@@ -16,19 +16,25 @@ import functools
import inspect import inspect
import json import json
import logging import logging
from typing import Callable, Optional, TypeVar from typing import TYPE_CHECKING, Callable, Optional, TypeVar
from opentelemetry import context as context_api # Type imports for type checking only
from opentelemetry import trace if TYPE_CHECKING:
from opentelemetry import context as context_api
from opentelemetry import trace
from pipecat.utils.tracing.service_attributes import ( from pipecat.utils.tracing.service_attributes import (
add_llm_span_attributes, add_llm_span_attributes,
add_stt_span_attributes, add_stt_span_attributes,
add_tts_span_attributes, add_tts_span_attributes,
) )
from pipecat.utils.tracing.setup import OPENTELEMETRY_AVAILABLE, is_tracing_available from pipecat.utils.tracing.setup import is_tracing_available
from pipecat.utils.tracing.turn_context_provider import get_current_turn_context from pipecat.utils.tracing.turn_context_provider import get_current_turn_context
if is_tracing_available():
from opentelemetry import context as context_api
from opentelemetry import trace
T = TypeVar("T") T = TypeVar("T")
R = TypeVar("R") R = TypeVar("R")
@@ -114,7 +120,7 @@ def traced_tts(func: Optional[Callable] = None, *, name: Optional[str] = None) -
Returns: Returns:
Wrapped method with TTS-specific tracing. Wrapped method with TTS-specific tracing.
""" """
if not OPENTELEMETRY_AVAILABLE: if not is_tracing_available():
return _noop_decorator if func is None else _noop_decorator(func) return _noop_decorator if func is None else _noop_decorator(func)
def decorator(f): def decorator(f):
@@ -220,7 +226,7 @@ def traced_stt(func: Optional[Callable] = None, *, name: Optional[str] = None) -
Returns: Returns:
Wrapped method with STT-specific tracing. Wrapped method with STT-specific tracing.
""" """
if not OPENTELEMETRY_AVAILABLE: if not is_tracing_available():
return _noop_decorator if func is None else _noop_decorator(func) return _noop_decorator if func is None else _noop_decorator(func)
def decorator(f): def decorator(f):
@@ -296,7 +302,7 @@ def traced_llm(func: Optional[Callable] = None, *, name: Optional[str] = None) -
Returns: Returns:
Wrapped method with LLM-specific tracing. Wrapped method with LLM-specific tracing.
""" """
if not OPENTELEMETRY_AVAILABLE: if not is_tracing_available():
return _noop_decorator if func is None else _noop_decorator(func) return _noop_decorator if func is None else _noop_decorator(func)
def decorator(f): def decorator(f):

View File

@@ -4,7 +4,12 @@
# SPDX-License-Identifier: BSD 2-Clause License # SPDX-License-Identifier: BSD 2-Clause License
# #
from typing import Optional from typing import TYPE_CHECKING, Optional
# Import types for type checking only
if TYPE_CHECKING:
from opentelemetry.context import Context
from opentelemetry.trace import SpanContext
from pipecat.utils.tracing.setup import is_tracing_available from pipecat.utils.tracing.setup import is_tracing_available
@@ -21,7 +26,7 @@ class TurnContextProvider:
""" """
_instance = None _instance = None
_current_turn_context: Optional[Context] = None _current_turn_context: Optional["Context"] = None
@classmethod @classmethod
def get_instance(cls): def get_instance(cls):
@@ -30,7 +35,7 @@ class TurnContextProvider:
cls._instance = TurnContextProvider() cls._instance = TurnContextProvider()
return cls._instance return cls._instance
def set_current_turn_context(self, span_context: Optional[SpanContext]): def set_current_turn_context(self, span_context: Optional["SpanContext"]):
"""Set the current turn context. """Set the current turn context.
Args: Args:
@@ -46,7 +51,7 @@ class TurnContextProvider:
else: else:
self._current_turn_context = None self._current_turn_context = None
def get_current_turn_context(self) -> Optional[Context]: def get_current_turn_context(self) -> Optional["Context"]:
"""Get the OpenTelemetry context for the current turn. """Get the OpenTelemetry context for the current turn.
Returns: Returns:
@@ -56,7 +61,7 @@ class TurnContextProvider:
# Create a simple helper function to get the current turn context # Create a simple helper function to get the current turn context
def get_current_turn_context() -> Optional[Context]: def get_current_turn_context() -> Optional["Context"]:
"""Get the OpenTelemetry context for the current turn. """Get the OpenTelemetry context for the current turn.
Returns: Returns:

View File

@@ -4,7 +4,7 @@
# SPDX-License-Identifier: BSD 2-Clause License # SPDX-License-Identifier: BSD 2-Clause License
# #
from typing import Dict, Optional from typing import TYPE_CHECKING, Dict, Optional
from loguru import logger from loguru import logger
@@ -14,6 +14,10 @@ from pipecat.utils.tracing.conversation_context_provider import ConversationCont
from pipecat.utils.tracing.setup import is_tracing_available from pipecat.utils.tracing.setup import is_tracing_available
from pipecat.utils.tracing.turn_context_provider import TurnContextProvider from pipecat.utils.tracing.turn_context_provider import TurnContextProvider
# Import types for type checking only
if TYPE_CHECKING:
from opentelemetry.trace import Span, SpanContext
if is_tracing_available(): if is_tracing_available():
from opentelemetry import trace from opentelemetry import trace
from opentelemetry.trace import Span, SpanContext from opentelemetry.trace import Span, SpanContext
@@ -33,13 +37,13 @@ class TurnTraceObserver(BaseObserver):
def __init__(self, turn_tracker: TurnTrackingObserver, conversation_id: Optional[str] = None): def __init__(self, turn_tracker: TurnTrackingObserver, conversation_id: Optional[str] = None):
super().__init__() super().__init__()
self._turn_tracker = turn_tracker self._turn_tracker = turn_tracker
self._current_span: Optional[Span] = None self._current_span: Optional["Span"] = None
self._current_turn_number: int = 0 self._current_turn_number: int = 0
self._trace_context_map: Dict[int, SpanContext] = {} self._trace_context_map: Dict[int, "SpanContext"] = {}
self._tracer = trace.get_tracer("pipecat.turn") if is_tracing_available() else None self._tracer = trace.get_tracer("pipecat.turn") if is_tracing_available() else None
# Conversation tracking properties # Conversation tracking properties
self._conversation_span: Optional[Span] = None self._conversation_span: Optional["Span"] = None
self._conversation_id = conversation_id self._conversation_id = conversation_id
if turn_tracker: if turn_tracker:
@@ -180,7 +184,7 @@ class TurnTraceObserver(BaseObserver):
logger.debug(f"Ended tracing for Turn {turn_number}") logger.debug(f"Ended tracing for Turn {turn_number}")
def get_current_turn_context(self) -> Optional[SpanContext]: def get_current_turn_context(self) -> Optional["SpanContext"]:
"""Get the span context for the current turn. """Get the span context for the current turn.
This can be used by services to create child spans. This can be used by services to create child spans.
@@ -190,7 +194,7 @@ class TurnTraceObserver(BaseObserver):
return self._current_span.get_span_context() return self._current_span.get_span_context()
def get_turn_context(self, turn_number: int) -> Optional[SpanContext]: def get_turn_context(self, turn_number: int) -> Optional["SpanContext"]:
"""Get the span context for a specific turn. """Get the span context for a specific turn.
This can be used by services to create child spans. This can be used by services to create child spans.

View File

@@ -1 +1 @@
-e ".[anthropic,aws,google,langchain,tracing]" -e ".[anthropic,aws,google,langchain]"