docs(observability): add services/api README; update ml/serving + recommender docs (#18)

- services/api/README.md: new — contract, middleware stack, background
  tasks, config table (LOG_LEVEL, SENTRY_DSN), health story, extraction
  criteria
- ml/serving/README.md: add Observability section (structlog JSON,
  traceparent → trace_id binding), add SENTRY_DSN + ENV to config table
- services/recommender/README.md: fix policy table — egreedy-v2 is
  active (#99), egreedy-v1 is shadow

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 03:41:39 +00:00
parent c4960d0601
commit b554970032
3 changed files with 100 additions and 3 deletions

View File

@@ -47,6 +47,12 @@ On startup, `nats_consumer.py` registers two durable push consumers against NATS
**Disabled** when `NATS_URL` is unset (default in local dev without NATS). No import of `nats-py` occurs in that case.
## Observability
Logs are structured JSON via **structlog**. Every line includes `level`, `logger`, `timestamp`, and — when a W3C `traceparent` header is present on the incoming request — `trace_id` bound via Python `contextvars`, so all log lines within a request carry the same trace ID as the upstream API call.
Sentry error capture is active when `SENTRY_DSN` is set.
## Config
| Env var | Default | Description |
@@ -58,6 +64,8 @@ On startup, `nats_consumer.py` registers two durable push consumers against NATS
| `NATS_DURABLE_PREFIX` | `feature-pipeline` | Prefix for durable consumer names |
| `NATS_MAX_DELIVER` | `5` | Max redelivery attempts before dropping |
| `DEFAULT_PROMPT_VERSION` | `v1` | Fallback prompt version for `/generate` |
| `ENV` | `development` | Environment label (passed to Sentry) |
| `SENTRY_DSN` | `` | Sentry DSN; empty = Sentry disabled |
## Health story