fix(pflogsumm): Prevent incorrect stats when log retention is > 1 year - #4709
Conversation
Please also update the changelog. |
pflogsumm was processing all files from /var/log/mail, so If the log retention for the mailserver is greater than one year, it would process files from a year ago. Since the log files only contains the day without the year, it would consider logs from a year ago as if they were from yesterday, and produce incorrect daily reports. Fix this by limiting analyzed files to those less than 6 months. Signed-off-by: Pierre-Yves Rofes <3604235+piwai@users.noreply.github.com>
|
@casperklein done |
|
Sorry I was bit too slow to chime in on review 😓
Could I please have some context for the approx 6 month value? My findings from below suggest this task is only meant to send mail from a
How did you go about that btw? Did you set something like I assume your config hasn't changed the default Could you add context as to why you prefer retaining internal logs for that length of time? No external backups or collection through the host such as UPDATE: Given that the bug was actually due to an old log timestamp format lacking an associated year for filtering by, was this something you missed when upgrading to DMS v14 or newer? Our changelog did point out logs would be formatted differently. When did you upgrade? Overview of logging feature / integration in DMSLooking over the following context:
I have this understanding:
This PR only made a change to the The When we configure $ cat /etc/logwatch/conf/logfiles/maillog.conf
#
# Extensions for docker-mailserver /var/log/mail/. log path
#
# Mail log files
LogFile = mail/mail.log
LogFile = mail/mail.log.1
# Support Archives
Archive = mail/mail.log.*.gz$ cat /etc/logwatch/conf/logfiles/clam-update.conf
LogFile = /var/log/mail/freshclam.logSince Startup scripts - Related logic that affects log files mtimeNOTE: We also have log fixes applied in this container startup function:
|
|
TL;DR: Actual source of failure identified (old DMS logs used a different timestamp format that omitted the year). Change in timestamp format since DMS v14 (June 2024)Also worth noting is in June 2024 with the DMS v14 release (upgrade to Debian 12), the changelog Rsyslog notes mention the timestamp format was changed by Debian:
I provided more insights here, but these two snippets below are worth pointing out. EDIT:Another related PR
The # Old RFC 3164 format (lacks a year, assumes present year):
$ logger --rfc3164 --priority mail.error --id=1337 --tag dms-changedetector "This is an example error message!"
<19>May 26 11:45:27 mail dms-changedetector[1337]: This is an example error message!
# RFC 5424 format (notq omits the structured data regarding time, msgid is rfc5424 only):
$ logger --rfc5424=notq --priority mail.error --id=1337 --msgid=hello --tag dms-changedetector "This is an example error message!"
<19>1 2024-05-26T11:45:28.305480+00:00 mail.example.test dms-changedetector 1337 hello - This is an example error message!While in DMS this is how the formats differ from the above two So rsyslog isn't outputting RFC 3164 or RFC 5424 syslog formats regardless, just ingesting either , displaing the message and differing by timestamp format. Notice the lack of year in logs for DMS v13.3 / Reproduction - Verified assumptionsI've confirmed what might have been obvious by now, the RFC 3339 timestamps on logs are fine, it's the old DMS releases logs that were using RFC 3164 until Debian 12 / DMS 14 finally switched to using RFC 3339 timestamps.
#!/bin/bash
# Prepend some timestamps for the log processors to filter by:
function _generate_mock_logs() {
local LOG_MESSAGE="${1:?Expected a log message}"
# RFC 3339 timestamp from yesterday, with offsets by year:
RFC_3339_YMD0=$(date -d "yesterday" +"%Y-%m-%d")
RFC_3339_YMD1=$(date -d "yesterday - 1 year" +"%Y-%m-%d")
RFC_3339_YMD2=$(date -d "yesterday - 2 years" +"%Y-%m-%d")
# RFC 3164 timestamps are like `Jan 1 12:34:56` (format lacks context of which year)
RFC_3164_MD=$(date -d "yesterday - 2 years" +"%b %e")
# RFC 3339 Format: <YYYY-MM-DD>T<HH:mm:ss>[.<fractional-seconds: 1-7 decimal places)>]<UTC offset: (Z|+HH:mm|-HH:mm)>
RFC_3339_SUFFIX='00:00:00.100001+00:00'
local LOG_LINES=(
"${RFC_3339_YMD0}T${RFC_3339_SUFFIX} ${LOG_MESSAGE}" # 2026
"${RFC_3339_YMD1}T${RFC_3339_SUFFIX} ${LOG_MESSAGE}" # 2025
"${RFC_3339_YMD2}T${RFC_3339_SUFFIX} ${LOG_MESSAGE}" # 2024
"${RFC_3164_MD} 00:00:00 ${LOG_MESSAGE}" # 2026 (year could not be encoded)
)
# Output the array as a multi-line string
printf "%s\n" "${LOG_LINES[@]}"
}
# Example log messages (neither message below was mutually reported across both commands, thus separate examples used):
JSON_DATA=$(printf '%s' '
[
{
"CMD": "pflogsumm",
"LOG_MESSAGE": "mail postfix/master[762]: daemon started -- version 3.7.11, configuration /etc/postfix"
},
{
"CMD": "logwatch",
"LOG_MESSAGE": "mail postfix/postfix-script[761]: starting the Postfix mail system"
}
]')
function _run_log_reporters() {
local MAIL_LOG="${TMP_DIR}/mail.log"
# Iterating over objects/structs in Bash is awkward..
# JSON used with tab delimiter to split object properties into variable assignments.
local CMD LOG_MESSAGE REPORT
while IFS=$'\t' read -r CMD LOG_MESSAGE; do
_generate_mock_logs "${LOG_MESSAGE}" > "${MAIL_LOG}"
case "${CMD}" in
# `pflogsumm` can accept log files as args or via stdin, otherwise hangs?:
('pflogsumm')
REPORT=$(pflogsumm -d yesterday "${MAIL_LOG}" | grep -i -A2 master)
;;
# `logwatch` can only process log files via resolved config files via `LogFile` setting.
# - `--logfile` (a service group) or `--service` restricts what logs to process.
# - `--logdir` can add additional logdirs (however `/var/log` + `/var/adm` are always implicit).
# NOTE: To ignore `/var/log` as a logdir, ensure the generated logs and `--range` wouldn't overlap with `/var/log/mail.log`.
('logwatch')
REPORT=$(TZ=UTC logwatch --service postfix --range yesterday --logdir "${TMP_DIR}" | grep -A5 'Postfix Begin')
;;
esac
echo -e "\n\nReport (filtered) from '${CMD}':"
sed 's/^/\t/' <<< "${REPORT}"
done < <(jaq -r '.[] | .CMD + "\t" + .LOG_MESSAGE' <<< "${JSON_DATA}")
}
TMP_DIR=$(mktemp -d)
_run_log_reporters
rm -rf "${TMP_DIR}"# RFC 3164 log line (used prior to DMS v14) was counted:
$ bash verify-log-parsing.sh
Report (filtered) from 'pflogsumm':
Master daemon messages
----------------------
2 daemon started -- version 3.7.11, configuration /etc/postfix
Report (filtered) from 'logwatch':
--------------------- Postfix Begin ------------------------
2 Postfix start 2
---------------------- Postfix End ------------------------- |
|
Hey @polarathene, thanks for the detailled review! I will try to answer to everything.
Actually you're right! 180 is definitely not necessary. Since the issue appeared after one year, I just reduced to half without thinking too much about it. My bad :-(
I'm using a custom user-patches.sh script, with something like:
Nope, I think this was introduced in a more recent version (I'm not on latest, see below).
Yes, I'm not using logwatch
Of course! I'm using DMS for my personal mail, so rather low traffic. Some time ago a friend of mine sent me an email, but I never received it. Some weeks later he told me about it, and I couldn't find anything in the logs since they had been rotated.
Actually I'm still using 12.1 😅 I remember I tried to upgrade some time ago and encountered some regressions, so I kept the working version. I will try to upgrade again to latest stable release
To conclude, this may not be necessary on newer versions, but for performance issue it still might be relevant, to avoid unzipping hundreds of log files. |
|
@polarathene I updated to restrict to 3 days only (2 + 1 to avoid edge cases) |
|
@piwai it looks like you opened a PR to your own fork of DMS by accident? 😅 I have a suggestion below that might be a better approach (no mtime filtering needed). You are correct about the Once you've upgraded you can drop the custom patch if you like 👍 (NOTE:
I agree that the previous logic wasn't ideal. Thanks for contributing to the project so we could resolve that ❤️ I don't know if we really need an mtime filter though? Since we're only concerned with processing logs for I think this would be sufficient (No pipe with # `pflogsumm` expects files in chronological order, while for `-d yesterday`
# the only relevant log files to process are `mail.log.1` (oldest) and `mail.log`:
BODY=$(/usr/sbin/pflogsumm --problems_first -d yesterday /var/log/mail/mail.log{.1,})I included some inline commentary for context. Additional note... I've noticed that Response to other parts of your reply (collapsed as less relevant)
Ah... yes it seems that docker-mailserver/CHANGELOG.md Line 255 in 7290055
Yeah, DMS v12.1 (May 2023) is quite old. You're going to want to comb through the changelog, at least the major version bumps to have a smoother upgrade experience. You can try reach out about regressions you experience with an upgrade, but the older the version the less support that we can provide.
Ah okay, that's fair :) You perhaps would benefit from Although for compatibility with your existing
Sure, I can understand that :) Some prefer the "same place" to be more centralized log collection, which the container logging drivers can be better for. There's benefits to doing such, but I totally get if you prefer retaining log history within the associated container, I'd still advise keeping a periodic backup of that data somewhere though just in case. |
|
Below is just some notes addressing concerns I had raised earlier (like with Mixed intervalsSummary: No issues to address. Can ignore. DMS officially supports configuring
|
docker-mailserver#4709) pflogsumm was processing all files from /var/log/mail, so If the log retention for the mailserver is greater than one year, it would process files from a year ago. Since the log files only contains the day without the year, it would consider logs from a year ago as if they were from yesterday, and produce incorrect daily reports. Fix this by limiting analyzed files to those less than 6 months. Signed-off-by: Pierre-Yves Rofes <3604235+piwai@users.noreply.github.com> Co-authored-by: Casper <casperklein@users.noreply.github.com>
|
sorry for the delay. @polarathene I finally tested your suggestion to keep only mail.log{.1,} and it works as expected. I opened #4722 |
This fixes commit d15b446 intronduced with PR docker-mailserver#4709 which added 6 months worth of log files when only 2 days are necessary
Description
I have configured mail log retention to be several years instead of default. Recently, I started to notice unusually high daily volume in the report produced by pflogsumm. After investigation, it appears that the wrapper currently unextract all log files in log folder without considering their age.
So If the log retention for the mailserver is greater than one year, pflogsumm will process files from more 1 year ago, and since the log file only contains the day, it will consider these files as if they were from yesterday, producing incorrect reports.
With this modification, only log files < 180 days will be sent to pflogsumm for processing.
Fixes #
Type of change
Checklist
docs/)CHANGELOG.md