How to Enable Structured JSON Logging in workerd: Complete Configuration Guide
Enable structured JSON logging in workerd by setting structuredLogging = true in the logging block of your workerd.capnp configuration file.
workerd is Cloudflare's open-source JavaScript/WebAssembly runtime. When you activate structured JSON logging, the runtime replaces the default human-readable console output with a stream of newline-delimited JSON objects based on the Cap'n Proto schema log_schema::LogEntry.
How Structured Logging Works in workerd
The structured logging system intercepts all log calls at the process level and converts them to JSON before writing to STDOUT or STDERR.
The Cap'n Proto Foundation
The logging schema is defined in src/workerd/server/log-schema.capnp and imported by the JSON logger implementation. This schema enforces a consistent structure for every log entry, including timestamp, severity level, source location, and message content.
Process Context Activation
When the server parses your configuration, it checks for the structuredLogging flag in src/workerd/server/workerd.c++ (lines 24-28). If enabled, the code calls StructuredLoggingProcessContext::enableStructuredLogging(), which creates a JsonLogger instance that implements kj::ExceptionCallback. This overrides the standard KJ_LOG macro and exception handling pathways, ensuring all logs flow through the JSON pipeline instead of the default kj::TopLevelProcessContext.
Configuration Steps
Minimal Configuration Example
Add the structuredLogging field to the logging struct in your workerd.capnp file:
# workerd-config.capnp
using Workerd = import "/workerd/workerd.capnp";
const config :Workerd.Config = (
logging = (
structuredLogging = true,
),
services = [(
name = "main",
worker = (modules = [(name = "worker", esModule = embed "worker.js")]),
)],
);
The logging struct definition lives in src/workerd/server/workerd.capnp (lines 99-104).
Optional Prefix Configuration
You can customize output prefixes for stdout and stderr streams:
const config :Workerd.Config = (
logging = (
structuredLogging = true,
stdoutPrefix = "stdout: ",
stderrPrefix = "stderr: ",
),
);
Logging Behavior and Output Format
JSON Schema and Fields
In structured mode, StructuredLoggingProcessContext builds each log entry using buildJsonLogMessage (defined in src/workerd/server/json-logger.c++, lines 34-57). The resulting JSON includes:
timestamp: Unix timestamp in millisecondslevel: Severity level (INFO, WARNING, ERROR, etc.)source: Source file and line number (e.g., "worker.cpp:123")message: The log contentcontextDepth: Optional nesting level for contextual logging
Example output:
{"timestamp":1700345678901,"level":"WARNING","source":"worker.cpp:123","message":"Cache miss","contextDepth":0}
C++ Logging with KJ_LOG
When structured logging is active, all KJ_LOG macro calls are intercepted by JsonLogger::logMessage (see json-logger.c++ line 59):
#include <kj/debug.h>
void initializeWorker() {
KJ_LOG(INFO, "Worker startup complete");
KJ_LOG(WARNING, "Cache miss for key 'user:42'");
KJ_LOG(ERROR, "Database connection failed");
}
Each call emits a single JSON line to the output stream without buffering.
JavaScript Console Logging
Worker-side code automatically benefits from structured logging. The runtime forwards console.* methods through the same JsonLogger pipeline:
console.log("Processing request"); // -> {"level":"INFO","message":"Processing request",...}
console.warn("Rate limit approaching"); // -> {"level":"WARNING","message":"Rate limit approaching",...}
console.error("Unhandled exception"); // -> {"level":"ERROR","message":"Unhandled exception",...}
Capturing and Parsing Logs
Pipe the newline-delimited JSON stream to tools like jq for filtering and formatting:
workerd --config workerd-config.capnp | jq -r '. | select(.level == "ERROR") | .message'
This command filters for error-level messages and extracts the human-readable content. The behavior is verified by the test suite in src/workerd/server/json-logger-test.c++, which exercises both default and structured modes beginning at line 45.
Summary
- Configuration: Set
structuredLogging = truein theloggingblock ofworkerd.capnp(defined insrc/workerd/server/workerd.capnp). - Activation: The flag triggers
StructuredLoggingProcessContext::enableStructuredLogging()inworkerd.c++, creating aJsonLoggerinstance. - Format: Logs become newline-delimited JSON objects with
timestamp,level,source,message, andcontextDepthfields. - Coverage: Both C++
KJ_LOGmacros and JavaScriptconsole.*methods route through the structured pipeline. - Implementation: The core logic resides in
src/workerd/server/json-logger.c++using the Cap'n Proto schema fromlog-schema.capnp.
Frequently Asked Questions
How do I enable structured JSON logging in workerd?
Set structuredLogging = true inside the logging struct of your workerd.capnp configuration file. When the server starts, it detects this flag and calls StructuredLoggingProcessContext::enableStructuredLogging() to activate the JSON logger instead of the default plain-text output.
What fields are included in workerd's structured log output?
Every JSON log entry contains timestamp (Unix milliseconds), level (severity string), source (file and line), message (log content), and contextDepth (nesting level). The buildJsonLogMessage function in src/workerd/server/json-logger.c++ constructs this format according to the Cap'n Proto log_schema::LogEntry definition.
Does structured logging affect JavaScript console methods?
Yes. When structured logging is enabled, console.log, console.warn, and console.error calls from worker code are automatically converted to JSON format by the same JsonLogger pipeline that handles C++ logs. You do not need to modify your JavaScript code to benefit from structured output.
Where is the structured logging schema defined?
The schema is defined in src/workerd/server/log-schema.capnp and implemented in src/workerd/server/json-logger.c++. The configuration options are declared in src/workerd/server/workerd.capnp (lines 99-104), while the runtime activation logic appears in src/workerd/server/workerd.c++.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →