From d2c7d6ef38fca52b05b7d76bec96a031e60a8d89 Mon Sep 17 00:00:00 2001 From: Matthias Hartmann Date: Wed, 8 Sep 2021 02:13:35 +0200 Subject: [PATCH] Extends Logger interface and adds -v and --loglevel flags for verbose output --- cmd/knoxite/config.go | 1 - cmd/knoxite/logger.go | 56 ++++++++++++++++++++++--------------- cmd/knoxite/main.go | 44 ++++++++++++++++++----------- cmd/knoxite/utils/utils.go | 20 ++++++++----- logger.go | 16 +++++++---- verbosity.go => loglevel.go | 9 +++--- 6 files changed, 90 insertions(+), 56 deletions(-) rename verbosity.go => loglevel.go (63%) diff --git a/cmd/knoxite/config.go b/cmd/knoxite/config.go index 27410b8..01076b3 100644 --- a/cmd/knoxite/config.go +++ b/cmd/knoxite/config.go @@ -9,7 +9,6 @@ package main import ( "bytes" "fmt" - "log" "strconv" "strings" diff --git a/cmd/knoxite/logger.go b/cmd/knoxite/logger.go index 9d78c7f..55e9e95 100644 --- a/cmd/knoxite/logger.go +++ b/cmd/knoxite/logger.go @@ -17,14 +17,14 @@ import ( ) type Logger struct { - VerbosityLevel knoxite.Verbosity - w io.Writer + LogLevel knoxite.LogLevel + w io.Writer } -func NewLogger(v knoxite.Verbosity) *Logger { +func NewLogger(l knoxite.LogLevel) *Logger { return &Logger{ - VerbosityLevel: v, - w: os.Stdout, + LogLevel: l, + w: os.Stdout, } } @@ -33,6 +33,16 @@ func (l *Logger) WithWriter(w io.Writer) *Logger { return l } +func (l Logger) Fatal(v ...interface{}) { + l.log(knoxite.LogLevelFatal, v...) + os.Exit(1) +} + +func (l Logger) Fatalf(format string, v ...interface{}) { + l.logf(knoxite.LogLevelFatal, format, v...) + os.Exit(1) +} + func (l Logger) Warn(v ...interface{}) { l.log(knoxite.LogLevelWarning, v...) } @@ -41,6 +51,14 @@ func (l Logger) Warnf(format string, v ...interface{}) { l.logf(knoxite.LogLevelWarning, format, v...) } +func (l Logger) Print(v ...interface{}) { + l.log(knoxite.LogLevelPrint, v...) +} + +func (l Logger) Printf(format string, v ...interface{}) { + l.logf(knoxite.LogLevelPrint, format, v...) +} + func (l Logger) Info(v ...interface{}) { l.log(knoxite.LogLevelInfo, v...) } @@ -57,30 +75,22 @@ func (l Logger) Debugf(format string, v ...interface{}) { l.logf(knoxite.LogLevelDebug, format, v...) } -func (l Logger) Fatal(v ...interface{}) { - l.log(knoxite.LogLevelFatal, v...) - os.Exit(1) -} - -func (l Logger) Fatalf(format string, v ...interface{}) { - l.logf(knoxite.LogLevelFatal, format, v...) - os.Exit(1) -} - -func (l Logger) log(verbosity knoxite.Verbosity, v ...interface{}) { - if verbosity <= l.VerbosityLevel { - l.printV(verbosity, v...) +func (l Logger) log(logLevel knoxite.LogLevel, v ...interface{}) { + if logLevel <= l.LogLevel { + l.printV(logLevel, v...) } } -func (l Logger) logf(verbosity knoxite.Verbosity, format string, v ...interface{}) { - if verbosity <= l.VerbosityLevel { - l.printV(verbosity, fmt.Sprintf(format, v...)) +func (l Logger) logf(logLevel knoxite.LogLevel, format string, v ...interface{}) { + if logLevel <= l.LogLevel { + l.printV(logLevel, fmt.Sprintf(format, v...)) } } -func (l Logger) printV(verbosity knoxite.Verbosity, v ...interface{}) { - _, _ = l.w.Write([]byte(verbosity.String() + ": ")) +func (l Logger) printV(logLevel knoxite.LogLevel, v ...interface{}) { + if logLevel != knoxite.LogLevelPrint { + _, _ = l.w.Write([]byte(logLevel.String() + ": ")) + } _, _ = l.w.Write([]byte(fmt.Sprint(v...))) _, _ = l.w.Write([]byte("\n")) } diff --git a/cmd/knoxite/main.go b/cmd/knoxite/main.go index 53e2b96..a31d64a 100644 --- a/cmd/knoxite/main.go +++ b/cmd/knoxite/main.go @@ -10,9 +10,6 @@ package main import ( - "fmt" - "io/ioutil" - "log" "os" "syscall" @@ -41,7 +38,8 @@ type GlobalOptions struct { Alias string Password string ConfigURL string - Verbosity string + Verbose bool + LogLevel string } var ( @@ -57,31 +55,32 @@ var ( Short: "Knoxite is a data storage & backup tool", Long: "Knoxite is a secure and flexible data storage and backup tool\n" + "Complete documentation is available at https://github.com/knoxite/knoxite", - SilenceErrors: true, - SilenceUsage: true, + SilenceErrors: true, + SilenceUsage: true, DisableAutoGenTag: true, } - logger knoxite.Logger + log knoxite.Logger ) func main() { shutdown.OnSignal(0, os.Interrupt, syscall.SIGTERM) - // quiet shutdown logger - shutdown.Logger = shutdown.LogPrinter(log.New(ioutil.Discard, "", log.LstdFlags)) + // use quiet knoxite.NopLogger as shutdown logger + shutdown.Logger = shutdown.LogPrinter(knoxite.NopLogger{}) // shutdown.SetTimeout(0) RootCmd.PersistentFlags().StringVarP(&globalOpts.Repo, "repo", "r", "", "Repository directory to backup to/restore from (default: current working dir)") RootCmd.PersistentFlags().StringVarP(&globalOpts.Alias, "alias", "R", "", "Repository alias to backup to/restore from") RootCmd.PersistentFlags().StringVar(&globalOpts.Password, "password", "", "Password to use for data encryption") RootCmd.PersistentFlags().StringVarP(&globalOpts.ConfigURL, "configURL", "C", config.DefaultPath(), "Path to the configuration file") - RootCmd.PersistentFlags().StringVarP(&globalOpts.Verbosity, "verbose", "v", "Warning", "Verbose output: possible levels are Debug, Info and Warning") + RootCmd.PersistentFlags().StringVar(&globalOpts.LogLevel, "loglevel", "Print", "Verbose output. Possible levels are Debug, Info, Warning and Fatal") + RootCmd.PersistentFlags().BoolVarP(&globalOpts.Verbose, "verbose", "v", false, "Verbose output on log level Info. Use --loglevel to choose between Debug, Info, Warning and Fatal") globalOpts.Repo = os.Getenv("KNOXITE_REPOSITORY") globalOpts.Password = os.Getenv("KNOXITE_PASSWORD") if err := RootCmd.Execute(); err != nil { - fmt.Println(err) + log.Fatal(err) os.Exit(-1) } } @@ -101,8 +100,21 @@ func init() { } func initLogger() { - logger = *NewLogger(utils.VerbosityTypeFromString(globalOpts.Verbosity)). + if globalOpts.Verbose { + globalOpts.LogLevel = "Info" + } + + logLevel, err := utils.LogLevelFromString(globalOpts.LogLevel) + + log = *NewLogger(logLevel). WithWriter(os.Stdout) + + if err != nil { + log.Warnf("Error setting log level \"%s\": %s. Using default log level Info instead.", globalOpts.LogLevel, err) + } + + // set logger for knoxite lib + knoxite.SetLogger(log) } // initConfig initializes the configuration for knoxite. @@ -111,19 +123,19 @@ func initLogger() { func initConfig() { // We dont allow both flags to be set as this can lead to unclear instructions. if RootCmd.PersistentFlags().Changed("repo") && RootCmd.PersistentFlags().Changed("alias") { - logger.Fatalf("Specify either repository directory '-r' or an alias '-R'") + log.Fatalf("Specify either repository directory '-r' or an alias '-R'") return } var err error cfg, err = config.New(globalOpts.ConfigURL) if err != nil { - logger.Fatalf("error reading the config file: %v", err) + log.Fatalf("Error reading the config file: %v", err) return } if err = cfg.Load(); err != nil { - logger.Fatalf("error parsing the toml config file at '%s': %v", cfg.URL().Path, err) + log.Fatalf("Error parsing the toml config file at '%s': %v", cfg.URL().Path, err) return } @@ -137,7 +149,7 @@ func initConfig() { if globalOpts.Alias != "" { rep, ok := cfg.Repositories[globalOpts.Alias] if !ok { - logger.Fatalf("error loading the specified alias") + log.Fatalf("Error loading the specified alias") return } diff --git a/cmd/knoxite/utils/utils.go b/cmd/knoxite/utils/utils.go index c370757..a89df30 100644 --- a/cmd/knoxite/utils/utils.go +++ b/cmd/knoxite/utils/utils.go @@ -24,9 +24,10 @@ import ( ) var ( - ErrPasswordMismatch = errors.New("Passwords did not match") + ErrPasswordMismatch = errors.New("passwords did not match") ErrEncryptionUnknown = errors.New("unknown encryption format") ErrCompressionUnknown = errors.New("unknown compression format") + ErrLogLevelUnknown = errors.New("unknown log level") ) func ReadPassword(prompt string) (string, error) { @@ -193,16 +194,21 @@ func PathToUrl(u string) (*url.URL, error) { return url, nil } -// VerbosityTypeFromString returns the verbosity type from a user-specified string. -func VerbosityTypeFromString(s string) knoxite.Verbosity { +// LogLevelFromString returns the log level from a user-specified string. +// returns log level print as default. +func LogLevelFromString(s string) (knoxite.LogLevel, error) { switch strings.ToLower(s) { + case "fatal": + return knoxite.LogLevelFatal, nil case "warning": - return knoxite.LogLevelWarning + return knoxite.LogLevelWarning, nil + case "print": + return knoxite.LogLevelPrint, nil case "info": - return knoxite.LogLevelInfo + return knoxite.LogLevelInfo, nil case "debug": - return knoxite.LogLevelDebug + return knoxite.LogLevelDebug, nil default: - return knoxite.LogLevelWarning + return knoxite.LogLevelPrint, ErrLogLevelUnknown } } diff --git a/logger.go b/logger.go index 9612154..d8712fe 100644 --- a/logger.go +++ b/logger.go @@ -13,6 +13,8 @@ type Logger interface { Fatalf(format string, v ...interface{}) Warn(v ...interface{}) Warnf(format string, v ...interface{}) + Print(v ...interface{}) + Printf(format string, v ...interface{}) Info(v ...interface{}) Infof(format string, v ...interface{}) Debug(v ...interface{}) @@ -27,14 +29,22 @@ func SetLogger(l Logger) { log = l } -// NopLogger will be used by default if no logger has been set via SetLogger(). +// The quiet NopLogger will be used by default if no logger has been set via SetLogger(). type NopLogger struct { } +func (nl NopLogger) Fatal(v ...interface{}) {} + +func (nl NopLogger) Fatalf(format string, v ...interface{}) {} + func (nl NopLogger) Warn(v ...interface{}) {} func (nl NopLogger) Warnf(format string, v ...interface{}) {} +func (nl NopLogger) Print(v ...interface{}) {} + +func (nl NopLogger) Printf(format string, v ...interface{}) {} + func (nl NopLogger) Info(v ...interface{}) {} func (nl NopLogger) Infof(format string, v ...interface{}) {} @@ -42,7 +52,3 @@ func (nl NopLogger) Infof(format string, v ...interface{}) {} func (nl NopLogger) Debug(v ...interface{}) {} func (nl NopLogger) Debugf(format string, v ...interface{}) {} - -func (nl NopLogger) Fatal(v ...interface{}) {} - -func (nl NopLogger) Fatalf(format string, v ...interface{}) {} diff --git a/verbosity.go b/loglevel.go similarity index 63% rename from verbosity.go rename to loglevel.go index 1982fd7..0754e90 100644 --- a/verbosity.go +++ b/loglevel.go @@ -8,16 +8,17 @@ package knoxite -// verbosity levels for logging. -type Verbosity int +// log levels for logging. +type LogLevel int const ( LogLevelFatal = iota LogLevelWarning + LogLevelPrint LogLevelInfo LogLevelDebug ) -func (v Verbosity) String() string { - return [...]string{"Fatal", "Warning", "Info", "Debug"}[v] +func (l LogLevel) String() string { + return [...]string{"Fatal", "Warning", "Print", "Info", "Debug"}[l] }