Skip to content

Validate settings and normalize log levels; enrich structured logging and clear request context; add tests#2

Open
code404c wants to merge 1 commit intomainfrom
codex/refine-settings-and-logging-for-stability
Open

Validate settings and normalize log levels; enrich structured logging and clear request context; add tests#2
code404c wants to merge 1 commit intomainfrom
codex/refine-settings-and-logging-for-stability

Conversation

@code404c
Copy link
Copy Markdown
Owner

Motivation

  • Prevent invalid runtime configuration by validating numeric settings and normalizing log_level early.
  • Ensure structured logs always include stable context fields to avoid missing keys in downstream systems.
  • Avoid ContextVar leakage across requests in long-lived threads or coroutines by explicitly clearing request context after each request.

Description

  • Added Field constraints to port, sync_wait_timeout_s, sqlite_busy_timeout_ms, and stt_timeout_seconds in Settings to enforce valid ranges.
  • Implemented a @field_validator normalize_log_level to canonicalize and validate log_level (including alias mapping for WARN/FATAL).
  • Added _record_patch to inject service, request_id, and job_id into each structured log record and wired it into loguru via logger.configure(patcher=...).
  • Introduced clear_request_context() and ensured the FastAPI request middleware calls it in a finally block to clear context after each request.
  • Added unit tests covering configuration validation and normalization, logging record patch behavior and context clearing, and an integration test ensuring the request context is cleared after handling /health.

Testing

  • Ran unit tests under tests/core/test_config.py which validate Settings field constraints and log_level normalization, and they passed.
  • Ran unit tests under tests/core/test_logging.py which exercise InterceptHandler, _record_patch, bind_request_context, and clear_request_context, and they passed.
  • Ran gateway tests including tests/gateway/test_app.py which verifies the request middleware clears context after requests, and they passed.

Codex Task

Copilot AI review requested due to automatic review settings March 14, 2026 16:07
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens runtime configuration and improves structured logging consistency across services by validating key Settings fields, normalizing log_level, enriching Loguru records with stable context fields, and clearing per-request ContextVar state in the gateway middleware; it also adds unit/integration coverage for these behaviors.

Changes:

  • Added Pydantic Field constraints for numeric settings and a log_level normalizer/validator in Settings.
  • Added a Loguru record patcher to inject service, request_id, and job_id into structured logs.
  • Introduced clear_request_context() and invoked it from the FastAPI middleware; added tests for config/logging and a gateway request-context test.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/minutes_core/config.py Adds numeric constraints and normalizes/validates log_level early.
src/minutes_core/logging.py Introduces _record_patch and clear_request_context; wires patcher into Loguru configuration.
src/minutes_gateway/app.py Ensures request ContextVars are cleared via middleware finally.
tests/core/test_config.py New unit tests for settings validation and log level normalization.
tests/core/test_logging.py Adds tests for record patching and context clearing.
tests/gateway/test_app.py Adds an integration-style test intended to assert request context is cleared after /health.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines 83 to +89
bind_request_context(request_id=request.state.request_id)
response = await call_next(request)
response.headers["x-request-id"] = request.state.request_id
return response
try:
response = await call_next(request)
response.headers["x-request-id"] = request.state.request_id
return response
finally:
clear_request_context()
Comment on lines +7 to +14
from minutes_core.logging import (
InterceptHandler,
_record_patch,
bind_request_context,
clear_request_context,
job_id_var,
request_id_var,
)
Comment thread tests/gateway/test_app.py
Comment on lines +64 to +73
"""请求结束后应清理 ContextVar,避免跨请求上下文残留。"""
from minutes_core.logging import job_id_var, request_id_var

with gateway_harness_factory() as harness:
response = harness.client.get("/health", headers={"x-request-id": "req-cleanup"})
assert response.status_code == 200
assert response.headers["x-request-id"] == "req-cleanup"

assert request_id_var.get() is None
assert job_id_var.get() is None
valid_levels = {"TRACE", "DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL"}
if normalized not in valid_levels:
valid = ", ".join(sorted(valid_levels))
raise ValueError(f"Invalid MINUTES_LOG_LEVEL={value!r}. Expected one of: {valid}")
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b70aa91dea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +88 to +89
finally:
clear_request_context()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Defer context cleanup until response has finished

Clearing request_id_var/job_id_var in this finally runs immediately after call_next() returns a Response, not after the response body is fully sent, so logs emitted during response streaming (for example the SSE path returned by stream_job_events) or later middleware/server logging for that request lose correlation IDs and get null context fields. Move cleanup to a point that executes after response completion (e.g., ASGI send completion or a response-finalization hook) so per-request logs stay traceable through the full lifecycle.

Useful? React with 👍 / 👎.

code404c added a commit that referenced this pull request Mar 15, 2026
…d actor job_id binding

Cherry-pick improvements from codex/refine-settings-and-logging-for-stability (PR #2),
rejecting all reverts. Adds _record_patch for consistent structured log fields,
clear_request_context to prevent cross-request leaks, Field constraints on config,
log_level normalization (WARN→WARNING, FATAL→CRITICAL), and bind_request_context
in all Dramatiq actors for job_id traceability.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants