11"""Logging configuration utilities."""
22
33import logging
4+ import re
45import sys
56from typing import Literal
67
78
9+ class HealthcheckLogFilter (logging .Filter ):
10+ """Filter to suppress access logs for healthcheck endpoints."""
11+
12+ HEALTHCHECK_PATTERN = re .compile (r'"[A-Z]+\s+/(health|ready)(\?[^\s]*)?\s+HTTP/' )
13+
14+ def filter (self , record : logging .LogRecord ) -> bool :
15+ """Return False to drop healthcheck logs, True to keep others."""
16+ message = record .getMessage ()
17+ return not self .HEALTHCHECK_PATTERN .search (message )
18+
19+
820def configure_logging (
921 level : str = "INFO" ,
1022 log_format : Literal ["text" , "json" ] = "text" ,
@@ -59,6 +71,9 @@ def configure_logging(
5971 else :
6072 _configure_text_logging (numeric_level )
6173
74+ # Apply healthcheck log filter to uvicorn access logger
75+ _configure_access_log_filter ()
76+
6277
6378def _configure_text_logging (level : int ) -> None :
6479 """Configure standard text-based logging."""
@@ -76,3 +91,9 @@ def _configure_text_logging(level: int) -> None:
7691 logging .getLogger ("httpx" ).setLevel (logging .WARNING )
7792 logging .getLogger ("httpcore" ).setLevel (logging .WARNING )
7893 logging .getLogger ("asyncio" ).setLevel (logging .WARNING )
94+
95+
96+ def _configure_access_log_filter () -> None :
97+ """Add filter to suppress healthcheck endpoint logs from uvicorn access logs."""
98+ uvicorn_access_logger = logging .getLogger ("uvicorn.access" )
99+ uvicorn_access_logger .addFilter (HealthcheckLogFilter ())
0 commit comments