Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/v3/configuration/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ Options:
Log the first X-Forwarded-For address of requests from --trusted-proxies [env: SERVER_LOG_FORWARDED_FOR=] [default: false] [possible values: true, false]
--trusted-proxies <TRUSTED_PROXIES>
List of proxy IPs to use the X-Real-IP and X-Forwarded-For headers from. The default trusts no one, so the headers are not logged unless set. IPv4 entries also match their IPv4-mapped IPv6 form (`::ffff:a.b.c.d`) [env: SERVER_TRUSTED_PROXIES=]
--log-trace-context [<LOG_TRACE_CONTEXT>]
Add the `trace_id`, `span_id` and `trace_flags` fields of a valid W3C `traceparent` request header to the log lines emitted by the request handler. Requires `--log-format json` [env: SERVER_LOG_TRACE_CONTEXT=] [default: false] [possible values: true, false]
--redirect-trailing-slash [<REDIRECT_TRAILING_SLASH>]
Check for a trailing slash in the requested directory URI and redirect permanently (308) to the same path with a trailing slash suffix if it is missing [env: SERVER_REDIRECT_TRAILING_SLASH=] [default: true] [possible values: true, false]
--include-hidden [<INCLUDE_HIDDEN>]
Expand Down
4 changes: 4 additions & 0 deletions src/v3/configuration/env.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ Log the first `X-Forwarded-For` address of requests from `SERVER_TRUSTED_PROXIES

List of proxy IPs to use the `X-Real-IP` and `X-Forwarded-For` headers from. IPv4 entries also match their IPv4-mapped IPv6 form (`::ffff:a.b.c.d`). See [Trusted proxies](../features/logging.md#trusted-proxies). Default empty (trusts no one, so the headers are not logged).

## SERVER_LOG_TRACE_CONTEXT

Add the `trace_id`, `span_id` and `trace_flags` fields of a valid W3C `traceparent` request header to the log lines written for the request. Requires the `json` log format. See [Logging Trace Context](../features/logging.md#logging-trace-context). Default `false`.

## SERVER_REDIRECT_TRAILING_SLASH

Check for a trailing slash in the requested directory URI and redirect permanently (308) to the same path with a trailing slash suffix if it is missing. Default `true` (enabled).
Expand Down
3 changes: 3 additions & 0 deletions src/v3/configuration/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ log-forwarded-for = false
#### Proxy IPs to accept the X-Real-IP and X-Forwarded-For headers from. Empty means none
trusted-proxies = []

#### Log the W3C trace context of the `traceparent` header (JSON log format only)
log-trace-context = false

#### Redirect to trailing slash in the requested directory uri
redirect-trailing-slash = true

Expand Down
32 changes: 31 additions & 1 deletion src/v3/features/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ When the level is `info` or lower, SWS logs one line per request with the `respo
}
```

No line is logged when SWS fails to build a response. The `remote_addr`, `x_real_ip` and `real_remote_ip` fields are added when the corresponding logging options are enabled and a value is available. Fields without a value are omitted.
No line is logged when SWS fails to build a response. The `remote_addr`, `x_real_ip` and `real_remote_ip` fields are added when the corresponding logging options are enabled and a value is available, and the `trace_id`, `span_id` and `trace_flags` fields when [trace context logging](#logging-trace-context) is enabled. Fields without a value are omitted.

## Log Remote Addresses

Expand Down Expand Up @@ -294,6 +294,36 @@ The URI and the `Host`, `User-Agent` and `Referer` headers come from the client.

An escaped value longer than 4 KiB is cut and ends with `...`, so a large header cannot produce a large log line.

## Logging Trace Context

When SWS runs behind a proxy or load balancer that starts or continues a [W3C Trace Context](https://www.w3.org/TR/trace-context/) trace, the proxy forwards a `traceparent` request header. SWS can add the trace context of that header to its log lines, so a log backend can link them to the trace and to the logs of other services.

This feature is disabled by default. Enable it with the boolean `--log-trace-context` option, the equivalent [SERVER_LOG_TRACE_CONTEXT](./../configuration/env#server-log-trace-context) env or the `log-trace-context` key under `[general]` in the [TOML file](./../configuration/file). It requires the `json` [log format](#log-format): SWS refuses to start with `--log-trace-context` and another format.

When enabled and the request has a valid `traceparent` header, the log lines written for the request get three top-level fields, as recommended by the OpenTelemetry [Trace Context in Non-OTLP Log Formats](https://opentelemetry.io/docs/specs/otel/compatibility/logging_trace_context/) specification:

- `trace_id`: the `trace-id` of the header (32 lowercase hex characters).
- `span_id`: the `parent-id` of the header (16 lowercase hex characters), which is the span of the caller. SWS does not create spans of its own.
- `trace_flags`: the `trace-flags` of the header (2 lowercase hex characters).

The fields are added to the per-request line (the `response` line of [Per-request logging](#per-request-logging), or the line of the [Access Log Format](#access-log-format) when one is set) and to the other lines logged while the request is handled, such as the `error_page` warning of a `404`. Lines logged outside the request handler, such as connection errors or lines of the HTTPS redirect listener, do not get them. The fields are added at every log level, e.g. to the `404` warning when the level is `warn`.

```sh
static-web-server -p 8787 -d ./public/ -g info --log-format json --log-trace-context
```

```sh
curl "http://localhost:8787/missing.css" \
--header "traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
```

```json
{"timestamp":"2026-09-28T10:39:57.103712+02:00","level":"WARN","method":"GET","uri":"/missing.css","status":404,"error":"Not Found","target":"static_web_server::error_page","span_id":"00f067aa0ba902b7","trace_flags":"01","trace_id":"4bf92f3577b34da6a3ce929d0e0e4736"}
{"timestamp":"2026-09-28T10:39:57.103890+02:00","level":"INFO","message":"response","method":"GET","uri":"/missing.css","status":404,"target":"static_web_server::log_addr","span_id":"00f067aa0ba902b7","trace_flags":"01","trace_id":"4bf92f3577b34da6a3ce929d0e0e4736"}
```

SWS only reads the header. It does not generate trace IDs, export spans or change the headers of the request or the response. Missing, invalid or repeated `traceparent` headers are ignored; see the specification's [versioning rules](https://www.w3.org/TR/trace-context/#versioning-of-traceparent).

## File Logging

By default **SWS** writes log records to standard error. The `--log-file` option additionally streams every record to a file on disk, in **addition** to `stderr`. This is useful for production deployments where `stderr` is captured by a service manager but a durable on-disk copy is also required.
Expand Down