From 0e05d1cc9d2a078fd25b10e7349489979012d82b Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 8 Feb 2026 16:22:58 +0100 Subject: [PATCH] fix(log): write each log category to its own file (#2206) Previously, `makeLogHandler()` hardcoded "standard" as the logfile name passed to `getLogWriter()`, causing all log categories (`database`, `http`, `events`, `mail`) to write to `standard.log` instead of their own files. Add a logfile parameter to `makeLogHandler()` so each caller specifies its category name, producing `database.log`, `http.log`, `echo.log`, `events.log`, and `mail.log` as expected. Fixes https://github.com/go-vikunja/vikunja/issues/2177 --- pkg/log/echo_logger.go | 2 +- pkg/log/logging.go | 8 ++++---- pkg/log/logging_test.go | 27 +++++++++++++++++++++++++++ pkg/log/mail_logger.go | 2 +- pkg/log/watermill_logger.go | 2 +- pkg/log/xorm_logger.go | 2 +- 6 files changed, 35 insertions(+), 8 deletions(-) diff --git a/pkg/log/echo_logger.go b/pkg/log/echo_logger.go index ddc0e0724..49c542fb4 100644 --- a/pkg/log/echo_logger.go +++ b/pkg/log/echo_logger.go @@ -22,6 +22,6 @@ import ( // NewEchoLogger creates and initializes a new slog logger for Echo v5 func NewEchoLogger(configLogEnabled bool, configLogEcho string, configLogFormat string) *slog.Logger { - handler := makeLogHandler(configLogEnabled, configLogEcho, "DEBUG", configLogFormat) + handler := makeLogHandler(configLogEnabled, configLogEcho, "http", "DEBUG", configLogFormat) return slog.New(handler).With("component", "http") } diff --git a/pkg/log/logging.go b/pkg/log/logging.go index 4d094f614..111bfd029 100644 --- a/pkg/log/logging.go +++ b/pkg/log/logging.go @@ -37,7 +37,7 @@ func InitLogger() { logInstance = slog.New(handler) } -func makeLogHandler(enabled bool, output string, level string, format string) slog.Handler { +func makeLogHandler(enabled bool, output string, logfile string, level string, format string) slog.Handler { var slogLevel slog.Level switch strings.ToUpper(level) { case "CRITICAL", "ERROR": @@ -62,7 +62,7 @@ func makeLogHandler(enabled bool, output string, level string, format string) sl writer := io.Discard if enabled && output != "off" { - writer = getLogWriter(output, "standard") + writer = getLogWriter(output, logfile) } return createHandler(writer, slogLevel, format) @@ -89,7 +89,7 @@ func createHandler(writer io.Writer, level slog.Level, format string) slog.Handl // NewHTTPLogger creates and initializes a new HTTP logger func NewHTTPLogger(enabled bool, output string, format string) *slog.Logger { - handler := makeLogHandler(enabled, output, "DEBUG", format) + handler := makeLogHandler(enabled, output, "http", "DEBUG", format) return slog.New(handler).With("component", "http") } @@ -97,7 +97,7 @@ func NewHTTPLogger(enabled bool, output string, format string) *slog.Logger { // ConfigureStandardLogger configures the global log handler func ConfigureStandardLogger(enabled bool, output string, path string, level string, format string) { logPath = path - handler := makeLogHandler(enabled, output, level, format) + handler := makeLogHandler(enabled, output, "standard", level, format) logInstance = slog.New(handler) } diff --git a/pkg/log/logging_test.go b/pkg/log/logging_test.go index 26192e071..13b6b556b 100644 --- a/pkg/log/logging_test.go +++ b/pkg/log/logging_test.go @@ -40,6 +40,33 @@ func TestConfigureStandardLoggerWithPath(t *testing.T) { assert.True(t, os.IsNotExist(err), "Log file should NOT be created in current directory") } +func TestMakeLogHandlerCreatesCorrectLogFile(t *testing.T) { + tempDir := t.TempDir() + logPath = tempDir + + tests := []struct { + name string + logfile string + expected string + }{ + {"standard", "standard", "standard.log"}, + {"database", "database", "database.log"}, + {"http", "http", "http.log"}, + {"events", "events", "events.log"}, + {"mail", "mail", "mail.log"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _ = makeLogHandler(true, "file", tt.logfile, "INFO", "text") + + expectedPath := filepath.Join(tempDir, tt.expected) + _, err := os.Stat(expectedPath) + require.NoError(t, err, "Log file %s should be created", tt.expected) + }) + } +} + func TestConfigureStandardLoggerSetsPathBeforeHandler(t *testing.T) { tempDir := t.TempDir() diff --git a/pkg/log/mail_logger.go b/pkg/log/mail_logger.go index 3a5e5cd5b..32bfe3ce2 100644 --- a/pkg/log/mail_logger.go +++ b/pkg/log/mail_logger.go @@ -29,7 +29,7 @@ type MailLogger struct { // NewMailLogger creates and initializes a new mail logger func NewMailLogger(configLogEnabled bool, configLogMail string, configLogMailLevel string, configLogFormat string) maillog.Logger { - handler := makeLogHandler(configLogEnabled, configLogMail, configLogMailLevel, configLogFormat) + handler := makeLogHandler(configLogEnabled, configLogMail, "mail", configLogMailLevel, configLogFormat) mailLogger := &MailLogger{ logger: slog.New(handler).With("component", "mail"), diff --git a/pkg/log/watermill_logger.go b/pkg/log/watermill_logger.go index b35773842..16b0c20be 100644 --- a/pkg/log/watermill_logger.go +++ b/pkg/log/watermill_logger.go @@ -29,7 +29,7 @@ type WatermillLogger struct { // NewWatermillLogger creates and initializes a new watermill logger func NewWatermillLogger(configLogEnabled bool, configLogEvents string, configLogEventsLevel string, configLogFormat string) *WatermillLogger { - handler := makeLogHandler(configLogEnabled, configLogEvents, configLogEventsLevel, configLogFormat) + handler := makeLogHandler(configLogEnabled, configLogEvents, "events", configLogEventsLevel, configLogFormat) watermillLogger := &WatermillLogger{ logger: slog.New(handler).With("component", "events"), diff --git a/pkg/log/xorm_logger.go b/pkg/log/xorm_logger.go index b067d068b..1c970285e 100644 --- a/pkg/log/xorm_logger.go +++ b/pkg/log/xorm_logger.go @@ -31,7 +31,7 @@ type XormLogger struct { // NewXormLogger creates and initializes a new xorm logger func NewXormLogger(configLogEnabled bool, configLogDatabase string, configLogDatabaseLevel string, configLogFormat string) *XormLogger { - handler := makeLogHandler(configLogEnabled, configLogDatabase, configLogDatabaseLevel, configLogFormat) + handler := makeLogHandler(configLogEnabled, configLogDatabase, "database", configLogDatabaseLevel, configLogFormat) xormLogger := &XormLogger{ logger: slog.New(handler).With("component", "database"),