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.
Log file
Section titled “Log file”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.
File names and rotation
Section titled “File names and rotation”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:
rotate | File name |
|---|---|
daily | stalwart.log.2026-01-14 |
hourly | stalwart.log.2026-01-14T09 |
minutely | stalwart.log.2026-01-14T09:12 |
never | stalwart.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.
Output format
Section titled “Output format”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.
Write failures
Section titled “Write failures”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"}Console
Section titled “Console”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.
Journal
Section titled “Journal”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 asAuthentication failed.PRIORITY: the level, mapped to syslog priorities:errorto 3,warnto 4,infoto 5,debugto 6 andtraceto 7.SYSLOG_IDENTIFIER: the name of the executable, normallystalwart.- One field per key of the event, named after the key in upper case, such as
REMOTEIP,ACCOUNTID,QUEUEIDorSPANID.
The event name is not included. The fields allow entries to be filtered with journalctl, by priority or by any key, for example:
journalctl -t stalwart -p warningjournalctl -t stalwart REMOTEIP=203.0.113.9journalctl -t stalwart QUEUEID=1834620912The following tracer sends info events to the journal:
{ "@type": "Journal", "level": "info"}