Files

4.0 KiB

Logging Guidelines

How logging is done in this project.


Overview

Backend uses structlog integrated with stdlib logging configuration.

Evidence:

  • Logger factory: backend/src/core/logging/logger.py
  • Logging config and processors: backend/src/core/logging/config.py
  • Formatter/JSON pipeline: backend/src/core/logging/formatters.py
  • Request context middleware: backend/src/core/logging/middleware.py
  • Runtime usage examples: backend/src/app.py, backend/src/v1/todo/service.py

Log Levels

Observed level usage:

  • debug: low-level diagnostic events (e.g., JWT success branch)
    • backend/src/v1/users/dependencies.py
  • info: normal lifecycle and business events
    • backend/src/app.py (startup/initialized)
    • backend/src/v1/todo/service.py (todo_created, todo_updated, etc.)
  • warning: recoverable issues, unauthorized attempts, validation problems
    • backend/src/app.py (HTTP and validation warnings)
    • backend/src/v1/todo/service.py (unauthorized operations)
  • error / exception: failures needing investigation
    • backend/src/app.py (logger.exception("Unhandled error"))
    • repositories with logger.exception(...) before re-raise

Structured Logging

Conventions from current setup:

  1. Always obtain logger through core.logging.get_logger(...).
  2. Use structured fields (keyword args / bound context), not string interpolation only.
  3. Request-level context can be attached by RequestContextMiddleware (request_id, method, path, client_ip, user_id) when the middleware is mounted.
  4. JSON output is enabled by default (runtime.log_json = True), with fallback plain formatter supported.

Examples:

  • backend/src/core/logging/middleware.py binds and propagates request context (middleware implementation)
  • backend/src/core/logging/config.py configures processors and handlers
  • backend/tests/integration/test_fastapi_logging_integration.py mounts the middleware in test FastAPI app and asserts context fields in emitted logs

Current wiring note:

  • backend/src/app.py currently does not call app.add_middleware(RequestContextMiddleware); treat middleware context fields as opt-in wiring, not guaranteed global behavior.

What to Log

Log these consistently:

  • Service lifecycle events (startup/shutdown/init failures)
    • backend/src/app.py
    • backend/src/services/base/service_interface.py
  • Security/auth failures and unauthorized access attempts
    • backend/src/v1/users/dependencies.py
    • backend/src/v1/todo/service.py
  • Database or external dependency failures with stable context fields
    • backend/src/v1/*/repository.py patterns
    • backend/src/services/base/{redis.py,supabase.py}

What NOT to Log

Sensitive data should be redacted; avoid raw secrets/tokens/credentials.

Evidence:

  • Sensitive field defaults in backend/src/core/config/settings.py (password, token, authorization, etc.)
  • Redaction processor tests:
    • backend/tests/unit/test_logging_filters.py
    • backend/tests/unit/test_logging_config.py

Avoid logging:

  • Raw access tokens / refresh tokens / cookies
  • Passwords, API keys, secret values
  • Full untrusted payload dumps containing PII

Anti-patterns / Forbidden Patterns

  • Do not use print() in backend runtime code; use project logger APIs.
    • Rule source: backend/AGENTS.md
  • Do not bypass logging config by ad-hoc logger setup in feature modules.
    • Use configure_logging(...) from backend/src/core/logging/config.py.
  • Do not log sensitive fields without redaction.
  • Do not assume request context fields exist unless RequestContextMiddleware is explicitly mounted.

Uncertainties (documented, not invented)

  • This repo has tests for logging behavior and redaction, but no single documented required schema for every log event across all modules (beyond context fields and processor output).
  • core.logging.middleware.register_exception_handlers(...) exists but app-level error handling is primarily in backend/src/app.py; effective production wiring should remain explicit per app bootstrap.