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