Files
rclone/fs/log/event_log_windows.go
Nick Craig-Wood 15510c66d4
Some checks failed
Build & Push Docker Images / Build Docker Image for linux/386 (push) Has been cancelled
build / windows (push) Has been cancelled
build / other_os (push) Has been cancelled
build / mac_amd64 (push) Has been cancelled
build / mac_arm64 (push) Has been cancelled
build / linux (push) Has been cancelled
build / go1.23 (push) Has been cancelled
build / linux_386 (push) Has been cancelled
build / lint (push) Has been cancelled
build / android-all (push) Has been cancelled
Build & Push Docker Images / Build Docker Image for linux/amd64 (push) Has been cancelled
Build & Push Docker Images / Build Docker Image for linux/arm/v6 (push) Has been cancelled
Build & Push Docker Images / Build Docker Image for linux/arm/v7 (push) Has been cancelled
Build & Push Docker Images / Build Docker Image for linux/arm64 (push) Has been cancelled
Build & Push Docker Images / Merge & Push Final Docker Image (push) Has been cancelled
log: add --windows-event-log-level to support Windows Event Log
This provides JSON logs in the Windows Event Log.
2025-05-23 11:27:49 +01:00

80 lines
2.0 KiB
Go

// Windows event logging
//go:build windows
package log
import (
"fmt"
"log/slog"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/lib/atexit"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc/eventlog"
)
const (
errorID = uint32(windows.ERROR_INTERNAL_ERROR)
infoID = uint32(windows.ERROR_SUCCESS)
sourceName = "rclone"
)
var (
windowsEventLog *eventlog.Log
)
func startWindowsEventLog(handler *OutputHandler) error {
// Don't install Windows event log if it is disabled.
if Opt.WindowsEventLogLevel == fs.LogLevelOff {
return nil
}
// Install the event source - we don't care if this fails as Windows has sensible fallbacks.
_ = eventlog.InstallAsEventCreate(sourceName, eventlog.Info|eventlog.Warning|eventlog.Error)
// Open the event log
// If sourceName didn't get registered then Windows will use "Application" instead which is fine.
// Though in my tests it seemsed to use sourceName regardless.
elog, err := eventlog.Open(sourceName)
if err != nil {
return fmt.Errorf("open event log: %w", err)
}
// Set the global for the handler
windowsEventLog = elog
// Close it on exit
atexit.Register(func() {
err := elog.Close()
if err != nil {
fs.Errorf(nil, "Failed to close Windows event log: %v", err)
}
})
// Add additional JSON logging to the eventLog handler.
handler.AddOutput(true, eventLog)
fs.Infof(nil, "Logging to Windows event log at level %v", Opt.WindowsEventLogLevel)
return nil
}
// We use levels ERROR, NOTICE, INFO, DEBUG
// Need to map to ERROR, WARNING, INFO
func eventLog(level slog.Level, text string) {
// Check to see if this level is required
if level < fs.LogLevelToSlog(Opt.WindowsEventLogLevel) {
return
}
// Now log to windows eventLog
switch level {
case fs.SlogLevelEmergency, fs.SlogLevelAlert, fs.SlogLevelCritical, slog.LevelError:
_ = windowsEventLog.Error(errorID, text)
case slog.LevelWarn:
_ = windowsEventLog.Warning(infoID, text)
case fs.SlogLevelNotice, slog.LevelInfo, slog.LevelDebug:
_ = windowsEventLog.Info(infoID, text)
}
}