Files

110 lines
4.0 KiB
Markdown

# 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.