diff --git a/agentops/client/api/versions/v3.py b/agentops/client/api/versions/v3.py index 2707d3108..22f22392b 100644 --- a/agentops/client/api/versions/v3.py +++ b/agentops/client/api/versions/v3.py @@ -11,7 +11,7 @@ from agentops.client.api.base import BaseApiClient from agentops.client.api.types import AuthTokenResponse from agentops.exceptions import ApiServerException - +from agentops.logging import logger class V3Client(BaseApiClient): """Client for the AgentOps V3 API""" @@ -33,24 +33,28 @@ def fetch_auth_token(self, api_key: str) -> AuthTokenResponse: r = self.post(path, data, headers) - if r.status_code != 200: - error_msg = f"Authentication failed: {r.status_code}" - try: - error_data = r.json() - if "error" in error_data: - error_msg = f"Authentication failed: {error_data['error']}" - except Exception: - pass - raise ApiServerException(error_msg) - try: - jr = r.json() - token = jr.get("token") - if not token: - raise ApiServerException("No token in authentication response") + if r.status_code != 200: + error_msg = f"Authentication failed: {r.status_code}" + try: + error_data = r.json() + if "error" in error_data: + error_msg = f"{error_data['error']}" + except Exception: + pass + raise ApiServerException(error_msg) - return jr + try: + jr = r.json() + token = jr.get("token") + if not token: + raise ApiServerException("No token in authentication response") + + return jr + except Exception as e: + raise ApiServerException(f"Failed to process authentication response: {str(e)}") except Exception as e: - raise ApiServerException(f"Failed to process authentication response: {str(e)}") + logger.error(f"{str(e)} - Perhaps an invalid API key?") + return None # Add V3-specific API methods here diff --git a/agentops/client/client.py b/agentops/client/client.py index ae6f8e8c6..23549d764 100644 --- a/agentops/client/client.py +++ b/agentops/client/client.py @@ -68,6 +68,8 @@ def init(self, **kwargs): # Prefetch JWT token if enabled # TODO: Move this validation somewhere else (and integrate with self.config.prefetch_jwt_token once we have a solution to that) response = self.api.v3.fetch_auth_token(self.config.api_key) + if response is None: + return # Save the bearer for use with the v4 API self.api.v4.set_auth_token(response["token"]) diff --git a/agentops/legacy/__init__.py b/agentops/legacy/__init__.py index 60226b0dd..a321da2bf 100644 --- a/agentops/legacy/__init__.py +++ b/agentops/legacy/__init__.py @@ -34,7 +34,8 @@ def __init__(self, span: Any, token: Any): def __del__(self): try: - self.span.end() + if self.span is not None: + self.span.end() except: pass @@ -66,9 +67,10 @@ def end_session(self, **kwargs): forces a flush to ensure the span is exported immediately. """ - _set_span_attributes(self.span, kwargs) - self.span.end() - _flush_span_processors() + if self.span is not None: + _set_span_attributes(self.span, kwargs) + self.span.end() + _flush_span_processors() def _create_session_span(tags: Union[Dict[str, Any], List[str], None] = None) -> tuple: @@ -130,7 +132,21 @@ def start_session( if not TracingCore.get_instance().initialized: from agentops import Client # Pass auto_start_session=False to prevent circular dependency - Client().init(auto_start_session=False) + try: + Client().init(auto_start_session=False) + # If initialization failed (returned None), create a dummy session + if not TracingCore.get_instance().initialized: + logger.warning("AgentOps client initialization failed. Creating a dummy session that will not send data.") + # Create a dummy session that won't send data but won't throw exceptions + dummy_session = Session(None, None) + _current_session = dummy_session + return dummy_session + except Exception as e: + logger.warning(f"AgentOps client initialization failed: {str(e)}. Creating a dummy session that will not send data.") + # Create a dummy session that won't send data but won't throw exceptions + dummy_session = Session(None, None) + _current_session = dummy_session + return dummy_session span, ctx, token = _create_session_span(tags) session = Session(span, token) @@ -155,7 +171,7 @@ def _set_span_attributes(span: Any, attributes: Dict[str, Any]) -> None: span: The span to set attributes on attributes: The attributes to set as a dictionary """ - if not attributes or not hasattr(span, "set_attribute"): + if span is None: return for key, value in attributes.items(): @@ -235,9 +251,10 @@ def end_session(session_or_status: Any = None, **kwargs) -> None: if session_or_status is None and kwargs: if _current_session is not None: try: - _set_span_attributes(_current_session.span, kwargs) - _finalize_span(_current_session.span, _current_session.token) - _flush_span_processors() + if _current_session.span is not None: + _set_span_attributes(_current_session.span, kwargs) + _finalize_span(_current_session.span, _current_session.token) + _flush_span_processors() _current_session = None except Exception as e: logger.warning(f"Error ending current session: {e}") @@ -256,9 +273,11 @@ def end_session(session_or_status: Any = None, **kwargs) -> None: if hasattr(session_or_status, 'span') and hasattr(session_or_status, 'token'): try: # Set attributes and finalize the span - _set_span_attributes(session_or_status.span, kwargs) - _finalize_span(session_or_status.span, session_or_status.token) - _flush_span_processors() + if session_or_status.span is not None: + _set_span_attributes(session_or_status.span, kwargs) + if session_or_status.span is not None: + _finalize_span(session_or_status.span, session_or_status.token) + _flush_span_processors() # Clear the global session reference if this is the current session if _current_session is session_or_status: