116 lines
3.2 KiB
Go
116 lines
3.2 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
|
)
|
|
|
|
var (
|
|
baseTargets []logger.Logger
|
|
once sync.Once
|
|
initErr error
|
|
)
|
|
|
|
// InstancedLogger prefixes each message with its instance-specific prefix and a timestamp,
|
|
// while writing to shared log outputs.
|
|
type InstancedLogger struct {
|
|
prefix string
|
|
targets []logger.Logger
|
|
}
|
|
|
|
// NewLogger returns a logger instance that writes to the shared logs
|
|
//
|
|
// but prefixes every message with [prefix].
|
|
func NewLogger(prefix string) (*InstancedLogger, error) {
|
|
once.Do(func() {
|
|
baseTargets, initErr = createBaseTargets()
|
|
})
|
|
if initErr != nil {
|
|
return nil, initErr
|
|
}
|
|
return &InstancedLogger{prefix: prefix, targets: baseTargets}, nil
|
|
}
|
|
|
|
// createBaseTargets initializes the shared log file and console loggers once.
|
|
func createBaseTargets() ([]logger.Logger, error) {
|
|
cfgDir, err := os.UserConfigDir()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot determine user config dir: %w", err)
|
|
}
|
|
logDir := filepath.Join(cfgDir, "FanslySync", "logs")
|
|
if err := os.MkdirAll(logDir, 0o755); err != nil {
|
|
return nil, fmt.Errorf("cannot create log directory: %w", err)
|
|
}
|
|
|
|
// Prune logs older than 14 days
|
|
cutoff := time.Now().Add(-14 * 24 * time.Hour)
|
|
entries, _ := os.ReadDir(logDir)
|
|
for _, e := range entries {
|
|
if e.IsDir() || e.Name() == "runtime_latest.log" {
|
|
continue
|
|
}
|
|
info, err := e.Info()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if info.ModTime().Before(cutoff) {
|
|
_ = os.Remove(filepath.Join(logDir, e.Name()))
|
|
}
|
|
}
|
|
|
|
// Remove old runtime_latest.log if it exists
|
|
runtimePath := filepath.Join(logDir, "runtime_latest.log")
|
|
if _, err := os.Stat(runtimePath); err == nil {
|
|
_ = os.Remove(runtimePath)
|
|
}
|
|
|
|
// Prepare file paths
|
|
ts := time.Now().Format("2006-01-02_15-04-05")
|
|
tsPath := filepath.Join(logDir, fmt.Sprintf("runtime_%s.log", ts))
|
|
latestPath := filepath.Join(logDir, "runtime_latest.log")
|
|
|
|
// Create loggers
|
|
tsLogger := logger.NewFileLogger(tsPath)
|
|
latestLogger := logger.NewFileLogger(latestPath)
|
|
termLogger := logger.NewDefaultLogger()
|
|
|
|
return []logger.Logger{tsLogger, latestLogger, termLogger}, nil
|
|
}
|
|
|
|
// log dispatches a timestamped, prefixed message to all shared targets.
|
|
func (l *InstancedLogger) log(level, message string) {
|
|
timestamp := time.Now().Format("2006-01-02 15:04:05")
|
|
fullMsg := fmt.Sprintf("%s [%s] %s", timestamp, l.prefix, message)
|
|
for _, t := range l.targets {
|
|
switch level {
|
|
case "Print":
|
|
t.Print(fullMsg)
|
|
case "Trace":
|
|
t.Trace(fullMsg)
|
|
case "Debug":
|
|
t.Debug(fullMsg)
|
|
case "Info":
|
|
t.Info(fullMsg)
|
|
case "Warning":
|
|
t.Warning(fullMsg)
|
|
case "Error":
|
|
t.Error(fullMsg)
|
|
case "Fatal":
|
|
t.Fatal(fullMsg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (l *InstancedLogger) Print(message string) { l.log("Print", message) }
|
|
func (l *InstancedLogger) Trace(message string) { l.log("Trace", message) }
|
|
func (l *InstancedLogger) Debug(message string) { l.log("Debug", message) }
|
|
func (l *InstancedLogger) Info(message string) { l.log("Info", message) }
|
|
func (l *InstancedLogger) Warning(message string) { l.log("Warning", message) }
|
|
func (l *InstancedLogger) Error(message string) { l.log("Error", message) }
|
|
func (l *InstancedLogger) Fatal(message string) { l.log("Fatal", message) }
|