From d207c73061ca32a25791030f31baf4aa7047c0ba Mon Sep 17 00:00:00 2001 From: Braelyn Boynton Date: Fri, 11 Apr 2025 14:05:44 -0700 Subject: [PATCH 1/3] bad api key doesnt block --- agentops/client/api/versions/v3.py | 38 +++++++++++++++++------------- agentops/client/client.py | 2 ++ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/agentops/client/api/versions/v3.py b/agentops/client/api/versions/v3.py index 2707d3108..c8f19507c 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 AgentOps API key?") + return None # Add V3-specific API methods here diff --git a/agentops/client/client.py b/agentops/client/client.py index 935f21c3c..894995ee7 100644 --- a/agentops/client/client.py +++ b/agentops/client/client.py @@ -45,6 +45,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"]) From e98fea0113fb5fecb63eb2d65094e9d7364f1a12 Mon Sep 17 00:00:00 2001 From: Braelyn Boynton Date: Fri, 11 Apr 2025 14:07:41 -0700 Subject: [PATCH 2/3] remove redundent agentops --- agentops/client/api/versions/v3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agentops/client/api/versions/v3.py b/agentops/client/api/versions/v3.py index c8f19507c..22f22392b 100644 --- a/agentops/client/api/versions/v3.py +++ b/agentops/client/api/versions/v3.py @@ -54,7 +54,7 @@ def fetch_auth_token(self, api_key: str) -> AuthTokenResponse: except Exception as e: raise ApiServerException(f"Failed to process authentication response: {str(e)}") except Exception as e: - logger.error(f"{str(e)} - Perhaps an invalid AgentOps API key?") + logger.error(f"{str(e)} - Perhaps an invalid API key?") return None # Add V3-specific API methods here From 9f4c37a964b8b582794f66d9fca69fa15e6eb2f5 Mon Sep 17 00:00:00 2001 From: Dwij Patel Date: Sat, 12 Apr 2025 03:14:36 +0530 Subject: [PATCH 3/3] fixed for start_session --- agentops/legacy/__init__.py | 48 ++++++++++++++++++++++-------- agentops/sdk/decorators/utility.py | 6 +++- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/agentops/legacy/__init__.py b/agentops/legacy/__init__.py index 0949825d1..1bf085426 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, context, token = _create_session_span(tags) session = Session(span, token) @@ -149,7 +165,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(): @@ -216,9 +232,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: - _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 return @@ -226,14 +243,19 @@ def end_session(session_or_status: Any = None, **kwargs) -> None: # In both cases, we call _finalize_span with the span and token from the Session. # This is the most direct and precise way to end a specific session. if hasattr(session_or_status, 'span') and hasattr(session_or_status, 'token'): - # 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() + # Set attributes if provided + if kwargs: + _set_span_attributes(session_or_status.span, kwargs) + + # End the span + 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: _current_session = None + return def end_all_sessions(): diff --git a/agentops/sdk/decorators/utility.py b/agentops/sdk/decorators/utility.py index 0e3953dfd..3660d17a9 100644 --- a/agentops/sdk/decorators/utility.py +++ b/agentops/sdk/decorators/utility.py @@ -233,6 +233,9 @@ def _record_entity_output(span: trace.Span, result: Any) -> None: def _finalize_span(span: trace.Span, token: Any) -> None: """End the span and detach the context token""" + if span is None: + return + if hasattr(span, "get_span_context") and hasattr(span.get_span_context(), "span_id"): span_id = f"{span.get_span_context().span_id:x}" logger.debug(f"[DEBUG] ENDING span {getattr(span, 'name', 'unknown')} - span_id: {span_id}") @@ -243,7 +246,8 @@ def _finalize_span(span: trace.Span, token: Any) -> None: current_after_end = _get_current_span_info() logger.debug(f"[DEBUG] AFTER span.end() - Current context: {current_after_end}") - context_api.detach(token) + if token is not None: + context_api.detach(token) # Debug info after detaching final_context = _get_current_span_info()