fix(proxy): defer file logging install to create_app()

Move _setup_file_logging() from module import to create_app() so
importing headroom.proxy.server in tests or library contexts no longer
silently attaches a RotatingFileHandler to the user's live proxy.log.

This was discovered via PR #303: running the test suite produced
"Optimization failed: TimeoutError" entries in ~/.headroom/logs/proxy.log
because TestClient instantiations from test_proxy_anthropic_compression_diagnostics.py
inherited the module-level handler.

Add a regression test that imports the server module in a subprocess
and asserts no RotatingFileHandler is attached to the headroom logger.

Refs #303 (review thread).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
SwiftWing21 2026-04-28 15:28:33 -07:00
parent a1f168369d
commit 3d2d894a33
2 changed files with 39 additions and 3 deletions

View file

@ -188,9 +188,6 @@ logger = logging.getLogger("headroom.proxy")
_MULTI_WORKER_CONFIG_ENV = "HEADROOM_PROXY_CONFIG_JSON"
# Always-on file logging to ~/.headroom/logs/ for `headroom perf` analysis
_setup_file_logging()
# Compression pipeline timeout in seconds
@ -1064,6 +1061,12 @@ def create_app(config: ProxyConfig | None = None) -> FastAPI:
from contextlib import asynccontextmanager
# Always-on file logging to ~/.headroom/logs/ for `headroom perf` analysis.
# Installed here (not at module import) so importing headroom.proxy.server
# in tests or library contexts does not silently attach a RotatingFileHandler
# to the user's live proxy.log.
_setup_file_logging()
config = config or ProxyConfig()
proxy = HeadroomProxy(config)

View file

@ -371,6 +371,39 @@ class TestSetupFileLogging:
# Should not raise
_setup_file_logging()
def test_importing_server_does_not_install_file_handler(self, tmp_path: Path) -> None:
"""Importing headroom.proxy.server must NOT attach a RotatingFileHandler
to the user's live proxy.log. The handler is installed by create_app()
instead, so test runs and library imports do not pollute logs.
"""
import os
import subprocess
import sys
import textwrap
script = textwrap.dedent(
"""
import logging
from logging.handlers import RotatingFileHandler
import headroom.proxy.server # noqa: F401
hr = logging.getLogger("headroom")
installed = any(isinstance(h, RotatingFileHandler) for h in hr.handlers)
print("INSTALLED" if installed else "CLEAN")
"""
).strip()
env = {**os.environ, "HEADROOM_WORKSPACE_DIR": str(tmp_path)}
result = subprocess.run(
[sys.executable, "-c", script],
capture_output=True,
text=True,
env=env,
check=True,
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
)
assert result.stdout.strip() == "CLEAN", (
f"Importing headroom.proxy.server attached a file handler: {result.stdout!r}"
)
# ---------------------------------------------------------------------------
# Repro script URL helpers and stats tests