log: fix side effects when importing rclone as a library

Avoid side effects by using own logger instance

- Importing fs/log only sets rclone's private logger via fs.SetLogger,
  so internal rclone logging works from the moment the package is
  imported but the process-wide slog default is left untouched.

- slog.SetDefault and slog.SetLogLoggerLevel move into InitLogging,
  which is called explicitly from the CLI (cmd/cmd.go), the librclone
  wrapper and the integration test framework. So rclone-as-a-program
  keeps capturing log.Print/log.Fatal and slog.Default() output as
  before.

Library consumers that import fs/log without calling InitLogging now
keep their own slog default and can safely route rclone output back
into it via log.Handler.SetOutput without recursing.

Fixes #8907

Co-authored-by: Nick Craig-Wood <nick@craig-wood.com>
This commit is contained in:
Sven Rebhan
2026-05-04 11:06:30 +01:00
committed by GitHub
co-authored by Nick Craig-Wood
parent 9f89102a57
commit b8b3346499
3 changed files with 33 additions and 6 deletions
+10 -1
View File
@@ -12,6 +12,10 @@ import (
"github.com/rclone/rclone/lib/caller"
)
// logger represents the slog logging facility and should be overridden by
// the fs/log handling code.
var logger *slog.Logger = slog.Default()
// LogLevel describes rclone's logs. These are a subset of the syslog log levels.
type LogLevel = Enum[logLevelChoices]
@@ -137,7 +141,7 @@ func LogLevelToSlog(level LogLevel) slog.Level {
}
func logSlog(level LogLevel, text string, attrs []any) {
slog.Log(context.Background(), LogLevelToSlog(level), text, attrs...)
logger.Log(context.Background(), LogLevelToSlog(level), text, attrs...)
}
func logSlogWithObject(level LogLevel, o any, text string, attrs []any) {
@@ -337,3 +341,8 @@ func PrettyPrint(in any, label string, level LogLevel) {
}
LogPrintf(level, label, "\n%s\n", string(inBytes))
}
// SetLogger overrides the slog logger using the specified handler
func SetLogger(h slog.Handler) {
logger = slog.New(h)
}