feat(log): suppress successful MCP access logs in health filter
Extend `_HealthAccessFilter` to also drop uvicorn access log lines for successful `POST /mcp` requests, in addition to the existing `/live`, `/ready`, and `/metrics` health probes. **Why:** Every Daedalus health poll and tool call hits the single `/mcp` route. Pallas already emits structured `mcp_request_start` / `mcp_request_complete` logs at the agent layer, making the uvicorn access line pure duplication and noise in syslog. **How:** - Replace the simple substring list `_HEALTH_PATHS` with compiled regex patterns (`_HEALTH_PATH_RE`, `_MCP_RE`) for more precise path matching - Add `_SUCCESS_STATUS_RE` to only suppress 1xx/2xx/3xx responses; non-successful responses (4xx, 5xx) still pass through as real signals - Update docstring to document the new suppression rules clearly
This commit is contained in:
@@ -17,6 +17,7 @@ Level conventions (Ouranos Lab — Python services use UPPERCASE):
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
|
||||||
@@ -37,17 +38,33 @@ class _JSONFormatter(logging.Formatter):
|
|||||||
|
|
||||||
|
|
||||||
class _HealthAccessFilter(logging.Filter):
|
class _HealthAccessFilter(logging.Filter):
|
||||||
"""Drop uvicorn access log lines for health/metrics endpoints.
|
"""Drop uvicorn access log lines for routine 2xx/3xx probes.
|
||||||
|
|
||||||
Health check success is the *absence* of errors, not the presence of 200s.
|
Health check success is the *absence* of errors, not the presence of 200s
|
||||||
Logging every HAProxy probe at INFO floods syslog with noise.
|
(Ouranos Red Panda standard). Suppresses:
|
||||||
|
|
||||||
|
* Successful probes to ``/live``, ``/ready``, ``/metrics``
|
||||||
|
* Successful ``POST /mcp`` calls — the MCP endpoint is single-route, every
|
||||||
|
Daedalus health poll and tool call lands there. Pallas already emits
|
||||||
|
its own structured ``mcp_request_start`` / ``mcp_request_complete`` logs
|
||||||
|
at the agent layer, so the uvicorn access line is pure duplication.
|
||||||
|
|
||||||
|
Non-2xx/3xx responses still pass through — a failing probe or a 5xx on
|
||||||
|
``/mcp`` is a real signal.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_HEALTH_PATHS = (" GET /live ", " GET /ready ", " GET /metrics ")
|
_HEALTH_PATH_RE = re.compile(r'"GET /(?:live|ready|metrics)(?:/|\?|\s|")')
|
||||||
|
_MCP_RE = re.compile(r'"POST /mcp(?:/|\?|\s|")')
|
||||||
|
_SUCCESS_STATUS_RE = re.compile(r'" (?:1\d\d|2\d\d|3\d\d)(?:\s|$)')
|
||||||
|
|
||||||
def filter(self, record: logging.LogRecord) -> bool:
|
def filter(self, record: logging.LogRecord) -> bool:
|
||||||
msg = record.getMessage()
|
msg = record.getMessage()
|
||||||
return not any(path in msg for path in self._HEALTH_PATHS)
|
is_routine = bool(
|
||||||
|
self._HEALTH_PATH_RE.search(msg) or self._MCP_RE.search(msg)
|
||||||
|
)
|
||||||
|
if is_routine and self._SUCCESS_STATUS_RE.search(msg):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def setup_logging() -> None:
|
def setup_logging() -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user