caddyserver/caddy
Logging system
Caddy uses go.uber.org/zap for structured logging. Configuration lives in logging.go (~25 KB) and bundled encoders/writers in modules/logging/.
Purpose
Build a tree of named loggers from JSON config. Each module gets a child logger named after its module ID; user-defined loggers can split off subsets by name pattern (e.g. an access log scoped to http.log.access).
Directory layout
| Path | Role |
|---|---|
logging.go |
Logging config type, BaseLog, CustomLog, log-tree provisioning |
logging_test.go |
Logger-tree tests |
modules/logging/ |
Encoders and writers |
modules/logging/encoders.go |
Console/JSON encoders |
modules/logging/appendencoder.go |
Append-key encoder |
modules/logging/filterencoder.go |
Filter encoder (cookie, header, IP-mask redaction) (~15 KB) |
modules/logging/filters.go |
Field filter modules (~24 KB) |
modules/logging/journaldencoder.go |
systemd journal encoder |
modules/logging/filewriter.go |
Rotating file writer |
modules/logging/netwriter.go |
TCP/UDP writer |
Key abstractions
| Type | Where | Description |
|---|---|---|
Logging |
logging.go |
Top-level config: a default log + named custom logs |
BaseLog |
logging.go |
Encoder + writer + level + sampling |
CustomLog |
logging.go |
A BaseLog plus name include/exclude rules |
Encoder |
(zap) | Output formatter (caddy.logging.encoders.*) |
WriterOpener |
logging.go |
Module that returns an io.WriteCloser (caddy.logging.writers.*) |
| Filter modules | modules/logging/filters.go |
Hash, replace, delete, mask, regexp redaction for individual log fields |
How it works
graph TD
Config[Logging config] --> Provision[Logging.openLogs]
Provision --> Default[default zap logger]
Provision --> CustomLogs[named loggers]
CustomLogs -->|filter by include/exclude| Tree[zap logger tree]
Module -->|ctx.Logger| Tree
Tree --> Encoder
Encoder --> Writer
Writer --> Sink[stdout/stderr/file/network/journald]Logger tree
Logging.openLogs (in logging.go) walks the configuration and builds zap Cores for every distinct (encoder, writer, level) combination. Loggers are then named: ctx.Logger() looks up the deepest matching name in the tree, so http.handlers.file_server will route through any logger whose include list contains http.handlers.file_server or any of its prefixes (http, http.handlers, …).
Bundled encoders
| Module ID | Source |
|---|---|
caddy.logging.encoders.json |
zap default JSON encoder |
caddy.logging.encoders.console |
zap console encoder |
caddy.logging.encoders.append |
appendencoder.go — adds static fields |
caddy.logging.encoders.filter |
filterencoder.go — applies field filters |
caddy.logging.encoders.journald |
journaldencoder.go |
Field filters
The filter encoder lets you redact or transform individual fields:
| Module ID | Source | Effect |
|---|---|---|
caddy.logging.encoders.filter.hash |
filters.go |
Replace value with a SHA-256 hash |
caddy.logging.encoders.filter.replace |
filters.go |
Replace value with a constant string |
caddy.logging.encoders.filter.delete |
filters.go |
Remove the field |
caddy.logging.encoders.filter.ip_mask |
filters.go |
Mask an IP address to a configurable prefix length |
caddy.logging.encoders.filter.cookie |
filters.go |
Filter values inside a Cookie header |
caddy.logging.encoders.filter.query |
filters.go |
Filter URL query parameters |
caddy.logging.encoders.filter.regexp |
filters.go |
Substitute by regex |
caddy.logging.encoders.filter.multi_regexp |
filters.go |
Multi-pattern variant |
caddy.logging.encoders.filter.rename |
filters.go |
Rename the field |
Writers
| Module ID | Source |
|---|---|
caddy.logging.writers.stdout |
logging.go |
caddy.logging.writers.stderr |
logging.go |
caddy.logging.writers.discard |
logging.go |
caddy.logging.writers.file |
modules/logging/filewriter.go (uses timberjack for rotation) |
caddy.logging.writers.net |
modules/logging/netwriter.go |
Access logs
Access logs are not a special path. They are zap log entries from the HTTP server (modules/caddyhttp/server.go and modules/caddyhttp/logging.go) under the logger name http.log.access.<server-id>. To send them to a separate file, configure a CustomLog whose include pattern matches http.log.access.
Integration points
ctx.Logger: the universal entry point for module log output (context.go).- HTTP server logs: access logs are produced by
modules/caddyhttp/server.goand shaped bymodules/caddyhttp/logging.go. - Caddyfile global options:
logdirectives in the Caddyfile compile toLoggingJSON.
Entry points for modification
- Add an encoder? Implement
zapcore.Encoderand registercaddy.logging.encoders.<name>. - Add a writer? Implement
caddy.WriterOpenerand registercaddy.logging.writers.<name>. - Add a filter? Implement
caddy.LogFieldFilterand registercaddy.logging.encoders.filter.<name>.
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.