Mirrowel commited on
Commit
10dabd5
·
1 Parent(s): c036ceb

fix(logging): provide raw response in failure logs

Browse files

Previously, streamed API errors could result in incomplete raw response details in failure logs, making debugging challenging.
This update ensures that the full raw response text, including reassembled data from streams, is explicitly captured within the client's error handling.
The failure logger is also updated to accept and prioritize this explicit raw response, guaranteeing comprehensive error logging for all API error types.

src/rotator_library/client.py CHANGED
@@ -544,11 +544,12 @@ class RotatingClient:
544
 
545
  except (StreamedAPIError, litellm.RateLimitError) as e:
546
  last_exception = e
547
- log_failure(api_key=current_key, model=model, attempt=attempt + 1, error=e, request_headers=dict(request.headers) if request else {})
548
  classified_error = classify_error(e)
549
 
550
  # This is the final, robust handler for streamed errors.
551
  error_payload = {}
 
552
  # The actual exception might be wrapped in our StreamedAPIError.
553
  original_exc = getattr(e, 'data', e)
554
 
@@ -562,6 +563,16 @@ class RotatingClient:
562
  except (json.JSONDecodeError, TypeError):
563
  lib_logger.warning("Could not parse JSON details from streamed error exception.")
564
  error_payload = {}
 
 
 
 
 
 
 
 
 
 
565
 
566
  error_details = error_payload.get("error", {})
567
  error_status = error_details.get("status", "")
 
544
 
545
  except (StreamedAPIError, litellm.RateLimitError) as e:
546
  last_exception = e
547
+
548
  classified_error = classify_error(e)
549
 
550
  # This is the final, robust handler for streamed errors.
551
  error_payload = {}
552
+ cleaned_str = None
553
  # The actual exception might be wrapped in our StreamedAPIError.
554
  original_exc = getattr(e, 'data', e)
555
 
 
563
  except (json.JSONDecodeError, TypeError):
564
  lib_logger.warning("Could not parse JSON details from streamed error exception.")
565
  error_payload = {}
566
+
567
+ # Now, log the failure with the extracted raw response.
568
+ log_failure(
569
+ api_key=current_key,
570
+ model=model,
571
+ attempt=attempt + 1,
572
+ error=e,
573
+ request_headers=dict(request.headers) if request else {},
574
+ raw_response_text=cleaned_str
575
+ )
576
 
577
  error_details = error_payload.get("error", {})
578
  error_status = error_details.get("status", "")
src/rotator_library/failure_logger.py CHANGED
@@ -43,13 +43,15 @@ failure_logger = setup_failure_logger()
43
  # Get the main library logger for concise, propagated messages
44
  main_lib_logger = logging.getLogger('rotator_library')
45
 
46
- def log_failure(api_key: str, model: str, attempt: int, error: Exception, request_headers: dict):
47
  """
48
  Logs a detailed failure message to a file and a concise summary to the main logger.
49
  """
50
  # 1. Log the full, detailed error to the dedicated failures.log file
51
- raw_response = None
52
- if hasattr(error, 'response') and hasattr(error.response, 'text'):
 
 
53
  raw_response = error.response.text
54
 
55
  detailed_log_data = {
 
43
  # Get the main library logger for concise, propagated messages
44
  main_lib_logger = logging.getLogger('rotator_library')
45
 
46
+ def log_failure(api_key: str, model: str, attempt: int, error: Exception, request_headers: dict, raw_response_text: str = None):
47
  """
48
  Logs a detailed failure message to a file and a concise summary to the main logger.
49
  """
50
  # 1. Log the full, detailed error to the dedicated failures.log file
51
+ # Prioritize the explicitly passed raw response text, as it may contain
52
+ # reassembled data from a stream that is not available on the exception object.
53
+ raw_response = raw_response_text
54
+ if not raw_response and hasattr(error, 'response') and hasattr(error.response, 'text'):
55
  raw_response = error.response.text
56
 
57
  detailed_log_data = {