Files
kennethreitz 90a082a0ac Add structured logging with per-request context (#604)
## Summary

New `enable_logging=True` parameter on `responder.API()` that provides
structured, request-scoped logging using stdlib `logging` and
`contextvars`.

### What it does

- **`api.log`** — always available on every API instance. Works as a
plain logger by default; gains per-request context enrichment with
`enable_logging=True`
- **Per-request context** — every log message automatically includes
request ID, HTTP method, path, and client IP
- **Access logging** — logs every request with timing: `GET /path → 200
(1.2ms)`
- **Request ID** — generates or forwards `X-Request-ID` headers
(supersedes `request_id=True` when both are set)
- **stdlib logging** — works with any existing handler, formatter, or
log aggregator

### Usage

```python
# api.log always works — no setup required
api = responder.API()
api.log.info("starting up")  # plain logger, no context

# With enable_logging=True, log messages get request context automatically
api = responder.API(enable_logging=True)

@api.route("/")
def index(req, resp):
    api.log.info("handling request")
    # => 2026-03-24 12:00:00 [INFO] responder.app — handling request [GET /] [req:abc123] [client:127.0.0.1]
```

For additional loggers in helper modules:

```python
from responder.ext.logging import get_logger
logger = get_logger("myapp.db")
```

### Architecture

- `responder/ext/logging.py` — self-contained module with:
- `LoggingMiddleware` — pure ASGI middleware that sets contextvars and
logs access
- `RequestContextFilter` — logging filter that injects context into
records
  - `RequestContext` — read-only access to current request metadata
  - `get_logger()` / `setup_logging()` — convenience functions
- `api.log` — always a valid logger; context-aware when
`enable_logging=True`, plain stdlib logger otherwise
- Wired into `API.__init__` via the `enable_logging` parameter

### Files

- `responder/ext/logging.py` — new module
- `responder/api.py` — added `enable_logging` parameter and `api.log`
- `tests/test_logging.py` — 9 tests
- `docs/source/tour.rst` — new Structured Logging section
- `docs/source/index.rst` — added to feature list

## Test plan
- [x] 9 logging tests pass
- [x] Full suite: 208 passed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:22:57 -04:00
..
2018-10-11 12:59:27 -04:00
2018-10-11 12:59:27 -04:00