From 431c86cbf57d6ed07a28e439abb5fc6586930426 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Thu, 12 Dec 2024 12:18:10 -0800 Subject: [PATCH] (feat) add `error_code`, `error_class`, `llm_provider` to `StandardLoggingPayload` (#7200) * add StandardLoggingPayloadErrorInformation to error * test_get_error_information --- litellm/litellm_core_utils/litellm_logging.py | 21 +++++++++++ litellm/types/utils.py | 7 ++++ .../test_standard_logging_payload.py | 35 +++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index 35a9b12a905..e6bdbf74515 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -49,6 +49,7 @@ from litellm.types.utils import ( StandardLoggingModelCostFailureDebugInformation, StandardLoggingModelInformation, StandardLoggingPayload, + StandardLoggingPayloadErrorInformation, StandardLoggingPayloadStatus, StandardPassThroughResponseObject, TextCompletionResponse, @@ -2729,6 +2730,21 @@ class StandardLoggingPayloadSetup: return api_base.rstrip("/") return api_base + @staticmethod + def get_error_information( + original_exception: Optional[Exception], + ) -> StandardLoggingPayloadErrorInformation: + error_status: str = str(getattr(original_exception, "status_code", "")) + error_class: str = ( + str(original_exception.__class__.__name__) if original_exception else "" + ) + _llm_provider_in_exception = getattr(original_exception, "llm_provider", "") + return StandardLoggingPayloadErrorInformation( + error_code=error_status, + error_class=error_class, + llm_provider=_llm_provider_in_exception, + ) + @staticmethod def get_response_time( start_time_float: float, @@ -2863,6 +2879,10 @@ def get_standard_logging_object_payload( ) response_cost: float = kwargs.get("response_cost", 0) or 0.0 + error_information = StandardLoggingPayloadSetup.get_error_information( + original_exception=original_exception, + ) + ## get final response object ## final_response_obj = StandardLoggingPayloadSetup.get_final_response_obj( response_obj=response_obj, @@ -2903,6 +2923,7 @@ def get_standard_logging_object_payload( hidden_params=clean_hidden_params, model_map_information=model_cost_information, error_str=error_str, + error_information=error_information, response_cost_failure_debug_info=kwargs.get( "response_cost_failure_debug_information" ), diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 16b545fafff..a050737982c 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -1545,6 +1545,12 @@ class StandardLoggingModelCostFailureDebugInformation(TypedDict, total=False): custom_pricing: Optional[bool] +class StandardLoggingPayloadErrorInformation(TypedDict, total=False): + error_code: Optional[str] + error_class: Optional[str] + llm_provider: Optional[str] + + StandardLoggingPayloadStatus = Literal["success", "failure"] @@ -1579,6 +1585,7 @@ class StandardLoggingPayload(TypedDict): messages: Optional[Union[str, list, dict]] response: Optional[Union[str, list, dict]] error_str: Optional[str] + error_information: Optional[StandardLoggingPayloadErrorInformation] model_parameters: dict hidden_params: StandardLoggingHiddenParams diff --git a/tests/logging_callback_tests/test_standard_logging_payload.py b/tests/logging_callback_tests/test_standard_logging_payload.py index 8f5424474e7..29dd1454bd2 100644 --- a/tests/logging_callback_tests/test_standard_logging_payload.py +++ b/tests/logging_callback_tests/test_standard_logging_payload.py @@ -380,6 +380,41 @@ def test_strip_trailing_slash(): ) +def test_get_error_information(): + """Test get_error_information with different types of exceptions""" + + # Test with None + result = StandardLoggingPayloadSetup.get_error_information(None) + print("error_information", json.dumps(result, indent=2)) + assert result["error_code"] == "" + assert result["error_class"] == "" + assert result["llm_provider"] == "" + + # Test with a basic Exception + basic_exception = Exception("Test error") + result = StandardLoggingPayloadSetup.get_error_information(basic_exception) + print("error_information", json.dumps(result, indent=2)) + assert result["error_code"] == "" + assert result["error_class"] == "Exception" + assert result["llm_provider"] == "" + + # Test with litellm exception from provider + litellm_exception = litellm.exceptions.RateLimitError( + message="Test error", + llm_provider="openai", + model="gpt-3.5-turbo", + response=None, + litellm_debug_info=None, + max_retries=None, + num_retries=None, + ) + result = StandardLoggingPayloadSetup.get_error_information(litellm_exception) + print("error_information", json.dumps(result, indent=2)) + assert result["error_code"] == "429" + assert result["error_class"] == "RateLimitError" + assert result["llm_provider"] == "openai" + + def test_get_response_time(): """Test get_response_time with different streaming scenarios""" # Test case 1: Non-streaming response