feat(server): add syslog priority prefixes for systemd-journald (#5192)
* fix: add syslog priority prefixes for systemd-journald When running under systemd, all log messages were assigned priority 3 (error) by journald because navidrome wrote plain text to stderr without syslog priority prefixes. Add a journalFormatter that wraps the existing logrus formatter and prepends <N> syslog priority prefixes (RFC 5424) to each log line. The formatter is automatically enabled when the JOURNAL_STREAM environment variable is set (indicating the process is managed by systemd). Priority mapping: - Fatal/Panic → <2>/<0> (crit/emerg) - Error → <3> (err) - Warn → <4> (warning) - Info → <6> (info) - Debug/Trace → <7> (debug) Fixes #5142 * test: refactor journalFormatter tests to use Ginkgo and DescribeTable Signed-off-by: Deluan <deluan@navidrome.org> --------- Signed-off-by: Deluan <deluan@navidrome.org> Co-authored-by: Deluan <deluan@navidrome.org>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// journalFormatter wraps a logrus.Formatter and prepends a syslog priority
|
||||
// prefix (<N>) to each log line. When stderr is captured by systemd-journald,
|
||||
// this prefix tells journald the correct severity for each message.
|
||||
//
|
||||
// See https://www.freedesktop.org/software/systemd/man/sd-daemon.html
|
||||
type journalFormatter struct {
|
||||
inner logrus.Formatter
|
||||
}
|
||||
|
||||
// levelToPriority maps logrus levels to syslog priority values.
|
||||
// The mapping follows RFC 5424 severity levels.
|
||||
var levelToPriority = map[logrus.Level]int{
|
||||
logrus.PanicLevel: 0, // emerg
|
||||
logrus.FatalLevel: 2, // crit
|
||||
logrus.ErrorLevel: 3, // err
|
||||
logrus.WarnLevel: 4, // warning
|
||||
logrus.InfoLevel: 6, // info
|
||||
logrus.DebugLevel: 7, // debug
|
||||
logrus.TraceLevel: 7, // debug
|
||||
}
|
||||
|
||||
func (f *journalFormatter) Format(entry *logrus.Entry) ([]byte, error) {
|
||||
formatted, err := f.inner.Format(entry)
|
||||
if err != nil {
|
||||
return formatted, err
|
||||
}
|
||||
priority, ok := levelToPriority[entry.Level]
|
||||
if !ok {
|
||||
priority = 6 // default to info for unknown levels
|
||||
}
|
||||
prefix := []byte(fmt.Sprintf("<%d>", priority))
|
||||
return append(prefix, formatted...), nil
|
||||
}
|
||||
Reference in New Issue
Block a user