This commit is contained in:
Vansh Singh 2026-11-07 05:52:20 +00:00 • committed by GitHub
commit a096843d2e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 88 additions and 2 deletions

View file

@ -192,6 +192,7 @@ standard_logging_payload_excluded_fields: Optional[List[str]] = (
None # Fields to exclude from StandardLoggingPayload before callbacks receive it
)
log_raw_request_response: bool = False
max_raw_request_body_log_chars: Optional[int] = None
log_client_error_tracebacks: bool = False
log_auth_failure_key_identity: bool = False
request_correlation_in_logs: bool = False

View file

@ -2199,6 +2199,7 @@ MICROSOFT_USER_LAST_NAME_ATTRIBUTE: Final = str(os.getenv("MICROSOFT_USER_LAST_N
# Maximum payload size (in bytes) to fully serialize for DEBUG logging.
# Payloads larger than this are truncated to avoid multi-second json.dumps blocking the response.
MAX_PAYLOAD_SIZE_FOR_DEBUG_LOG: Final = get_env_int("MAX_PAYLOAD_SIZE_FOR_DEBUG_LOG", 102400) # 100 KB
MAX_RAW_REQUEST_BODY_LOG_CHARS: Final = get_env_int("MAX_RAW_REQUEST_BODY_LOG_CHARS", 102400) # 100 KB
# Policy template enrichment
MAX_COMPETITOR_NAMES: Final = get_env_int("MAX_COMPETITOR_NAMES", 100)

View file

@ -49,6 +49,7 @@ from litellm.constants import (
INTERNAL_CALLBACK_NAMES,
KUBERNETES_POD_ROUTING_KEY,
LITELLM_LOGGING_NO_UPSTREAM_LLM_CALL,
MAX_RAW_REQUEST_BODY_LOG_CHARS,
PROVIDER_REQUEST_ID_HEADERS,
REALTIME_METERED_USAGE_KEY,
REDACTED_BY_LITELLM,
@ -1841,8 +1842,17 @@ class Logging(LiteLLMLoggingBaseClass):
else:
verbose_logger.debug("\x1b[92m%s\x1b[0m\n", curl_command)
def _get_max_raw_request_body_log_chars(self) -> int:
if getattr(litellm, "max_raw_request_body_log_chars", None) is not None:
return cast(int, litellm.max_raw_request_body_log_chars)
return MAX_RAW_REQUEST_BODY_LOG_CHARS
def _get_request_body(self, data: dict) -> str:
return str(data)
body: Final = str(data)
max_chars: Final = self._get_max_raw_request_body_log_chars()
if len(body) > max_chars:
return f"<{len(body)} chars omitted, over MAX_RAW_REQUEST_BODY_LOG_CHARS={max_chars}>"
return body
def _get_request_curl_command(self, api_base: str, headers: dict | None, additional_args: dict, data: dict) -> str:
masked_api_base: Final = self._get_masked_api_base(api_base)
@ -1858,7 +1868,10 @@ class Logging(LiteLLMLoggingBaseClass):
if additional_args.get("request_str", None) is not None:
# print the sagemaker / bedrock client request
curl_command = "\nRequest Sent from LiteLLM:\n"
request_str: Final = additional_args.get("request_str", "")
request_str: str = str(additional_args.get("request_str", ""))
max_chars: Final = self._get_max_raw_request_body_log_chars()
if len(request_str) > max_chars:
request_str = f"<{len(request_str)} chars omitted, over MAX_RAW_REQUEST_BODY_LOG_CHARS={max_chars}>"
curl_command += request_str
return curl_command

View file

@ -8711,6 +8711,77 @@ def test_pre_call_redacts_and_masks_raw_request(logging_obj):
assert "key=*****" in raw_api_base
def test_pre_call_omits_raw_request_body_over_size_limit(logging_obj, monkeypatch):
"""Redacting an oversized raw request blocks the event loop, so the body is omitted from the curl command."""
monkeypatch.setattr("litellm.litellm_core_utils.litellm_logging.MAX_RAW_REQUEST_BODY_LOG_CHARS", 100)
metadata = {"user_api_key_alias": "qa-key"}
logging_obj.model_call_details["litellm_params"] = {"metadata": metadata}
logging_obj.log_raw_request_response = True
body = {"messages": [{"role": "user", "content": "LONG-PROMPT-CONTENT " * 20}]}
logging_obj.pre_call(
input="hi",
api_key="",
additional_args={
"api_base": "https://api.openai.com/v1/chat/completions",
"headers": {},
"complete_input_dict": body,
},
)
raw_request = metadata["raw_request"]
assert "LONG-PROMPT-CONTENT" not in raw_request
assert "chars omitted, over MAX_RAW_REQUEST_BODY_LOG_CHARS=100" in raw_request
assert "https://api.openai.com/v1/chat/completions" in raw_request
assert logging_obj.model_call_details["raw_request_typed_dict"]["raw_request_body"] == body
def test_pre_call_omits_request_str_over_size_limit(logging_obj, monkeypatch):
"""Oversized request_str (e.g. from Bedrock or SageMaker) is also omitted from raw request logging."""
monkeypatch.setattr("litellm.litellm_core_utils.litellm_logging.MAX_RAW_REQUEST_BODY_LOG_CHARS", 100)
metadata = {"user_api_key_alias": "qa-key"}
logging_obj.model_call_details["litellm_params"] = {"metadata": metadata}
logging_obj.log_raw_request_response = True
long_request_str = "BEDROCK-RAW-PAYLOAD-" * 20
logging_obj.pre_call(
input="hi",
api_key="",
additional_args={
"api_base": "https://bedrock-runtime.us-east-1.amazonaws.com",
"headers": {},
"request_str": long_request_str,
},
)
raw_request = metadata["raw_request"]
assert "BEDROCK-RAW-PAYLOAD-" not in raw_request
assert "chars omitted, over MAX_RAW_REQUEST_BODY_LOG_CHARS=100" in raw_request
def test_pre_call_includes_request_body_under_size_limit(logging_obj, monkeypatch):
"""Normal sized payloads under the limit are fully included and redacted."""
monkeypatch.setattr("litellm.litellm_core_utils.litellm_logging.MAX_RAW_REQUEST_BODY_LOG_CHARS", 1000)
metadata = {"user_api_key_alias": "qa-key"}
logging_obj.model_call_details["litellm_params"] = {"metadata": metadata}
logging_obj.log_raw_request_response = True
body = {"messages": [{"role": "user", "content": "short prompt"}]}
logging_obj.pre_call(
input="hi",
api_key="",
additional_args={
"api_base": "https://api.openai.com/v1/chat/completions",
"headers": {},
"complete_input_dict": body,
},
)
raw_request = metadata["raw_request"]
assert "short prompt" in raw_request
assert "chars omitted" not in raw_request
_PRIVATE_RAW_REQUEST_ARGS: Final = {
"api_base": "https://api.openai.com/v1/chat/completions",
"headers": {},