-
Notifications
You must be signed in to change notification settings - Fork 0
Logging
The backend emits structured JSON via nestjs-pino. Separate concern from audit logging - this is operational app logs, not the tamper-evident business trail.
Every line is one JSON object with level, time, context, msg, an event field, and a requestId for HTTP-scoped events. Example (pretty-printed for readability - prod emits it as a single line):
{
"level": "info",
"time": "2026-04-19T14:23:07.142Z",
"context": "TreatmentsService",
"requestId": "01HQK7X1...",
"userId": "usr_9f3...",
"event": "treatment.created",
"treatmentId": "trt_...",
"refNumber": 42,
"msg": "treatment.created"
}Every HTTP response carries an x-request-id header. If the client sends one matching ^[A-Za-z0-9_-]{1,128}$, it is echoed back; otherwise the server generates a ULID. The same id is bound into every log line within that request's scope, including failures deep in guards and interceptors. Paste an id into docker logs backend | jq 'select(.requestId == "01HQ...")' to reconstruct a request.
Background jobs (RSS sync, monthly compliance snapshot) run under jobId/jobName context in the same way.
Runtime redaction via pino's redact. Two tiers defined in backend/src/common/logging/redact-paths.ts:
-
Strip (disappears entirely):
password,passwordHash,resetToken,sessionSecret,req.headers.authorization,req.headers.cookie. -
Censor (
"[Redacted]"):email,phone,remoteAddress,ip,req.headers["x-forwarded-for"].
Both tiers match up to two levels of nesting. Call sites should log IDs, never whole Prisma entities.
For auth flows that do not yet know a userId (signup, login-failed, password-reset), log an emailHash (10-char truncated SHA-256) instead of a raw address - correlatable across lines, low-entropy enough to not survive as a persistent identifier.
| Var | Default | Values |
|---|---|---|
LOG_LEVEL |
debug in dev, info elsewhere |
trace / debug / info / warn / error / fatal / silent
|
LOG_PRETTY |
on in dev, off elsewhere |
true / false - turns on pino-pretty for colored human-readable lines |
LOG_HTTP |
true |
false disables the per-request access log (http.request.completed / http.request.failed) |
In tests, test/setup.ts forces LOG_LEVEL=silent and LOG_HTTP=false, and test/silence-logger.ts silences @nestjs/common's classic Logger via Logger.overrideLogger(false) per worker.