caddy-website/src/docs/markdown/caddyfile/directives/log.md

599 lines
18 KiB
Markdown
Raw Normal View History

2020-02-28 11:16:45 -07:00
---
title: log (Caddyfile directive)
---
<script>
window.$(function() {
2024-02-20 06:49:30 -05:00
// Fix > in code blocks
window.$('pre.chroma .k:contains(">")')
.each(function() {
const e = window.$(this);
// Skip if ends with >
if (e.text().trim().endsWith('>')) return;
// Replace > with <span class="p">&gt;</span>
e.html(e.html().replace(/&gt;/g, '<span class="p">&gt;</span>'));
});
// We'll add links to all the subdirectives if a matching anchor tag is found on the page.
addLinksToSubdirectives();
});
</script>
2020-02-28 11:16:45 -07:00
# log
Enables and configures HTTP request logging (also known as access logs).
<aside class="tip">
2024-02-20 06:49:30 -05:00
To configure Caddy's runtime logs, see the [`log` global option](/docs/caddyfile/options#log) instead.
</aside>
2024-02-20 06:49:30 -05:00
The `log` directive applies to the hostnames of the site block it appears in, unless overridden with the `hostnames` subdirective.
When configured, by default all requests to the site will be logged. To conditionally skip some requests from logging, use the [`log_skip` directive](log_skip).
To add custom fields to the log entries, use the [`log_append` directive](log_append).
- [Syntax](#syntax)
- [Output modules](#output-modules)
- [stderr](#stderr)
- [stdout](#stdout)
- [discard](#discard)
- [file](#file)
- [net](#net)
- [Format modules](#format-modules)
- [console](#console)
- [json](#json)
- [filter](#filter)
- [delete](#delete)
- [rename](#rename)
- [replace](#replace)
- [ip_mask](#ip-mask)
- [query](#query)
- [cookie](#cookie)
- [regexp](#regexp)
- [hash](#hash)
- [append](#append)
- [Examples](#examples)
By default, headers with potentially sensitive information (`Cookie`, `Set-Cookie`, `Authorization` and `Proxy-Authorization`) will be logged as `REDACTED` in access logs. This behaviour can be disabled with the [`log_credentials`](/docs/caddyfile/options#log-credentials) global server option.
2020-02-28 11:16:45 -07:00
## Syntax
```caddy-d
2023-08-03 00:57:37 -04:00
log [<logger_name>] {
hostnames <hostnames...>
no_hostname
2020-02-28 11:16:45 -07:00
output <writer_module> ...
format <encoder_module> ...
level <level>
}
```
- **logger_name** <span id="logger_name"/> is an optional override of the logger name for this site.
2024-02-20 06:49:30 -05:00
By default, a logger name is generated automatically, e.g. `log0`, `log1`, and so on depending on the order of the sites in the Caddyfile. This is only useful if you wish to reliably refer to the output of this logger from another logger defined in global options. See [an example](#multiple-outputs) below.
- **hostnames** <span id="hostnames"/> is an optional override of the hostnames that this logger applies to.
2024-02-20 06:49:30 -05:00
By default, the logger applies to the hostnames of the site block it appears in, i.e. the site addresses. This is useful if you wish to define different loggers per subdomain in a [wildcard site block](/docs/caddyfile/patterns#wildcard-certificates). See [an example](#wildcard-logs) below.
- **no_hostname** <span id="no_hostname"/> prevents the logger from being associated with any of the site block's hostnames. By default, the logger is associated with the [site address](/docs/caddyfile/concepts#addresses) that the `log` directive appears in.
This is useful when you want to log requests to different files based on some condition, such as the request path or method, using the [`log_name` directive](/docs/caddyfile/directives/log_name).
- **output** <span id="output"/> configures where to write the logs. See [`output` modules](#output-modules) below.
2023-08-03 00:57:37 -04:00
2024-02-20 06:49:30 -05:00
Default: `stderr`.
2023-08-03 00:57:37 -04:00
- **format** <span id="format"/> describes how to encode, or format, the logs. See [`format` modules](#format-modules) below.
2023-08-03 00:57:37 -04:00
2024-02-20 06:49:30 -05:00
Default: `console` if `stderr` is detected to be a terminal, `json` otherwise.
2023-08-03 00:57:37 -04:00
- **level** <span id="level"/> is the minimum entry level to log. Default: `INFO`.
2024-02-20 06:49:30 -05:00
Note that access logs currently only emit `INFO` and `ERROR` level logs.
2020-02-28 11:16:45 -07:00
### Output modules
2024-02-20 06:49:30 -05:00
The **output** subdirective lets you customize where logs get written.
2020-02-28 11:16:45 -07:00
#### stderr
2024-02-20 06:49:30 -05:00
Standard error (console, is the default).
2020-02-28 11:16:45 -07:00
```caddy-d
2020-02-28 11:16:45 -07:00
output stderr
```
#### stdout
Standard output (console).
```caddy-d
2020-03-26 10:14:38 +07:00
output stdout
2020-02-28 11:16:45 -07:00
```
#### discard
No output.
```caddy-d
2020-02-28 11:16:45 -07:00
output discard
```
#### file
A file. By default, log files are rotated ("rolled") to prevent disk space exhaustion.
2024-02-20 06:49:30 -05:00
Log rolling is provided by [lumberjack <img src="/old/resources/images/external-link.svg" class="external-link">](https://github.com/natefinch/lumberjack)
```caddy-d
2020-02-28 11:16:45 -07:00
output file <filename> {
roll_disabled
roll_size <size>
roll_uncompressed
roll_local_time
2020-02-28 11:16:45 -07:00
roll_keep <num>
roll_keep_for <days>
}
```
- **&lt;filename&gt;** is the path to the log file.
2024-02-20 06:49:30 -05:00
2020-02-28 11:16:45 -07:00
- **roll_disabled** disables log rolling. This can lead to disk space depletion, so only use this if your log files are maintained some other way.
2024-02-20 06:49:30 -05:00
- **roll_size** is the size at which to roll the log file. The current implementation supports megabyte resolution; fractional values are rounded up to the next whole megabyte. For example, `1.1MiB` is rounded up to `2MiB`.
Default: `100MiB`
- **roll_uncompressed** turns off gzip log compression.
Default: gzip compression is enabled.
- **roll_local_time** sets the rolling to use local timestamps in filenames.
Default: uses UTC time.
- **roll_keep** is how many log files to keep before deleting the oldest ones.
Default: `10`
- **roll_keep_for** is how long to keep rolled files as a [duration string](/docs/conventions#durations). The current implementation supports day resolution; fractional values are rounded up to the next whole day. For example, `36h` (1.5 days) is rounded up to `48h` (2 days). Default: `2160h` (90 days)
2020-02-28 11:16:45 -07:00
#### net
A network socket. If the socket goes down, it will dump logs to stderr while it attempts to reconnect.
2020-02-28 11:16:45 -07:00
```caddy-d
output net <address> {
dial_timeout <duration>
2023-05-04 16:37:25 -06:00
soft_start
}
2020-02-28 11:16:45 -07:00
```
- **&lt;address&gt;** is the [address](/docs/conventions#network-addresses) to write logs to.
2024-02-20 06:49:30 -05:00
- **dial_timeout** is how long to wait for a successful connection to the log socket. Log emissions may be blocked for up to this long if the socket goes down.
2024-02-20 06:49:30 -05:00
2023-05-04 16:37:25 -06:00
- **soft_start** will ignore errors when connecting to the socket, allowing you to load your config even if the remote log service is down. Logs will be emitted to stderr instead.
2020-02-28 11:16:45 -07:00
### Format modules
The **format** subdirective lets you customize how logs get encoded (formatted). It appears within a `log` block.
<aside class="tip">
New Website: Phase I (#357) * Initial commit; starting new design Dropdown menu * Begin docs layout of new design * Get themes under control; button hover splash * Some basic responsiveness * Finish responsive layout; several bug fixes * Avoid flash during color scheme change * Begin building top of homepage * docs: Start building quick-assist feature * Work on homepage a little more * Keep working on homepage * More homepage progress * Some sponsor SVGs * Add sponsor features * Implement basic Sponsor Experience box * Reorganize some styles * WIP sponsors page * Start features page WIP * Minor improvements * Fix headings; work on features page * WIP features page * Continue work on marketing pages * Continue work on features page * More features WIP * Continue features page... * More work on features page * Keeping going :) * Continue home and features pages * More homepage/features content, screenshots, tweaks * Minor fixes to features page * Minor tweaks * Work on testimonials * Work on homepage more * More homepage work * Continue work on homepage * Add some sponsor logos * Some citation screenshots * Add citations * Start making homepage responsive * Re-add cache busting Fix docs * Use markdown syntax highlighting on frontpage * Rework AJQuery to $_ to not interfere with jQuery * Rewrite quick assist with AlpineJS, use markdown for contents * More work on marketing pages * Rebase and fix code displays * Syntax highlight on-demand example, fix rollover * Adjust on-demand demo * Work on responsiveness * Keep working on responsiveness * Mainly finish making design responsive * Thiccer favicon * More work on marketing pages * Keep on going * Fix link * Move new site into src folder * Add open graph image * Add recorded demo for homepage * Tweak caption * Fix Poppins font for now * Minor tweaks * Trim demo ending * Remove unfinished pages Also update Framer logo --------- Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2023-12-11 10:07:34 -07:00
**A note about Common Log Format (CLF):** CLF clashes with modern structured logs. To transform your access logs into the deprecated Common Log Format, please use the [`transform-encoder` plugin <img src="/old/resources/images/external-link.svg" class="external-link">](https://github.com/caddyserver/transform-encoder).
</aside>
2020-02-28 11:16:45 -07:00
In addition to the syntax for each individual encoder, these common properties can be set on most encoders:
```caddy-d
format <encoder_module> {
message_key <key>
level_key <key>
time_key <key>
name_key <key>
caller_key <key>
stacktrace_key <key>
line_ending <char>
time_format <format>
2022-10-17 13:53:08 -04:00
time_local
duration_format <format>
level_format <format>
2020-02-28 11:16:45 -07:00
}
```
2020-07-29 21:31:13 +08:00
- **message_key** The key for the message field of the log entry. Default: `msg`
2024-02-20 06:49:30 -05:00
2020-02-28 11:16:45 -07:00
- **level_key** The key for the level field of the log entry. Default: `level`
2024-02-20 06:49:30 -05:00
2020-07-29 21:31:13 +08:00
- **time_key** The key for the time field of the log entry. Default: `ts`
2024-02-20 06:49:30 -05:00
- **name_key** The key for the name field of the log entry. Default: `name`
2020-02-28 11:16:45 -07:00
- **caller_key** The key for the caller field of the log entry.
2024-02-20 06:49:30 -05:00
2020-02-28 11:16:45 -07:00
- **stacktrace_key** The key for the stacktrace field of the log entry.
2024-02-20 06:49:30 -05:00
2020-02-28 11:16:45 -07:00
- **line_ending** The line endings to use.
2024-02-20 06:49:30 -05:00
- **time_format** The format for timestamps.
Default: `wall_milli` if the format defaulted to `console`, `unix_seconds_float` otherwise.
May be one of:
- `unix_seconds_float` Floating-point number of seconds since the Unix epoch.
- `unix_milli_float` Floating-point number of milliseconds since the Unix epoch.
- `unix_nano` Integer number of nanoseconds since the Unix epoch.
- `iso8601` Example: `2006-01-02T15:04:05.000Z0700`
- `rfc3339` Example: `2006-01-02T15:04:05Z07:00`
- `rfc3339_nano` Example: `2006-01-02T15:04:05.999999999Z07:00`
- `wall` Example: `2006/01/02 15:04:05`
- `wall_milli` Example: `2006/01/02 15:04:05.000`
- `wall_nano` Example: `2006/01/02 15:04:05.000000000`
- `common_log` Example: `02/Jan/2006:15:04:05 -0700`
- Or, any compatible time layout string; see the [Go documentation](https://pkg.go.dev/time#pkg-constants) for full details.
2024-02-20 06:49:30 -05:00
Note that the parts of the format string are special constants for the layout; so `2006` is the year, `01` is the month, `Jan` is the month as a string, `02` is the day. Do not use the actual current date numbers in the format string.
2022-10-17 13:53:08 -04:00
- **time_local** Logs with the local system time rather than the default of UTC time.
2024-02-20 06:49:30 -05:00
- **duration_format** The format for durations.
Default: `seconds`.
May be one of:
- `s`, `second` or `seconds` Floating-point number of seconds elapsed.
- `ms`, `milli` or `millis` Floating-point number of milliseconds elapsed.
- `ns`, `nano` or `nanos` Integer number of nanoseconds elapsed.
2024-02-20 06:49:30 -05:00
- `string` Using Go's built-in string format, for example `1m32.05s` or `6.31ms`.
- **level_format** The format for levels.
Default: `color` if the format defaulted to `console`, `lower` otherwise.
May be one of:
- `lower` Lowercase.
- `upper` Uppercase.
- `color` Uppercase, with ANSI colors.
2020-02-28 11:16:45 -07:00
#### console
The console encoder formats the log entry for human readability while preserving some structure.
```caddy-d
format console
2020-02-28 11:16:45 -07:00
```
#### json
Formats each log entry as a JSON object.
```caddy-d
format json
2020-02-28 11:16:45 -07:00
```
#### filter
2020-02-28 11:16:45 -07:00
Allows per-field filtering.
2020-02-28 11:16:45 -07:00
```caddy-d
format filter {
fields {
<field> <filter> ...
}
<field> <filter> ...
wrap <encode_module> ...
}
```
Nested fields can be referenced by representing a layer of nesting with `>`. In other words, for an object like `{"a":{"b":0}}`, the inner field can be referenced as `a>b`.
The following fields are fundamental to the log and cannot be filtered because they are added by the underlying logging library as special cases: `ts`, `level`, `logger`, and `msg`.
Specifying `wrap` is optional; if omitted, a default is chosen depending on whether the current output module is [`stderr`](#stderr) or [`stdout`](#stdout), and is an interactive terminal, in which case [`console`](#console) is chosen, otherwise [`json`](#json) is chosen.
As a shortcut, the `fields` block can be omitted and the filters can be specified directly within the `filter` block.
These are the available filters:
##### delete
Marks a field to be skipped from being encoded.
```caddy-d
<field> delete
```
2024-02-20 06:49:30 -05:00
##### rename
Rename the key of a log field.
```caddy-d
<field> rename <key>
```
2024-02-20 06:49:30 -05:00
##### replace
Marks a field to be replaced with the provided string at encoding time.
```caddy-d
<field> replace <replacement>
```
2024-02-20 06:49:30 -05:00
##### ip_mask
2022-10-17 13:53:08 -04:00
Masks IP addresses in the field using a CIDR mask, i.e. the number of bits from the IP to retain, starting from the left side. If the field is an array of strings (e.g. HTTP headers), each value in the array is masked. The value may be a comma separated string of IP addresses.
There is separate configuration for IPv4 and IPv6 addresses, since they have a different total number of bits.
2024-02-20 06:49:30 -05:00
Most commonly, the fields to filter would be:
- `request>remote_ip` for the directly connecting client
- `request>client_ip` for the parsed "real client" when [`trusted_proxies`](/docs/caddyfile/options#trusted-proxies) is configured
- `request>headers>X-Forwarded-For` if behind a reverse proxy
```caddy-d
<field> ip_mask [<ipv4> [<ipv6>]] {
ipv4 <cidr>
ipv6 <cidr>
}
```
2020-02-28 11:16:45 -07:00
2024-02-20 06:49:30 -05:00
##### query
2024-02-20 06:49:30 -05:00
Marks a field to have one or more actions performed, to manipulate the query part of a URL field. Most commonly, the field to filter would be `request>uri`.
```caddy-d
<field> query {
delete <key>
replace <key> <replacement>
hash <key>
}
```
2024-02-20 06:49:30 -05:00
The available actions are:
- **delete** removes the given key from the query.
2024-02-20 06:49:30 -05:00
- **replace** replaces the value of the given query key with **replacement**. Useful to insert a redaction placeholder; you'll see that the query key was in the URL, but the value is hidden.
2024-02-20 06:49:30 -05:00
- **hash** replaces the value of the given query key with the first 4 bytes of the SHA-256 hash of the value, lowercase hexadecimal. Useful to obscure the value if it's sensitive, while being able to notice whether each request had a different value.
2024-02-20 06:49:30 -05:00
##### cookie
2024-02-20 06:49:30 -05:00
Marks a field to have one or more actions performed, to manipulate a `Cookie` HTTP header's value. Most commonly, the field to filter would be `request>headers>Cookie`.
```caddy-d
<field> cookie {
delete <name>
replace <name> <replacement>
hash <name>
}
```
2024-02-20 06:49:30 -05:00
The available actions are:
- **delete** removes the given cookie by name from the header.
2024-02-20 06:49:30 -05:00
- **replace** replaces the value of the given cookie with **replacement**. Useful to insert a redaction placeholder; you'll see that the cookie was in the header, but the value is hidden.
2024-02-20 06:49:30 -05:00
- **hash** replaces the value of the given cookie with the first 4 bytes of the SHA-256 hash of the value, lowercase hexadecimal. Useful to obscure the value if it's sensitive, while being able to notice whether each request had a different value.
If many actions are defined for the same cookie name, only the first action will be applied.
2024-02-20 06:49:30 -05:00
##### regexp
2022-10-17 13:53:08 -04:00
Marks a field to have a regular expression replacement applied at encoding time. If the field is an array of strings (e.g. HTTP headers), each value in the array has replacements applied.
```caddy-d
<field> regexp <pattern> <replacement>
```
The regular expression language used is RE2, included in Go. See the [RE2 syntax reference](https://github.com/google/re2/wiki/Syntax) and the [Go regexp syntax overview](https://pkg.go.dev/regexp/syntax).
In the replacement string, capture groups can be referenced with `${group}` where `group` is either the name or number of the capture group in the expression. Capture group `0` is the full regexp match, `1` is the first capture group, `2` is the second capture group, and so on.
2024-02-20 06:49:30 -05:00
##### hash
2022-10-17 13:53:08 -04:00
Marks a field to be replaced with the first 4 bytes (8 hex characters) of the SHA-256 hash of the value at encoding time. If the field is a string array (e.g. HTTP headers), each value in the array is hashed.
Useful to obscure the value if it's sensitive, while being able to notice whether each request had a different value.
```caddy-d
<field> hash
```
2020-02-28 11:16:45 -07:00
#### append
Appends field(s) to all log entries.
```caddy-d
format append {
fields {
<field> <value>
}
<field> <value>
wrap <encode_module> ...
}
```
It is most useful for adding information about the Caddy instance that is producing the log entries, possibly via an environment variable. The field values may be global placeholders (e.g. `{env.*}`), but _not_ per-request placeholders due to logs being written outside of the HTTP request context.
Specifying `wrap` is optional; if omitted, a default is chosen depending on whether the current output module is [`stderr`](#stderr) or [`stdout`](#stdout), and is an interactive terminal, in which case [`console`](#console) is chosen, otherwise [`json`](#json) is chosen.
The `fields` block can be omitted and the fields can be specified directly within the `append` block.
2020-02-28 11:16:45 -07:00
## Examples
2023-08-03 00:57:37 -04:00
Enable access logging to the default logger.
2024-02-20 06:49:30 -05:00
In other words, by default this logs to `stderr`, but this can be changed by reconfiguring the `default` logger with the [`log` global option](/docs/caddyfile/options#log):
2020-02-28 11:16:45 -07:00
2024-02-20 06:49:30 -05:00
```caddy
example.com {
log
}
2020-02-28 11:16:45 -07:00
```
2020-02-28 11:16:45 -07:00
Write logs to a file (with log rolling, which is enabled by default):
2024-02-20 06:49:30 -05:00
```caddy
example.com {
log {
output file /var/log/access.log
}
2020-02-28 11:16:45 -07:00
}
```
2020-02-28 11:16:45 -07:00
Customize log rolling:
2024-02-20 06:49:30 -05:00
```caddy
example.com {
log {
output file /var/log/access.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
2020-02-28 11:16:45 -07:00
}
}
```
Delete the `User-Agent` request header from the logs:
2020-02-28 11:16:45 -07:00
2024-02-20 06:49:30 -05:00
```caddy
example.com {
log {
format filter {
request>headers>User-Agent delete
}
}
2020-02-28 11:16:45 -07:00
}
```
Redact multiple sensitive cookies. (Note that some sensitive headers are logged with empty values by default; see the [`log_credentials` global option](/docs/caddyfile/options#log-credentials) to enable logging `Cookie` header values):
2024-02-20 06:49:30 -05:00
```caddy
example.com {
log {
format filter {
request>headers>Cookie cookie {
replace session REDACTED
delete secret
}
}
}
}
```
2023-08-03 00:57:37 -04:00
Mask the remote address from the request, keeping the first 16 bits (i.e. 255.255.0.0) for IPv4 addresses, and the first 32 bits from IPv6 addresses.
Note that as of Caddy v2.7, both `remote_ip` and `client_ip` are logged, where `client_ip` is the "real IP" when [`trusted_proxies`](/docs/caddyfile/options#trusted-proxies) is configured:
2024-02-20 06:49:30 -05:00
```caddy
example.com {
log {
format filter {
request>remote_ip ip_mask 16 32
request>client_ip ip_mask 16 32
}
}
}
```
To append a server ID from an environment variable to all log entries, and chain it with a `filter` to delete a header:
```caddy
example.com {
log {
format append {
server_id {env.SERVER_ID}
wrap filter {
request>headers>Cookie delete
}
}
}
}
```
2023-08-03 00:57:37 -04:00
2024-02-20 06:49:30 -05:00
<span id="wildcard-logs" /> To write separate log files for each subdomain in a [wildcard site block](/docs/caddyfile/patterns#wildcard-certificates), by overriding `hostnames` for each logger. This uses a [snippet](/docs/caddyfile/concepts#snippets) to avoid repetition:
2023-08-03 00:57:37 -04:00
```caddy
2024-02-20 06:49:30 -05:00
(subdomain-log) {
2023-08-03 00:57:37 -04:00
log {
2024-02-20 06:49:30 -05:00
hostnames {args[0]}
output file /var/log/{args[0]}.log
2023-08-03 00:57:37 -04:00
}
2024-02-20 06:49:30 -05:00
}
*.example.com {
import subdomain-log foo.example.com
@foo host foo.example.com
2023-08-03 00:57:37 -04:00
handle @foo {
respond "foo"
}
2024-02-20 06:49:30 -05:00
import subdomain-log bar.example.com
2023-08-03 00:57:37 -04:00
@bar host bar.example.com
handle @bar {
respond "bar"
}
}
```
New Website: Phase I (#357) * Initial commit; starting new design Dropdown menu * Begin docs layout of new design * Get themes under control; button hover splash * Some basic responsiveness * Finish responsive layout; several bug fixes * Avoid flash during color scheme change * Begin building top of homepage * docs: Start building quick-assist feature * Work on homepage a little more * Keep working on homepage * More homepage progress * Some sponsor SVGs * Add sponsor features * Implement basic Sponsor Experience box * Reorganize some styles * WIP sponsors page * Start features page WIP * Minor improvements * Fix headings; work on features page * WIP features page * Continue work on marketing pages * Continue work on features page * More features WIP * Continue features page... * More work on features page * Keeping going :) * Continue home and features pages * More homepage/features content, screenshots, tweaks * Minor fixes to features page * Minor tweaks * Work on testimonials * Work on homepage more * More homepage work * Continue work on homepage * Add some sponsor logos * Some citation screenshots * Add citations * Start making homepage responsive * Re-add cache busting Fix docs * Use markdown syntax highlighting on frontpage * Rework AJQuery to $_ to not interfere with jQuery * Rewrite quick assist with AlpineJS, use markdown for contents * More work on marketing pages * Rebase and fix code displays * Syntax highlight on-demand example, fix rollover * Adjust on-demand demo * Work on responsiveness * Keep working on responsiveness * Mainly finish making design responsive * Thiccer favicon * More work on marketing pages * Keep on going * Fix link * Move new site into src folder * Add open graph image * Add recorded demo for homepage * Tweak caption * Fix Poppins font for now * Minor tweaks * Trim demo ending * Remove unfinished pages Also update Framer logo --------- Co-authored-by: Francis Lavoie <lavofr@gmail.com>
2023-12-11 10:07:34 -07:00
<span id="multiple-outputs" /> To write the access logs for a particular subdomain to two different files, with different formats (one with [`transform-encoder` plugin <img src="/old/resources/images/external-link.svg" class="external-link">](https://github.com/caddyserver/transform-encoder) and the other with [`json`](#json)).
2023-08-03 00:57:37 -04:00
This works by overriding the logger name as `foo` in the site block, then including the access logs produced by that logger in the two loggers in global options with `include http.log.access.foo`:
```caddy
{
log access-formatted {
include http.log.access.foo
output file /var/log/access-foo.log
format transform "{common_log}"
}
log access-json {
include http.log.access.foo
output file /var/log/access-foo.json
format json
}
}
foo.example.com {
log foo
}
```