mirror of
https://github.com/mcp-use/mcp-use.git
synced 2026-09-14 18:06:01 +08:00
18f51eddb8
* move: session * move: client * move:config * move: exceptions * move: connectors -> client.connectors * move: task_managers -> client.task_managers * move: observability -> agents.observability * move: middleware -> client.middleware * move: managers -> agents.managers * move: auth -> client.auth * move: adapters -> agents.adapters * test: bc test * test: bc test * chore: remove relative imports * fix tests * chore: update docs * chore: deprecation warnings * chore: fix dangerous non absolute import * fix: remove legacy imports * telemetry
163 lines
5.2 KiB
Python
163 lines
5.2 KiB
Python
"""
|
|
Observability callbacks manager for MCP-use.
|
|
|
|
This module provides a centralized manager for handling observability callbacks
|
|
from various platforms (Langfuse, Laminar, etc.) in a clean and extensible way.
|
|
"""
|
|
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ObservabilityManager:
|
|
"""
|
|
Manages observability callbacks for MCP agents.
|
|
|
|
This class provides a centralized way to collect and manage callbacks
|
|
from various observability platforms (Langfuse, Laminar, etc.).
|
|
"""
|
|
|
|
def __init__(self, custom_callbacks: list | None = None):
|
|
"""
|
|
Initialize the ObservabilityManager.
|
|
|
|
Args:
|
|
custom_callbacks: Optional list of custom callbacks to use instead of defaults.
|
|
"""
|
|
self.custom_callbacks = custom_callbacks
|
|
self._available_handlers = []
|
|
self._handler_names = []
|
|
self._initialized = False
|
|
|
|
def _collect_available_handlers(self) -> None:
|
|
"""Collect all available observability handlers from configured platforms."""
|
|
if self._initialized:
|
|
return
|
|
|
|
# Import handlers lazily to avoid circular imports
|
|
try:
|
|
from .langfuse import langfuse_handler
|
|
|
|
if langfuse_handler is not None:
|
|
self._available_handlers.append(langfuse_handler)
|
|
self._handler_names.append("Langfuse")
|
|
logger.debug("ObservabilityManager: Langfuse handler available")
|
|
except ImportError:
|
|
logger.debug("ObservabilityManager: Langfuse module not available")
|
|
|
|
try:
|
|
from .laminar import laminar_initialized
|
|
|
|
if laminar_initialized:
|
|
# Laminar is initialized with automatic instrumentation only
|
|
self._handler_names.append("Laminar (auto-instrumentation)")
|
|
logger.debug("ObservabilityManager: Laminar auto-instrumentation active")
|
|
except ImportError:
|
|
logger.debug("ObservabilityManager: Laminar module not available")
|
|
|
|
# Future: Add more platforms here...
|
|
|
|
self._initialized = True
|
|
|
|
def get_callbacks(self) -> list:
|
|
"""
|
|
Get the list of callbacks to use.
|
|
|
|
Returns:
|
|
List of callbacks - either custom callbacks if provided,
|
|
or all available observability handlers.
|
|
"""
|
|
# If custom callbacks were provided, use those
|
|
if self.custom_callbacks is not None:
|
|
logger.debug(f"ObservabilityManager: Using {len(self.custom_callbacks)} custom callbacks")
|
|
return self.custom_callbacks
|
|
|
|
# Otherwise, collect and return all available handlers
|
|
self._collect_available_handlers()
|
|
|
|
if self._available_handlers:
|
|
logger.debug(f"ObservabilityManager: Using {len(self._available_handlers)} handlers")
|
|
else:
|
|
logger.debug("ObservabilityManager: No callbacks configured")
|
|
|
|
return self._available_handlers
|
|
|
|
def get_handler_names(self) -> list[str]:
|
|
"""
|
|
Get the names of available handlers.
|
|
|
|
Returns:
|
|
List of handler names (e.g., ["Langfuse", "Laminar"])
|
|
"""
|
|
if self.custom_callbacks is not None:
|
|
# For custom callbacks, try to get their class names
|
|
return [type(cb).__name__ for cb in self.custom_callbacks]
|
|
|
|
self._collect_available_handlers()
|
|
return self._handler_names
|
|
|
|
def has_callbacks(self) -> bool:
|
|
"""
|
|
Check if any callbacks are available.
|
|
|
|
Returns:
|
|
True if callbacks are available, False otherwise.
|
|
"""
|
|
callbacks = self.get_callbacks()
|
|
return len(callbacks) > 0
|
|
|
|
def add_callback(self, callback) -> None:
|
|
"""
|
|
Add a callback to the custom callbacks list.
|
|
|
|
Args:
|
|
callback: The callback to add.
|
|
"""
|
|
if self.custom_callbacks is None:
|
|
self.custom_callbacks = []
|
|
self.custom_callbacks.append(callback)
|
|
logger.debug(f"ObservabilityManager: Added custom callback: {type(callback).__name__}")
|
|
|
|
def clear_callbacks(self) -> None:
|
|
"""Clear all custom callbacks."""
|
|
self.custom_callbacks = []
|
|
logger.debug("ObservabilityManager: Cleared all custom callbacks")
|
|
|
|
def __repr__(self) -> str:
|
|
"""String representation of the ObservabilityManager."""
|
|
handler_names = self.get_handler_names()
|
|
if handler_names:
|
|
return f"ObservabilityManager(handlers={handler_names})"
|
|
return "ObservabilityManager(no handlers)"
|
|
|
|
|
|
# Singleton instance for easy access
|
|
_default_manager = None
|
|
|
|
|
|
def get_default_manager() -> ObservabilityManager:
|
|
"""
|
|
Get the default ObservabilityManager instance.
|
|
|
|
Returns:
|
|
The default ObservabilityManager instance (singleton).
|
|
"""
|
|
global _default_manager
|
|
if _default_manager is None:
|
|
_default_manager = ObservabilityManager()
|
|
return _default_manager
|
|
|
|
|
|
def create_manager(custom_callbacks: list | None = None) -> ObservabilityManager:
|
|
"""
|
|
Create a new ObservabilityManager instance.
|
|
|
|
Args:
|
|
custom_callbacks: Optional list of custom callbacks.
|
|
|
|
Returns:
|
|
A new ObservabilityManager instance.
|
|
"""
|
|
return ObservabilityManager(custom_callbacks=custom_callbacks)
|