refactor: add structured_log utility to eliminate logging boilerplate

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Justin Visser 2026-02-26 21:31:32 +01:00
parent 7736cab141
commit 6b47b56867
2 changed files with 95 additions and 1 deletions

View file

@ -7,7 +7,8 @@ from unittest.mock import AsyncMock
from fastapi.testclient import TestClient
from app.logging_config import JsonLogFormatter, parse_redact_fields
from app.logging_config import ConsoleLogFormatter, JsonLogFormatter, parse_redact_fields
from app.logging_utils import structured_log
from app.main import app
from app.http.middleware import REQUEST_ID_HEADER, parse_skip_paths
@ -53,3 +54,67 @@ def test_parse_skip_paths_trims_and_discards_empty_segments() -> None:
"/healthz",
"/api/v1/metrics",
)
# --- structured_log tests ---
def _capture_structured_log(caplog, level, event, **fields):
"""Helper: call structured_log and return the captured LogRecord."""
logger = logging.getLogger("tests.structured")
with caplog.at_level(logging.DEBUG, logger="tests.structured"):
structured_log(logger, level, event, **fields)
return caplog.records[-1]
def test_structured_log_json_formatter_uses_event_as_message(caplog) -> None:
record = _capture_structured_log(caplog, "info", "ingestion.run_started", user_id=42)
formatter = JsonLogFormatter(redact_fields=set())
payload = json.loads(formatter.format(record))
assert payload["event"] == "ingestion.run_started"
assert payload["user_id"] == 42
def test_structured_log_console_formatter(caplog) -> None:
record = _capture_structured_log(caplog, "warning", "export.failed", scholar_id=7)
formatter = ConsoleLogFormatter(redact_fields=set())
output = formatter.format(record)
assert "export.failed" in output
assert "scholar_id=7" in output
def test_structured_log_strips_metric_fields(caplog) -> None:
record = _capture_structured_log(
caplog,
"info",
"scrape.complete",
metric_name="articles_scraped",
metric_value=15,
scholar_id=3,
)
formatter = JsonLogFormatter(redact_fields=set())
payload = json.loads(formatter.format(record))
assert "metric_name" not in payload
assert "metric_value" not in payload
assert payload["scholar_id"] == 3
def test_structured_log_extra_fields_in_output(caplog) -> None:
record = _capture_structured_log(
caplog,
"info",
"scholar.created",
user_id=1,
scholar_id=99,
scholar_name="Ada Lovelace",
)
formatter = JsonLogFormatter(redact_fields=set())
payload = json.loads(formatter.format(record))
assert payload["event"] == "scholar.created"
assert payload["user_id"] == 1
assert payload["scholar_id"] == 99
assert payload["scholar_name"] == "Ada Lovelace"