fastify-xlogger
fastify-xlogger
Standardized logging for Fastify v5 built on the built-in Pino logger. Register once to get automatic request context, secret redaction at the Pino level, canonical log schema, boundary logging for external API calls, and background job correlation.
Installation
npm install @xenterprises/fastify-xlogger
Quick Start
import Fastify from "fastify";
import xLogger, { getLoggerOptions } from "@xenterprises/fastify-xlogger";
const fastify = Fastify({
logger: getLoggerOptions({ serviceName: "my-api" }),
});
await fastify.register(xLogger, { serviceName: "my-api" });
fastify.get("/users/:id", async (request) => {
request.contextLog.info({ userId: request.params.id }, "Fetching user");
fastify.xlogger.logEvent({
event: "user.fetched",
data: { userId: request.params.id },
request,
});
return { id: request.params.id };
});
Options
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
active | boolean | true | No | Set to false to skip plugin registration entirely. |
serviceName | string | SERVICE_NAME env or "fastify-app" | No | Service name included on every log entry. |
environment | string | NODE_ENV env or "development" | No | Environment name included on every log entry. |
redactPaths | string[] | [] | No | Additional Pino paths to redact (extends the built-in defaults). |
redactClobber | boolean | false | No | Replace the default redact list entirely instead of extending it. |
includeRequestBody | boolean | false | No | Include request body in logs. |
includeResponseBody | boolean | false | No | Include response body in logs. |
contextExtractor | function | null | No | (request) => object — add custom fields to every request context. |
enableBoundaryLogging | boolean | true | No | Enable boundary logging helpers on fastify.xlogger. |
request.contextLog
A Pino child logger automatically created for every request with canonical context fields:
| Field | Source |
|---|---|
requestId | request.id |
route | request.routeOptions.url |
method | request.method |
orgId | x-org-id / x-tenant-id header, or request.user.orgId / organizationId / tenantId |
userId | x-user-id header, or request.user.id / userId / sub |
traceId / spanId | traceparent header (OpenTelemetry W3C format) |
fastify.get("/orders/:id", async (request) => {
request.contextLog.info({ orderId: request.params.id }, "Processing order");
});
Methods
fastify.xlogger decorator
- logEvent — Log a structured business event with canonical schema.
- logBoundary — Log an external API call with vendor, operation, duration, and status.
- createBoundaryLogger — Create a timed boundary logger that captures duration automatically.
- createJobContext — Create a correlated child logger for background jobs with
start,complete, andfailhelpers. - extractContext — Extract the canonical context object from a Fastify request.
Exported function
- getLoggerOptions — Build Pino logger options (redaction, serializers, transport) for use when creating the Fastify instance.
Default Redacted Paths
Auth headers: req.headers.authorization, req.headers.cookie, req.headers['set-cookie'], req.headers['x-api-key']
Secret fields: password, token, secret, apiKey, api_key, accessToken, access_token, refreshToken, refresh_token, privateKey, private_key
PII / payment: cardNumber, card_number, cvv, ssn, creditCard
Nested: *.password, *.token, *.secret, *.apiKey, *.api_key
Use redactPaths to extend, or redactClobber: true to replace entirely.
Error Reference
Startup Errors
| Error | Cause |
|---|---|
[xLogger] redactPaths must be an array of strings | redactPaths is not an array. |
[xLogger] contextExtractor must be a function | contextExtractor is not a function. |
[xLogger] serviceName must be a string | serviceName is not a string. |
[xLogger] environment must be a string | environment is not a string. |
[xLogger] includeRequestBody must be a boolean | includeRequestBody is not a boolean. |
[xLogger] includeResponseBody must be a boolean | includeResponseBody is not a boolean. |
[xLogger] redactClobber must be a boolean | redactClobber is not a boolean. |
[xLogger] enableBoundaryLogging must be a boolean | enableBoundaryLogging is not a boolean. |
Runtime Errors
| Error | Cause |
|---|---|
[xLogger] logEvent requires a string 'event' parameter | logEvent() called without a string event. |
[xLogger] logBoundary requires a string 'vendor' parameter | logBoundary() called without vendor. |
[xLogger] logBoundary requires a string 'operation' parameter | logBoundary() called without operation. |
[xLogger] createBoundaryLogger requires a string 'vendor' parameter | createBoundaryLogger() called without vendor. |
[xLogger] createBoundaryLogger requires a string 'operation' parameter | createBoundaryLogger() called without operation. |
[xLogger] createJobContext requires a string 'jobName' parameter | createJobContext() called without jobName. |
Environment Variables
| Variable | Required | Description |
|---|---|---|
SERVICE_NAME | No | Fallback service name if serviceName option is not set. |
NODE_ENV | No | Controls log level (info in prod, debug otherwise) and transport (JSON in prod, pino-pretty otherwise). |
BETTERSTACK_SOURCE_TOKEN | No | Source token for @logtail/pino transport (optional peer dependency). |
How It Works
On registration, the plugin validates all options and decorates fastify.xlogger with configuration and utility methods. An onRequest hook creates a Pino child logger (request.contextLog) for every request by calling extractContext — which reads request.user, standard headers (x-org-id, x-tenant-id, x-user-id), and the W3C traceparent header — and binding those fields to the child. An onResponse hook writes a canonical http.response event with status code, elapsed time, and request context; level is error for 5xx, warn for 4xx, info otherwise. The utility methods are stateless — they write to request.log when a request is provided, or to fastify.log otherwise. The exported getLoggerOptions() configures Pino's redaction, serializers, and transport at Fastify instantiation time.
AI Context
package: "@xenterprises/fastify-xlogger"
type: fastify-plugin
use-when: Structured logging with request context, secret redaction, boundary logging for external APIs, and background job correlation
decorator: fastify.xlogger (logEvent, logBoundary, createBoundaryLogger, createJobContext, extractContext)
request-decorator: request.contextLog — auto-created Pino child per request with requestId, userId, orgId, traceId
exported: getLoggerOptions() — call at Fastify instantiation with logger option
env: SERVICE_NAME, NODE_ENV, BETTERSTACK_SOURCE_TOKEN (all optional)
