Measure Rspamd Symbol Impact with rspamd_stats

Before you disable a Rspamd rule because it feels noisy, run rspamd_stats and get an actual number. It turns your logs into hard stats on how often a symbol fires and whether it changes an outcome. The examples use the installed Rspamd package version 3.8.1-1ubuntu3 and only read log data. Allow about fifteen minutes, and have a shell, readable Rspamd logs and a symbol name you want to investigate.

Safety boundary: rspamd_stats does not rewrite the log, reload Rspamd or change a rule. Reading a system log may still require elevated privileges. Use sudo only for the read operation when your account cannot access the file.

1. Confirm the installed command

Check which executable will run and record its package version. These are ordinary read-only commands:

$ command -v rspamd_stats
/usr/bin/rspamd_stats
$ dpkg-query -W -f='${Package} ${Version}\n' rspamd
rspamd 3.8.1-1ubuntu3
$ rspamd_stats --help

The installed help is worth checking because the local 2018 manpage does not list every option in this package. This build also advertises --json, --nrelated and --mult. Treat those as version-specific until you check the help on another host. The documented defaults are reject score 15, junk score 6.0, alpha score 0.1, all log files in a selected directory, and zero excluded latest files.

Checkpoint: if command -v finds nothing, install the distribution's Rspamd package before continuing. Do not copy this host's binary into another system.

2. Start with one log file and one symbol

Use a single log first. Replace /var/log/rspamd/rspamd.log with a readable file from your host and replace SYMBOL_NAME with the exact symbol or a PCRE pattern you want to match:

$ rspamd_stats --log /var/log/rspamd/rspamd.log --symbol='SYMBOL_NAME'
=== Summary ====================================================================
Messages scanned: 1234

Symbol: SYMBOL_NAME (weight 2.100) (420 hits, 34.036%)
Ham hits: 18 (1.459%), total ham: 900 (ham with SYMBOL_NAME: 2.000%)
Spam hits: 350 (28.363%), total spam: 300 (spam with SYMBOL_NAME: 116.667%)
Junk hits: 52 (4.215%), total junk: 34 (junk with SYMBOL_NAME: 152.941%)
================================================================================

The counts above show the shape of the output, not a prediction for your logs. A real report may include change lines and different totals. The symbol argument is a regular expression, so quote it for the shell and keep punctuation deliberate: a bare pattern can match more symbols than you intended.

If the result says Messages scanned: 0, check the path, permissions and whether the file actually contains Rspamd task log entries first. An empty report is not evidence the symbol never fires.

3. Read the report without confusing its percentages

weight is the average score for the symbol. The total hit percentage divides messages containing the symbol by all scanned messages. The ham, spam and junk rows each show the symbol's hits in that class, the percentage against the class total, the class total, and the percentage of that class containing the symbol.

Those denominators answer different questions. A symbol can be rare overall but concentrated in spam. It can also rack up many hits in ham without being responsible for any classification change. Do not read a high spam percentage as proof of causation: the tool reports association and score-driven changes, while other rules and thresholds still affect the final action.

When present, Spam changes counts messages moved from ham or junk to spam because of the symbol's weight. Junk changes counts ham messages moved to junk. Compare the change counts with the thresholds you actually pass to the tool, not with whatever thresholds happen to be configured on a different Rspamd instance.

4. Analyse a rotated log directory

Once the single-file result makes sense, point --log at a directory. The utility recognises common newsyslog and logrotate numeric suffixes and compressed log types. Files without an index count as the newest; lower numeric indexes count as newer than higher ones.

$ rspamd_stats \
    --log /var/log/rspamd \
    --symbol='BAYES_SPAM' \
    --num-logs=3 \
    --exclude-logs=1

This asks for three eligible log files while excluding the newest one, useful when the current file is still being written or when you want a completed reporting window. The selection depends on the directory naming convention, so inspect the names first:

$ find /var/log/rspamd -maxdepth 1 -type f -printf '%f\n' | sort
$ rspamd_stats --log /var/log/rspamd --symbol='BAYES_SPAM' --num-logs=3 --exclude-logs=1

If access is denied, inspect the directory as your normal user first, then repeat only the read command with elevated privileges:

$ sudo rspamd_stats --log /var/log/rspamd --symbol='BAYES_SPAM' --num-logs=3

5. Limit the time window and thresholds

Use --start and --end to keep a report focused. Their values use YYYY-MM-DD HH:MM:SS and may be truncated; an omitted date defaults to the current date. Supply both full timestamps when comparing a historical incident:

$ rspamd_stats \
    --log /var/log/rspamd \
    --symbol='BAYES_SPAM' \
    --start '2026-09-24 00:00:00' \
    --end '2026-09-25 00:00:00' \
    --reject-score=15 \
    --junk-score=6.0 \
    --alpha-score=0.1

The reject and junk scores define the boundaries used while parsing; they are not a live query of Rspamd's current configuration. Pass the values that applied during the period under review, especially after a policy change. Alpha score filters out symbols whose score falls below the supplied minimum.

6. Produce machine-readable output when supported

This build advertises JSON output, handy for a one-off export or a script. Verify support on the target host before relying on it:

$ rspamd_stats --help | grep -- '--json'
       --json                 print json output instead of human readable
$ rspamd_stats --json --log /var/log/rspamd --symbol='BAYES_SPAM' > rspamd-stats.json
$ test -s rspamd-stats.json && echo 'JSON report written'
JSON report written

The output includes totals, actions and symbol data, but the exact fields belong to the installed implementation. Validate the file as JSON with a tool you already trust before feeding it to automation. The redirection creates or replaces rspamd-stats.json, so pick a new path or make a backup if that file matters.

Recovery: to undo the example, delete the generated report after checking it; the source logs are never modified.

7. Add correlations cautiously

--correlations adds paired correlation information for the symbols displayed. It can help you spot rules that commonly appear together, but correlation is not proof that one rule caused another, or that either rule is safe to remove. Keep the symbol pattern narrow and check the result against message samples and rule configuration:

$ rspamd_stats \
    --log /var/log/rspamd/rspamd.log \
    --symbol='BAYES_SPAM|FUZZY|R_DKIM_ALLOW' \
    --correlations

For a large directory, constrain the number of logs and the time range first. Otherwise a slow report or a crowded output becomes a distraction rather than an answer.

Done means