Logging

Via writes operational logs as structured key=value records, one event per line:

time=2026-10-01T13:26:16.666Z level=info event=request.completed request_id="fbd06c3469d1c645432441b7816b52ad" client="127.0.0.1" method="GET" host="example.com" path="/api/users" target="proxy" route_path="/api" upstream="http://127.0.0.1:8000" status=200 request_bytes=null response_bytes=421 duration_ms=4.691 failure=null

Strings are quoted and escaped. Numbers, booleans, and null remain directly machine-readable. A mutex keeps records from concurrent fibers on separate lines.

The startup banner is written to stdout. Operational records are written to stderr, which keeps logs suitable for systemd, containers, and shell redirection:

via -c config.yaml >startup.log 2>via.log

Request completion

Every handled request produces request.completed at info level:

request_id
client
method
host
path
target
route_path
upstream
status
request_bytes
response_bytes
duration_ms
failure

Query strings are intentionally not logged. This avoids putting tokens or other sensitive query parameters into normal operational logs.

request_bytes is null when the incoming body length is not known. response_bytes uses the response content length when available and otherwise tracks bytes streamed from an upstream.

Configuration events

Via emits:

  • config.applied after initial validation;
  • config.reloaded after an atomic hot reload;
  • config.rejected when a replacement configuration is invalid.

Rejected configuration records include whether Via kept a previous generation and whether debug diagnostic mode was activated.

Failure events

Transport and routing failures have dedicated events:

  • request.rejected;
  • routing.miss;
  • upstream.failed;
  • stream.failed.

All request-related events carry the same request ID returned in X-Request-ID and shown on Via error pages.

Debug mode

--debug adds:

  • request.started;
  • routing.selected;
  • upstream.response.

These records expose route selection and upstream timing context without changing the normal completion record.

via --debug -c config.yaml

systemd

The default one-line format is directly searchable with journalctl:

journalctl -u via -o cat
journalctl -u via -o cat | grep 'event=request.completed'
journalctl -u via -o cat | grep 'request_id="fbd06c3469d1c645432441b7816b52ad"'