mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
fix(logging): keep transformed server failures and config JSON mode on the error threshold
When a failure callback rewrites a malformed key rejection into a non-401 response, the proxy now also logs that response at ERROR on stderr, after the WARNING that describes the malformed key. The JSON handler installed by litellm_settings.json_logs carries the LITELLM_LOG level like the JSON_LOGS handler, so LITELLM_LOG=ERROR hides warnings in both JSON modes.
This commit is contained in:
parent
6646bb4319
commit
4c8e9d78dc
4 changed files with 34 additions and 7 deletions
|
|
@ -690,6 +690,7 @@ def _turn_on_json():
|
|||
- Adds a JSON formatter to all loggers
|
||||
"""
|
||||
handler: Final = LevelRoutingStreamHandler()
|
||||
handler.setLevel(numeric_level)
|
||||
handler.setFormatter(JsonFormatter())
|
||||
_initialize_loggers_with_handler(handler)
|
||||
# Set up exception handlers
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ class UserAPIKeyAuthExceptionHandler:
|
|||
request=request,
|
||||
use_x_forwarded_for=general_settings.get("use_x_forwarded_for") is True,
|
||||
)
|
||||
log_extra: Final = {"requester_ip": requester_ip}
|
||||
is_invalid_virtual_key: Final = is_invalid_virtual_key_error(e)
|
||||
is_quiet_log: Final = is_invalid_virtual_key and not litellm.log_client_error_tracebacks
|
||||
logger: Final = verbose_proxy_stdout_logger if is_quiet_log else verbose_proxy_logger
|
||||
|
|
@ -159,7 +160,7 @@ class UserAPIKeyAuthExceptionHandler:
|
|||
e,
|
||||
requester_ip,
|
||||
exc_info=True if litellm.log_client_error_tracebacks or not is_expected_client_error(e) else None,
|
||||
extra={"requester_ip": requester_ip},
|
||||
extra=log_extra,
|
||||
)
|
||||
|
||||
# Log this exception to OTEL, Datadog etc. Reuse the identity resolved
|
||||
|
|
@ -207,4 +208,12 @@ class UserAPIKeyAuthExceptionHandler:
|
|||
if transformed_exception is not None:
|
||||
e = transformed_exception
|
||||
|
||||
raise mark_invalid_virtual_key_error(_as_proxy_exception(e), is_invalid_virtual_key)
|
||||
final_exception: Final = mark_invalid_virtual_key_error(_as_proxy_exception(e), is_invalid_virtual_key)
|
||||
if is_quiet_log and str(final_exception.code) != str(status.HTTP_401_UNAUTHORIZED):
|
||||
verbose_proxy_logger.error(
|
||||
"litellm.proxy.proxy_server.user_api_key_auth(): Exception occured - %s\nRequester IP Address:%s",
|
||||
final_exception,
|
||||
requester_ip,
|
||||
extra=log_extra,
|
||||
)
|
||||
raise final_exception
|
||||
|
|
|
|||
|
|
@ -882,7 +882,7 @@ async def test_handle_authentication_error_keeps_unexpected_source_traceback_aft
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_authentication_error_does_not_preserve_invalid_virtual_key_marker_for_callback_503(caplog):
|
||||
async def test_handle_authentication_error_logs_callback_503_at_error_level_without_the_marker(caplog):
|
||||
handler = UserAPIKeyAuthExceptionHandler()
|
||||
transformed_exception = HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
|
|
@ -895,11 +895,12 @@ async def test_handle_authentication_error_does_not_preserve_invalid_virtual_key
|
|||
)
|
||||
|
||||
records = _auth_failure_records(caplog)
|
||||
assert len(records) == 1
|
||||
assert records[0].name == verbose_proxy_stdout_logger.name
|
||||
assert records[0].levelno == logging.WARNING
|
||||
assert records[0].exc_info is None
|
||||
assert [(r.name, r.levelno, r.exc_info) for r in records] == [
|
||||
(verbose_proxy_stdout_logger.name, logging.WARNING, None),
|
||||
(verbose_proxy_logger.name, logging.ERROR, None),
|
||||
]
|
||||
assert "LiteLLM Virtual Key expected" in records[0].getMessage()
|
||||
assert "Authentication service temporarily unavailable" in records[1].getMessage()
|
||||
assert exc_info.value.message == "Authentication service temporarily unavailable"
|
||||
assert exc_info.value.code == str(status.HTTP_503_SERVICE_UNAVAILABLE)
|
||||
assert not hasattr(exc_info.value, "_litellm_invalid_virtual_key_error")
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from typing import List
|
|||
import pytest
|
||||
|
||||
import litellm
|
||||
import litellm._logging as litellm_logging
|
||||
from litellm._logging import (
|
||||
_COLOR_LOG_FORMAT,
|
||||
_PLAIN_LOG_FORMAT,
|
||||
|
|
@ -986,6 +987,21 @@ def test_error_threshold_suppresses_invalid_key_warning_like_ordinary_warnings(c
|
|||
assert "ordinary proxy error" in err
|
||||
|
||||
|
||||
def test_config_json_mode_handler_honors_the_litellm_log_threshold(monkeypatch, capsys):
|
||||
monkeypatch.setattr(litellm_logging, "numeric_level", logging.ERROR)
|
||||
_turn_on_json()
|
||||
|
||||
verbose_proxy_stdout_logger.warning("invalid virtual key")
|
||||
verbose_proxy_logger.warning("ordinary proxy warning")
|
||||
verbose_proxy_logger.error("ordinary proxy error")
|
||||
|
||||
out, err = capsys.readouterr()
|
||||
assert out == ""
|
||||
assert "invalid virtual key" not in err
|
||||
assert "ordinary proxy warning" not in err
|
||||
assert "ordinary proxy error" in err
|
||||
|
||||
|
||||
def test_ordinary_proxy_records_still_propagate_to_root_handler():
|
||||
root_logger = logging.getLogger()
|
||||
root_stream = StringIO()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue