From 42484e2783978da9c9b5e066bef10b8ecbb4254a Mon Sep 17 00:00:00 2001 From: Wittano Date: Thu, 23 Nov 2023 14:41:42 +0100 Subject: [PATCH] feat(logger): create own logger --- cmd/filebot/commands.go | 2 + cmd/filebot/filebot.go | 3 +- cron/config.go | 4 +- cron/trash.go | 6 +-- file/move.go | 8 ++-- logger/logger.go | 104 +++++++++++++++++++++++++++++++++++++++- setting/config_file.go | 6 +-- setting/flags.go | 25 +++++++++- setting/logger.go | 13 +++++ watcher/watcher.go | 9 ++-- 10 files changed, 156 insertions(+), 24 deletions(-) create mode 100644 setting/logger.go diff --git a/cmd/filebot/commands.go b/cmd/filebot/commands.go index ffa535b..5033463 100644 --- a/cmd/filebot/commands.go +++ b/cmd/filebot/commands.go @@ -16,5 +16,7 @@ var ( func init() { rootCmd.PersistentFlags().StringVarP(&setting.Flags.ConfigPath, "setting", "c", setting.DefaultConfigPath(), "Specific path for filebot configuration") + rootCmd.PersistentFlags().StringVarP(&setting.Flags.LogFilePath, "log", "l", "", "Path to log file") + rootCmd.PersistentFlags().StringVarP(&setting.Flags.LogLevelName, "logLevel", "ll", "INFO", "Log level") rootCmd.PersistentFlags().DurationVarP(&setting.Flags.UpdateInterval, "updateInterval", "u", setting.DefaultUpdateInterval(), "Set time after filebot should be refresh watched file state") } diff --git a/cmd/filebot/filebot.go b/cmd/filebot/filebot.go index 4645cbd..8e211e7 100644 --- a/cmd/filebot/filebot.go +++ b/cmd/filebot/filebot.go @@ -5,7 +5,6 @@ import ( "github.com/wittano/filebot/cron" "github.com/wittano/filebot/setting" "github.com/wittano/filebot/watcher" - "log" ) func runMainCommand(_ *cobra.Command, _ []string) { @@ -26,6 +25,6 @@ func runMainCommand(_ *cobra.Command, _ []string) { func main() { if err := rootCmd.Execute(); err != nil { - log.Fatal(err) + setting.Logger().Fatal("Failed to start FileBot", err) } } diff --git a/cron/config.go b/cron/config.go index 0da3fbf..09a222f 100644 --- a/cron/config.go +++ b/cron/config.go @@ -2,7 +2,7 @@ package cron import ( "github.com/go-co-op/gocron" - "log" + "github.com/wittano/filebot/setting" "time" ) @@ -11,7 +11,7 @@ func NewScheduler() *gocron.Scheduler { _, err := s.Every(1).Hours().Do(moveToTrashTask) if err != nil { - log.Fatal(err) + setting.Logger().Fatal("Failed to register 'moveToTrash' task", err) } return s diff --git a/cron/trash.go b/cron/trash.go index 07433ea..f623093 100644 --- a/cron/trash.go +++ b/cron/trash.go @@ -1,11 +1,9 @@ package cron import ( - "fmt" "github.com/wittano/filebot/file" "github.com/wittano/filebot/setting" "golang.org/x/exp/slices" - "log" "os" "path/filepath" "time" @@ -27,7 +25,7 @@ func moveToTrashTask() { func moveFileToTrash(dir setting.Directory) { paths, err := dir.RealPaths() if err != nil { - log.Printf("Failed to get file paths. %s", err) + setting.Logger().Error("Failed to get file paths", err) return } @@ -45,7 +43,7 @@ func moveFileToTrash(dir setting.Directory) { func isAfterDateOfRemovingFile(path string, after uint) bool { stat, err := os.Stat(path) if err != nil { - log.Println(fmt.Sprintf("Failed to load file info from %s: %s", path, err)) + setting.Logger().Warn("Failed to load file info from "+path, err) return false } diff --git a/file/move.go b/file/move.go index 8336791..c693ee0 100644 --- a/file/move.go +++ b/file/move.go @@ -2,14 +2,14 @@ package file import ( "errors" - "log" + "github.com/wittano/filebot/setting" "os" "path/filepath" ) func MoveToDestination(dest string, paths ...string) { if _, err := os.Stat(dest); errors.Is(err, os.ErrNotExist) { - log.Printf("Destination directory %s doesn't exist", dest) + setting.Logger().Errorf("Destination directory %s doesn't exist", err, dest) return } @@ -19,11 +19,11 @@ func MoveToDestination(dest string, paths ...string) { if _, err := os.Stat(src); !errors.Is(err, os.ErrNotExist) { err := os.Rename(src, newPath) if err != nil { - log.Printf("Failed to move file from %s to %s. %s", src, newPath, err) + setting.Logger().Errorf("Failed to move file from %s to %s", err, src, newPath) return } - log.Printf("Moved file from %s to %s", src, dest) + setting.Logger().Info("Moved file from %s to %s", src, dest) } } } diff --git a/logger/logger.go b/logger/logger.go index 50494b8..4b44b82 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,6 +1,106 @@ package logger -// TODO Create logger settings -func init() { +import ( + "fmt" + "log" + "os" +) +type LogLevel uint + +const ( + ALL LogLevel = 0 + DEBUG LogLevel = 1 + WARN LogLevel = 2 + INFO LogLevel = 2 +) + +const errorPrefix = "[ERROR] " + +type Logger interface { + Info(msg string, args ...any) + Warn(msg string, err error) + Warnf(msg string, err error, args ...any) + Error(msg string, err error) + Errorf(msg string, err error, args ...any) + Debug(msg string, err error) + Fatal(msg string, err error) +} + +type fileStdWriter struct { + filePath string +} + +func (f fileStdWriter) Write(p []byte) (n int, err error) { + if f.filePath != "" { + go writeToLogFile(f.filePath, p) + } + + return os.Stdout.Write(p) +} + +func writeToLogFile(path string, p []byte) { + f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND, 0600) + if err != nil { + log.Fatalf("Failed to open log file") + } + defer f.Close() + + _, err = f.Write(p) + if err != nil { + log.Fatalf("Failed to log into file. %s", err) + } +} + +type myLogger struct { + log *log.Logger + level LogLevel +} + +func (m myLogger) Fatal(msg string, err error) { + m.log.Fatalf("[ERROR]: %s. %s", msg, err) +} + +func (m myLogger) Info(msg string, args ...any) { + m.log.Println(fmt.Sprintf("[INFO] %s", fmt.Sprintf(msg, args...))) +} + +func (m myLogger) Warn(msg string, err error) { + if m.level == WARN || m.level == ALL { + m.log.Println(appendError(fmt.Sprintf("[WARN] %s", msg), err)) + } +} + +func (m myLogger) Warnf(msg string, err error, args ...any) { + if m.level == WARN || m.level == ALL { + m.log.Println(appendError(fmt.Sprintf("[WARN] %s", fmt.Sprintf(msg, args...)), err)) + } +} + +func (m myLogger) Error(msg string, err error) { + m.log.Println(appendError(errorPrefix+msg, err)) +} + +func (m myLogger) Errorf(msg string, err error, args ...any) { + m.log.Println(appendError(fmt.Sprintf(errorPrefix+fmt.Sprintf(msg, args)), err)) +} + +func (m myLogger) Debug(msg string, err error) { + if m.level == DEBUG || m.level == ALL { + m.log.Println(appendError(errorPrefix+msg, err)) + } +} + +func appendError(msg string, err error) string { + if err != nil { + return msg + ", " + err.Error() + } + + return msg +} + +func NewLogger(filePath string, level LogLevel) Logger { + logger := log.New(fileStdWriter{filePath}, "[FileBot]", log.LstdFlags|log.Lmsgprefix) + + return myLogger{logger, level} } diff --git a/setting/config_file.go b/setting/config_file.go index 49ad251..630d9cc 100644 --- a/setting/config_file.go +++ b/setting/config_file.go @@ -5,12 +5,12 @@ import ( "github.com/wittano/filebot/path" "golang.org/x/exp/maps" "golang.org/x/exp/slices" - "log" "os" "path/filepath" "regexp" ) +// TODO Add validation type Config struct { Dirs []Directory } @@ -33,7 +33,7 @@ func (d Directory) RealPaths() (paths []string, err error) { } if err != nil { - log.Printf("Failed get files from pattern '%s'\n", exp) + Logger().Errorf("Failed get files from pattern '%s'", err, exp) return } @@ -63,7 +63,7 @@ func (d Directory) filterRealPaths(paths []string) (res []string) { for _, exp := range d.Exceptions { reg, err := regexp.Compile(exp) if err != nil { - log.Printf("Failed to compile regex: '%s'", exp) + Logger().Warnf("Failed to compile regex: '%s'", nil, exp) continue } diff --git a/setting/flags.go b/setting/flags.go index f6c3c46..7d89255 100644 --- a/setting/flags.go +++ b/setting/flags.go @@ -2,6 +2,7 @@ package setting import ( "github.com/mitchellh/go-homedir" + "github.com/wittano/filebot/logger" "log" "path/filepath" "time" @@ -10,11 +11,15 @@ import ( type Flag struct { ConfigPath string UpdateInterval time.Duration + LogFilePath string + LogLevelName string } var Flags = Flag{ DefaultConfigPath(), DefaultUpdateInterval(), + "", + "", } func (f Flag) Config() *Config { @@ -24,13 +29,29 @@ func (f Flag) Config() *Config { c, err := load(f.ConfigPath) if err != nil { - // TODO Add debug logs - log.Fatalf("Failed to load config file: %s", f.ConfigPath) + Logger().Fatal("Failed to load config file", err) } return c } +func (f Flag) LogLevel() logger.LogLevel { + var level logger.LogLevel + + switch f.LogLevelName { + case "ALL": + level = logger.ALL + case "DEBUG": + level = logger.DEBUG + case "WARN": + level = logger.WARN + default: + level = logger.INFO + } + + return level +} + func DefaultConfigPath() string { homeDir, err := homedir.Dir() if err != nil { diff --git a/setting/logger.go b/setting/logger.go new file mode 100644 index 0000000..cc0db19 --- /dev/null +++ b/setting/logger.go @@ -0,0 +1,13 @@ +package setting + +import "github.com/wittano/filebot/logger" + +var myLogger logger.Logger + +func Logger() logger.Logger { + if myLogger == nil { + myLogger = logger.NewLogger(Flags.LogFilePath, Flags.LogLevel()) + } + + return myLogger +} diff --git a/watcher/watcher.go b/watcher/watcher.go index b27799a..1385e59 100644 --- a/watcher/watcher.go +++ b/watcher/watcher.go @@ -6,7 +6,6 @@ import ( "github.com/wittano/filebot/cron" "github.com/wittano/filebot/file" "github.com/wittano/filebot/setting" - "log" "os" "sync" "time" @@ -23,7 +22,7 @@ type MyWatcher struct { func NewWatcher() MyWatcher { w, err := fsnotify.NewWatcher() if err != nil { - log.Fatalf("Failed initialized file system w: %s", err) + setting.Logger().Fatal("Failed initialized system file watcher", err) } blocker := make(chan bool) @@ -55,7 +54,7 @@ func (w MyWatcher) ObserveFiles() { return } - log.Printf("Error %s", err) + setting.Logger().Error("Watcher got unexpected error", err) } } } @@ -70,7 +69,7 @@ func (w *MyWatcher) AddFilesToObservable(config setting.Config) { for _, dir := range config.Dirs { paths, err := dir.RealPaths() if err != nil { - log.Printf("Failed to get path for files") + setting.Logger().Error("Failed to get path for files", err) continue } @@ -99,7 +98,7 @@ func (w *MyWatcher) fillFileObservedMap(src []string, dest string) { func (w *MyWatcher) addFilesToObservable(paths ...string) { for _, p := range paths { if err := w.Add(p); err != nil { - log.Printf("Cannot add %s file/directory to tracing list: %s", p, err) + setting.Logger().Errorf("Cannot add %s file/directory to tracing list", err, p) } } }