requestLog
constrequestLog: (config?) =>Policy
Defined in: packages/gateway/src/policies/observability/request-log.ts:142
Emit structured JSON logs for every request/response pair.
Captures method, path, status, duration, client IP, user agent, and gateway context (request ID, gateway name, route path). Runs at priority 0 so it wraps the entire pipeline and measures end-to-end latency.
By default, logs are written to console.log as JSON lines. Provide a
custom sink to route logs to an external service (e.g., Logflare,
Datadog, or a Durable Object buffer).
Data boundary: request logs vs analytics
Section titled “Data boundary: request logs vs analytics”Request logs and analytics (@vivero/stoma-analytics) serve
different purposes and deliberately carry different fields.
Request logs (this policy) are for debugging and operational triage. Fields are high-cardinality — grep-friendly, not GROUP BY-friendly:
| Field | Why it’s here |
|---|---|
| requestId | Unique per request — grep to find a single transaction |
| path | Actual URL e.g. /users/42 (high cardinality) |
| clientIp | PII, high cardinality — abuse investigation only |
| userAgent | High cardinality — debug specific client issues |
| spanId | Distributed tracing span correlation |
| requestBody | Deep debugging (opt-in, redactable) |
| responseBody | Deep debugging (opt-in, redactable) |
Overlapping fields (appear in both logs and analytics):
| Field | Why both need it |
|---|---|
| timestamp | Time-series bucketing (analytics) / grep by time (logs) |
| gatewayName | GROUP BY gateway (analytics) / filter logs by gateway |
| routePath | GROUP BY route pattern (analytics) / filter by route |
| method | GROUP BY method (analytics) / filter logs by method |
| statusCode | Error rate dashboards (analytics) / grep errors (logs) |
| durationMs | AVG/P99 latency (analytics) / slow request triage |
| traceId | Dashboard anomaly drill-down → find matching log lines |
Analytics-only fields (NOT in request logs):
| Field | Why only analytics |
|---|---|
| responseSize | SUM bandwidth, detect payload bloat — aggregate only |
| dimensions | Extensible low-cardinality facets for GROUP BY |
Parameters
Section titled “Parameters”config?
Section titled “config?”Custom field extraction, body logging, and sink. All fields optional.
Returns
Section titled “Returns”A Policy at priority 0 (runs first, wraps everything).
Example
Section titled “Example”import { createGateway } from "@vivero/stoma";import { requestLog } from "@vivero/stoma/policies";
// Default structured JSON logging to consolecreateGateway({ policies: [requestLog()], routes: [...],});
// With body logging and redactionrequestLog({ logRequestBody: true, logResponseBody: true, redactPaths: ["password", "*.secret", "auth.token"], sink: async (entry) => { await fetch("https://logs.example.com/ingest", { method: "POST", body: JSON.stringify(entry), }); },});