Drizzle Castor’s built-in logger wraps pino with aDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/fajarnugraha37/drizzle-castor/llms.txt
Use this file to discover all available pages before exploring further.
PatternFormatter that supports Quarkus-style format tokens. Every log entry is automatically enriched with the traceId from the current ExecutionContext, so log lines from concurrent requests stay correctly attributed even in high-throughput environments. You configure logging once on the schema builder and it applies uniformly to all repository operations.
Enabling the logger
Callbuilder.withLogger({ level, format }) before calling .build(). Both fields are optional; omitting level defaults to WARN and omitting format falls back to the library default format string.
Log levels
- TRACE
- DEBUG
- INFO
- WARN
- ERROR / FATAL
- OFF
Captures the most granular internal detail: query parsing steps, alias resolution, individual middleware dispatch calls. Use only during local debugging — extremely verbose.
Format string tokens
Theformat string is interpreted by the PatternFormatter class in src/helper/logger-helper.ts. Tokens are substituted at runtime for each log entry.
| Token | Description | Example output |
|---|---|---|
%d{format} | Current datetime using the given format string | %d{HH:mm:ss} → 14:32:07 |
%p | Log level in uppercase | INFO, WARN, ERROR |
%-5p | Log level left-padded to 5 characters | INFO , WARN , ERROR |
%c | Logger category (always castor.core for the built-in logger) | castor.core |
%i | Current process PID | 12345 |
%t | Trace ID from the current ExecutionContext | 3f2a1b9c-… |
%z | System timezone | Asia/Jakarta |
%s | The log message string | Executing read on users |
%e | Error stack trace (empty string when no error) | Error: …\n at … |
%n | Newline character | (line break) |
%{key.path} | Context injection — dot-notation path into the ExecutionContext | %{params.filter} |
Datetime format specifiers
The%d{format} token supports the following sub-tokens inside the braces:
| Sub-token | Value |
|---|---|
yyyy | Four-digit year |
MM | Two-digit month (01–12) |
dd | Two-digit day (01–31) |
HH | Two-digit hour, 24-hour clock (00–23) |
mm | Two-digit minute (00–59) |
ss | Two-digit second (00–59) |
SSS | Three-digit milliseconds (000–999) |
Context injection with %{key.path}
The %{key.path} token extracts any value from the ExecutionContext at log time using dot-notation. Array indices are also supported via bracket notation (e.g., params.projection[0]).
Extracting nested params
Extracting nested params
Access nested fields inside
ctx.params — for example, the first element of the projection array:Injecting state values set by middleware
Injecting state values set by middleware
If a middleware writes to
ctx.state.tenantId, you can surface it in every log line:Fallback for missing paths
Fallback for missing paths
If the dot-notation path does not resolve to a value (because the key is absent or the context is not available), the token is replaced with an empty string — no exception is thrown.
How the logger integrates with pino
Drizzle Castor creates aCastorLogger instance that wraps pino internally (src/helper/logger-helper.ts). Pino handles log-level filtering — if the configured level is INFO, pino’s isLevelEnabled check skips the formatting step entirely for DEBUG and TRACE calls, keeping the hot path cost close to zero.
The formatted string is written directly to process.stdout using process.stdout.write, preserving pino’s zero-copy write semantics while giving you full control over the output format.
logger singleton (exported from src/helper/logger-helper.ts) uses AsyncLocalStorage to pull the active ExecutionContext at the moment of each log call — so you never need to pass a logger instance through function arguments.
The context-aware logger is used by all internal Drizzle Castor modules. You do not need to import or call it manually; configuring it via
builder.withLogger() is sufficient.Example format strings
TraceId correlation for concurrent requests
The%t token always resolves to ctx.traceId — a UUID generated at the start of each repository call and threaded through all middleware, log calls, and telemetry events for that single operation. In a server handling concurrent requests, this lets you grep your log output by traceId to reconstruct the exact sequence of events for a given request without any extra instrumentation.
Related pages
Middleware pipeline
Add custom middleware that reads from the same ExecutionContext the logger uses.
Telemetry & Events
Subscribe to structured events that carry the same traceId for cross-system correlation.
Schema builder methods
Full reference for withLogger() and all other builder configuration methods.
Quickstart
See a minimal working example with logging configured alongside a repository.