Skip to content

Commit 7423224

Browse files
swissmoclaude
andcommitted
debug: add temporary diagnostics for the live filter-not-firing report
A SHA-pinned override (ruling out any git/uv caching explanation) still shows the unfiltered ERROR traceback in the live embedded server, and StatelessSessionLogFilter (unrelated, pre-existing-pattern logic) isn't suppressing "Terminating session: None" there either -- so something is preventing install_sdk_log_filters() from taking effect in that specific deployment, for a reason not yet identified from reading the code or reproducing locally. Two temporary WARNING-level log lines (visible without changing log level): - install_sdk_log_filters() logs each target logger's filter count right after installing, so we don't have to wait for a real disconnect race to see whether the filters actually attached. - SessionDisconnectLogFilter.filter() logs the exact type/module/repr of whatever it sees in exc_info, and how it classified it, whenever it's invoked on a matching record -- proving whether the filter runs at all, and if so, exactly what it's failing to recognize. Marked TEMPORARY; remove once the live mismatch is diagnosed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 37ab2af commit 7423224

1 file changed

Lines changed: 29 additions & 1 deletion

File tree

src/ha_mcp/log_filters.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
from fastmcp.exceptions import ToolError
2121
from pydantic import ValidationError as PydanticValidationError
2222

23+
_diag_logger = logging.getLogger(__name__)
24+
2325

2426
class StatelessSessionLogFilter(logging.Filter):
2527
"""Suppress the routine 'Terminating session: None' log from the MCP SDK.
@@ -135,7 +137,22 @@ def filter(self, record: logging.LogRecord) -> bool:
135137
return True
136138

137139
err = record.exc_info[1]
138-
if err is None or not _is_only_closed_resource_errors(err):
140+
classified = err is not None and _is_only_closed_resource_errors(err)
141+
# TEMPORARY DIAGNOSTIC (2026-08-24, remove once the live install/
142+
# classification mismatch reported against this branch is found):
143+
# proves whether this filter is even invoked in the deployment where
144+
# the demotion isn't showing up, and if so, exactly what exception
145+
# shape it saw and how it classified it.
146+
_diag_logger.warning(
147+
"SessionDisconnectLogFilter saw exc_info on %s: type=%r module=%r "
148+
"repr=%.200r classified=%s",
149+
record.name,
150+
type(err).__name__,
151+
type(err).__module__,
152+
err,
153+
classified,
154+
)
155+
if not classified:
139156
return True
140157

141158
record.msg = (
@@ -189,3 +206,14 @@ def install_sdk_log_filters() -> None:
189206
_add_filter_once("mcp.server.streamable_http", StatelessSessionLogFilter)
190207
_add_filter_once("mcp.server.streamable_http_manager", SessionDisconnectLogFilter)
191208
_add_filter_once("fastmcp.server.server", ToolValidationLogFilter)
209+
# TEMPORARY DIAGNOSTIC (2026-08-24, remove once the live install/
210+
# classification mismatch reported against this branch is found): proves
211+
# at startup -- without waiting for a real disconnect race -- whether
212+
# each target logger actually ends up carrying its filter.
213+
_diag_logger.warning(
214+
"install_sdk_log_filters completed: streamable_http=%d "
215+
"streamable_http_manager=%d fastmcp.server.server=%d",
216+
len(logging.getLogger("mcp.server.streamable_http").filters),
217+
len(logging.getLogger("mcp.server.streamable_http_manager").filters),
218+
len(logging.getLogger("fastmcp.server.server").filters),
219+
)

0 commit comments

Comments
 (0)