diff --git a/sdks/python/src/opik/api_objects/opik_client.py b/sdks/python/src/opik/api_objects/opik_client.py index 4e5e4a1beb..df0876bccb 100644 --- a/sdks/python/src/opik/api_objects/opik_client.py +++ b/sdks/python/src/opik/api_objects/opik_client.py @@ -67,6 +67,8 @@ def __init__( url_override=host, api_key=api_key, ) + config.check_for_misconfiguration(config_) + self._workspace: str = config_.workspace self._project_name: str = config_.project_name self._flush_timeout: Optional[int] = config_.default_flush_timeout diff --git a/sdks/python/src/opik/config.py b/sdks/python/src/opik/config.py index 4f03e3c7c6..881733f40c 100644 --- a/sdks/python/src/opik/config.py +++ b/sdks/python/src/opik/config.py @@ -10,7 +10,7 @@ from pydantic_settings import BaseSettings, InitSettingsSource from pydantic_settings.sources import ConfigFileSourceMixin -from . import dict_utils +from . import dict_utils, url_helpers from .api_key import opik_api_key PathType = Union[ @@ -250,3 +250,37 @@ def get_from_user_inputs(**user_inputs: Any) -> OpikConfig: cleaned_user_inputs = dict_utils.remove_none_from_dict(user_inputs) return OpikConfig(**cleaned_user_inputs) + + +def check_for_misconfiguration(config: OpikConfig) -> None: + cloud_installation = url_helpers.get_base_url( + config.url_override + ) == url_helpers.get_base_url(OPIK_URL_CLOUD) + localhost_installation = ( + "localhost" in config.url_override + ) # does not detect all OSS installations + workspace_is_default = config.workspace == OPIK_WORKSPACE_DEFAULT_NAME + api_key_configured = config.api_key is not None + + if cloud_installation and (not api_key_configured or workspace_is_default): + print() + LOGGER.error( + "========================\n" + "The workspace and API key must be specified to log data to https://www.comet.com/opik.\n" + "You can use `opik configure` CLI command to configure your environment for logging.\n" + "See the configuration details in the docs: https://www.comet.com/docs/opik/tracing/sdk_configuration.\n" + "==============================\n" + ) + return + + if localhost_installation and not workspace_is_default: + print() + LOGGER.error( + "========================\n" + "Open source installations do not support workspace specification. Only `default` is available.\n" + "See the configuration details in the docs: https://www.comet.com/docs/opik/tracing/sdk_configuration\n" + "If you need advanced workspace management - you may consider using our cloud offer (https://www.comet.com/site/pricing/)\n" + "or contact our team for purchasing and setting up a self-hosted installation.\n" + "==============================\n" + ) + return diff --git a/sdks/python/src/opik/logging_messages.py b/sdks/python/src/opik/logging_messages.py index 506cc316e5..72bebb8b8c 100644 --- a/sdks/python/src/opik/logging_messages.py +++ b/sdks/python/src/opik/logging_messages.py @@ -23,7 +23,7 @@ FAILED_TO_PARSE_OPENAI_STREAM_CONTENT = "Failed to parse openai Stream content. %s" FAILED_TO_PROCESS_MESSAGE_IN_BACKGROUND_STREAMER = ( - "Failed to process %s. Content: %s, Error: %s" + "Failed to process %s.\nContent: %s,\nError: %s" ) HALLUCINATION_DETECTION_FAILED = "Failed hallucination detection" diff --git a/sdks/python/src/opik/message_processing/message_processors.py b/sdks/python/src/opik/message_processing/message_processors.py index df857934f0..c439ab36b5 100644 --- a/sdks/python/src/opik/message_processing/message_processors.py +++ b/sdks/python/src/opik/message_processing/message_processors.py @@ -48,15 +48,19 @@ def process(self, message: messages.BaseMessage) -> None: try: handler(message) - except Exception as exception: - if ( - isinstance(exception, rest_api_core.ApiError) - and exception.status_code == 409 - ): + except rest_api_core.ApiError as exception: + if exception.status_code == 409: # sometimes retry mechanism works in a way that it sends the same request 2 times. # second request is rejected by the backend, we don't want users to an error. return + LOGGER.error( + logging_messages.FAILED_TO_PROCESS_MESSAGE_IN_BACKGROUND_STREAMER, + message_type.__name__, + message, + str(exception), + ) + except Exception as exception: LOGGER.error( logging_messages.FAILED_TO_PROCESS_MESSAGE_IN_BACKGROUND_STREAMER, message_type.__name__,