Skip to content

Tracers

Three tracers write events on the server’s own host: to log files, to the console and to the systemd journal. Which one fits depends mostly on how the server runs: log files are what the WebUI log viewer reads, the console is the usual choice in containers and foreground runs, and the journal integrates with a server that runs under systemd.

Each is a variant of the Tracer object (found in the WebUI under Settings › Telemetry › Tracers) and has the common settings described in Tracing. Exporting to an OpenTelemetry collector is described in OpenTelemetry.

The Log tracer writes events as text to files in a directory, starting a new file at a fixed interval. A new installation has one Log tracer.

This tracer matters for the WebUI as well. The WebUI log viewer reads every file in the directory of the first enabled Log tracer, so logs can be viewed in the WebUI only when such a tracer exists. For the same reason, that directory should contain only Stalwart’s log files.

path is the directory in which the files are written. The server does not create it, so it must exist and be writable by the server’s user.

prefix is the beginning of each file name, stalwart.log by default. rotate sets how often a new file is started, daily by default. The date and time of the start of each file, in UTC, are appended to the prefix:

rotateFile name
dailystalwart.log.2026-01-14
hourlystalwart.log.2026-01-14T09
minutelystalwart.log.2026-01-14T09:12
neverstalwart.log

Rotation only starts new files. Stalwart does not delete old log files, so they accumulate until something removes them. Use a scheduled job or logrotate for this, configured to delete files only, not to rename or truncate the file being written.

ansi adds colour codes to the output, which less -R and terminal viewers display. It is enabled by default for log files. Other tools see the codes as stray characters, so disable it for files that other tools read.

multiline writes each key of an event on its own line. The WebUI log viewer reads the single-line format and shows only the first line of multiline entries, so leave multiline off on the tracer whose files the WebUI reads.

If the directory does not exist or cannot be written, the events are discarded, and a telemetry.log-error event is emitted with the reason. That event is never written to any Log tracer. On a server whose only tracer is a Log tracer, the failure is therefore not visible anywhere.

A Stdout or Journal tracer at level warn, alongside the Log tracer, makes such errors visible. When writing resumes, a second telemetry.log-error event reports the number of events lost.

The following tracer writes info events to /var/log/stalwart, starting a new file every day:

{
"@type": "Log",
"path": "/var/log/stalwart",
"prefix": "stalwart.log",
"rotate": "daily",
"ansi": false,
"level": "info"
}

The Stdout tracer writes events to the console. Despite the name of the variant, the output goes to standard error. It is the usual choice in containers, where the container runtime collects the output, and when the server runs in the foreground. Only one console tracer can exist.

Three settings shape the output. buffered collects the events of each batch before writing them, which reduces the number of writes. ansi adds colour codes. multiline writes each key on its own line.

The following tracer writes info events to the console:

{
"@type": "Stdout",
"level": "info"
}

Under systemd, console output carries two timestamps. The journal captures console output with its own timestamp, in addition to the timestamp in each line. The Journal tracer avoids this duplication and adds structured fields.

The Journal tracer sends events to the systemd journal, on Linux systems running systemd. It has only the common settings, and only one journal tracer can exist. The tracer needs the journal socket: if the socket is not available, the tracer cannot be created, and the server reports Failed to create journald subscriber.

The advantage over console output is that each entry carries structured fields:

  • MESSAGE: the description of the event, such as Authentication failed.
  • PRIORITY: the level, mapped to syslog priorities: error to 3, warn to 4, info to 5, debug to 6 and trace to 7.
  • SYSLOG_IDENTIFIER: the name of the executable, normally stalwart.
  • One field per key of the event, named after the key in upper case, such as REMOTEIP, ACCOUNTID, QUEUEID or SPANID.

The event name is not included. The fields allow entries to be filtered with journalctl, by priority or by any key, for example:

Terminal window
journalctl -t stalwart -p warning
journalctl -t stalwart REMOTEIP=203.0.113.9
journalctl -t stalwart QUEUEID=1834620912

The following tracer sends info events to the journal:

{
"@type": "Journal",
"level": "info"
}