# How to Enable Structured JSON Logging in workerd: Complete Configuration Guide

> Learn to enable structured JSON logging in workerd. Configure your logs for better analysis and debugging with this complete guide. Master workerd configuration settings.

- Repository: [Cloudflare/workerd](https://github.com/cloudflare/workerd)
- Tags: how-to-guide
- Published: 2026-03-18

---

**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:

```capnp

# 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:

```capnp
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 milliseconds
- `level`: Severity level (INFO, WARNING, ERROR, etc.)
- `source`: Source file and line number (e.g., "worker.cpp:123")
- `message`: The log content
- `contextDepth`: Optional nesting level for contextual logging

Example output:

```json
{"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):

```c++
#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:

```javascript
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:

```bash
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 = true` in the `logging` block of `workerd.capnp` (defined in `src/workerd/server/workerd.capnp`).
- **Activation**: The flag triggers `StructuredLoggingProcessContext::enableStructuredLogging()` in `workerd.c++`, creating a `JsonLogger` instance.
- **Format**: Logs become newline-delimited JSON objects with `timestamp`, `level`, `source`, `message`, and `contextDepth` fields.
- **Coverage**: Both C++ `KJ_LOG` macros and JavaScript `console.*` methods route through the structured pipeline.
- **Implementation**: The core logic resides in `src/workerd/server/json-logger.c++` using the Cap'n Proto schema from `log-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++`**.