feat(proxy): honor LITELLM_DISABLE_ACCESS_LOG_PATHS to drop noisy uvicorn access log lines

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Devin AI 2026-09-14 16:39:54 +00:00
parent 9e1ed40db3
commit 2268bbaf5e
2 changed files with 95 additions and 0 deletions

View file

@ -225,6 +225,37 @@ class AccessLogRedactionFilter(logging.Filter):
_access_log_filter: Final = AccessLogRedactionFilter()
def _parse_disabled_access_log_paths(raw: str) -> frozenset[str]:
return frozenset(path for path in (segment.strip() for segment in raw.split(",")) if path)
_DISABLED_ACCESS_LOG_PATHS: Final = _parse_disabled_access_log_paths(os.getenv("LITELLM_DISABLE_ACCESS_LOG_PATHS", ""))
class AccessLogPathFilter(logging.Filter):
"""Drops uvicorn.access records for request paths listed in LITELLM_DISABLE_ACCESS_LOG_PATHS.
uvicorn passes record.args as (client_addr, method, full_path, http_version, status_code).
"""
def __init__(self, disabled_paths: frozenset[str]) -> None:
super().__init__()
self._disabled_paths: Final = disabled_paths
def filter(self, record: logging.LogRecord) -> bool:
if not self._disabled_paths:
return True
if not isinstance(record.args, tuple) or len(record.args) < 3:
return True
full_path: Final = record.args[2]
if not isinstance(full_path, str):
return True
return full_path.partition("?")[0] not in self._disabled_paths
_access_log_path_filter: Final = AccessLogPathFilter(_DISABLED_ACCESS_LOG_PATHS)
def _get_max_string_length_stdout_log() -> int:
"""Read the limit per record so a value loaded later via proxy config
environment_variables is honored."""
@ -664,6 +695,7 @@ def _redact_third_party_loggers() -> None:
logging.getLogger(name).addFilter(_secret_filter)
for name in _REDACTED_ACCESS_LOGGERS:
logging.getLogger(name).addFilter(_access_log_filter)
logging.getLogger(name).addFilter(_access_log_path_filter)
# Call the suppression function

View file

@ -2,6 +2,7 @@ import ast
import asyncio
import json
import logging
import os
import re
import sys
import time
@ -17,6 +18,7 @@ from litellm._logging import (
_MAX_SCRUBBED_ACCESS_ARG,
_PLAIN_LOG_FORMAT,
ALL_LOGGERS,
AccessLogPathFilter,
AccessLogRedactionFilter,
CorrelationContextFilter,
CorrelationPlainFormatter,
@ -26,6 +28,7 @@ from litellm._logging import (
StdoutLogTruncationFilter,
_get_uvicorn_json_log_config,
_initialize_loggers_with_handler,
_parse_disabled_access_log_paths,
_parse_json_logs_env,
_plain_log_format,
_stdout_truncation_marker,
@ -1178,3 +1181,63 @@ def test_access_redaction_survives_the_uvicorn_json_log_config():
lg.handlers[:] = handlers
lg.setLevel(level)
lg.propagate = True
@pytest.mark.parametrize(
"raw, expected",
[
("", frozenset()),
("/health,/metrics", frozenset({"/health", "/metrics"})),
(" /health , /metrics/ ,", frozenset({"/health", "/metrics/"})),
],
)
def test_parse_disabled_access_log_paths(raw, expected):
assert _parse_disabled_access_log_paths(raw) == expected
def test_access_log_path_filter_drops_a_listed_path():
access_log_filter = AccessLogPathFilter(frozenset({"/health/liveliness", "/metrics"}))
assert access_log_filter.filter(_access_record("/health/liveliness")) is False
assert access_log_filter.filter(_access_record("/metrics?format=prometheus")) is False
def test_access_log_path_filter_keeps_an_unlisted_path():
access_log_filter = AccessLogPathFilter(frozenset({"/health/liveliness", "/metrics"}))
assert access_log_filter.filter(_access_record("/v1/chat/completions")) is True
assert access_log_filter.filter(_access_record("/health")) is True
assert access_log_filter.filter(_access_record("/metrics/")) is True
def test_access_log_path_filter_is_a_no_op_when_unset():
assert AccessLogPathFilter(frozenset()).filter(_access_record("/health/liveliness")) is True
def test_access_log_path_filter_keeps_a_record_without_positional_args():
record = logging.LogRecord(
name="uvicorn.access",
level=logging.INFO,
pathname="",
lineno=0,
msg="access line",
args=None,
exc_info=None,
)
assert AccessLogPathFilter(frozenset({"/health/liveliness"})).filter(record) is True
def test_uvicorn_access_logger_drops_a_listed_path_end_to_end(monkeypatch):
monkeypatch.setenv("LITELLM_DISABLE_ACCESS_LOG_PATHS", "/health/liveliness")
access_log_filter = AccessLogPathFilter(
_parse_disabled_access_log_paths(os.environ["LITELLM_DISABLE_ACCESS_LOG_PATHS"])
)
logger = logging.getLogger("uvicorn.access")
assert any(isinstance(f, AccessLogPathFilter) for f in logger.filters)
logger.addFilter(access_log_filter)
try:
assert _emit_access_line("/health/liveliness") == ""
assert _emit_access_line("/v1/chat/completions") != ""
finally:
logger.removeFilter(access_log_filter)