From 6ad109849085aab8cfb1ae04aa9a4b4315d59911 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Thu, 22 Aug 2024 16:15:46 +0600 Subject: [PATCH] feat: add deferredLogger --- pkg/commands/app.go | 14 ++++-------- pkg/flag/options.go | 10 ++++---- pkg/log/deferred.go | 56 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 pkg/log/deferred.go diff --git a/pkg/commands/app.go b/pkg/commands/app.go index 280d1fa3cc2e..1728efdb8f04 100644 --- a/pkg/commands/app.go +++ b/pkg/commands/app.go @@ -65,12 +65,6 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e // NewApp is the factory method to return Trivy CLI func NewApp() *cobra.Command { cobra.EnableTraverseRunHooks = true // To execute persistent pre-run hooks from all parents. - - // Initialize the logger for `flag` and `app` packages. - // To display logs from these packages in Trivy format. - // We will set the `debug` and `disable` format after parsing the `--debug` and `--quiet` flags. - log.InitLogger(false, false) - globalFlags := flag.NewGlobalFlagGroup() rootCmd := NewRootCommand(globalFlags) rootCmd.AddGroup( @@ -134,7 +128,7 @@ func loadPluginCommands() []*cobra.Command { var commands []*cobra.Command plugins, err := plugin.NewManager().LoadAll(ctx) if err != nil { - log.DebugContext(ctx, "No plugins loaded") + log.DeferredLogger.Debug("No plugins loaded") return nil } for _, p := range plugins { @@ -166,13 +160,13 @@ func initConfig(configFile string, pathChanged bool) error { if err := viper.ReadInConfig(); err != nil { if errors.Is(err, os.ErrNotExist) { if !pathChanged { - log.Debugf("Default config file %q not found, using built in values", log.FilePath(configFile)) + log.DeferredLogger.Debug(fmt.Sprintf("Default config file %q not found, using built in values", log.FilePath(configFile))) return nil } } return xerrors.Errorf("config file %q loading error: %s", configFile, err) } - log.Info("Loaded", log.FilePath(configFile)) + log.DeferredLogger.Info("Loaded", log.FilePath(configFile)) return nil } @@ -222,6 +216,8 @@ func NewRootCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { // Initialize logger log.InitLogger(globalOptions.Debug, globalOptions.Quiet) + // Print log messages waiting for logger initialization + log.DeferredLogger.PrintLogs() return nil }, diff --git a/pkg/flag/options.go b/pkg/flag/options.go index e00aa4cfa922..eeb848351bcd 100644 --- a/pkg/flag/options.go +++ b/pkg/flag/options.go @@ -119,10 +119,10 @@ func (f *Flag[T]) Parse() error { } if f.Deprecated != "" && f.isSet() { - log.Warnf(`"--%s" is deprecated. %s`, f.Name, f.Deprecated) + log.DeferredLogger.Warn(fmt.Sprintf(`"--%s" is deprecated. %s`, f.Name, f.Deprecated)) } if f.Removed != "" && f.isSet() { - log.Errorf(`"--%s" was removed. %s`, f.Name, f.Removed) + log.DeferredLogger.Error(fmt.Sprintf(`"--%s" was removed. %s`, f.Name, f.Removed)) return xerrors.Errorf(`removed flag ("--%s")`, f.Name) } @@ -140,7 +140,7 @@ func (f *Flag[T]) parse() any { } v = viper.Get(alias.ConfigName) if v != nil { - log.Warnf("'%s' in config file is deprecated. Use '%s' instead.", alias.ConfigName, f.ConfigName) + log.DeferredLogger.Warn(fmt.Sprintf("'%s' in config file is deprecated. Use '%s' instead.", alias.ConfigName, f.ConfigName)) return v } } @@ -307,7 +307,7 @@ func (f *Flag[T]) BindEnv() error { } if alias.Deprecated { if _, ok := os.LookupEnv(envAlias); ok { - log.Warnf("'%s' is deprecated. Use '%s' instead.", envAlias, envName) + log.DeferredLogger.Warn(fmt.Sprintf("'%s' is deprecated. Use '%s' instead.", envAlias, envName)) } } } @@ -848,7 +848,7 @@ func (a flagAliases) NormalizeFunc() func(*pflag.FlagSet, string) pflag.Normaliz if alias.deprecated { // NormalizeFunc is called several times alias.once.Do(func() { - log.Warnf("'--%s' is deprecated. Use '--%s' instead.", name, alias.formalName) + log.DeferredLogger.Warn(fmt.Sprintf("'--%s' is deprecated. Use '--%s' instead.", name, alias.formalName)) }) } name = alias.formalName diff --git a/pkg/log/deferred.go b/pkg/log/deferred.go new file mode 100644 index 000000000000..fb455ae02beb --- /dev/null +++ b/pkg/log/deferred.go @@ -0,0 +1,56 @@ +package log + +// DeferredLogger are needed to save logs and print them after calling `PrintLogs()` command. +// for example, this may be necessary when the logger is not yet initialized, but messages need to be transmitted +// in this case, the messages are saved and printed after the logger is initialized +var DeferredLogger deferredLogger + +type deferredLogger struct { + deferredLogs []deferredLog +} + +type deferredLog struct { + logFunc func(format string, args ...any) + message string + args []any +} + +func (d *deferredLogger) Debug(message string, args ...any) { + d.deferredLogs = append(d.deferredLogs, deferredLog{ + logFunc: Debug, + message: message, + args: args, + }) +} + +func (d *deferredLogger) Info(message string, args ...any) { + d.deferredLogs = append(d.deferredLogs, deferredLog{ + logFunc: Info, + message: message, + args: args, + }) +} + +func (d *deferredLogger) Warn(message string, args ...any) { + d.deferredLogs = append(d.deferredLogs, deferredLog{ + logFunc: Warn, + message: message, + args: args, + }) +} + +func (d *deferredLogger) Error(message string, args ...any) { + d.deferredLogs = append(d.deferredLogs, deferredLog{ + logFunc: Error, + message: message, + args: args, + }) +} + +func (d *deferredLogger) PrintLogs() { + for _, l := range d.deferredLogs { + l.logFunc(l.message, l.args...) + } + // Clear deferredLogs + d.deferredLogs = nil +}