diff --git a/cmd/root.go b/cmd/root.go index a83f604b..826b4295 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,6 +5,7 @@ import ( "os" "strings" + "github.com/jetstack/preflight/pkg/logs" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -17,6 +18,9 @@ var rootCmd = &cobra.Command{ configuration checks using Open Policy Agent (OPA). Preflight checks are bundled into Packages`, + PersistentPreRun: func(cmd *cobra.Command, args []string) { + logs.Initialize() + }, } func init() { @@ -28,6 +32,8 @@ func init() { // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { + logs.AddFlags(rootCmd.PersistentFlags()) + if err := rootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) diff --git a/pkg/logs/logs.go b/pkg/logs/logs.go index 042281ae..6029eee2 100644 --- a/pkg/logs/logs.go +++ b/pkg/logs/logs.go @@ -1,8 +1,54 @@ package logs import ( + "io" "log" + "log/slog" "os" + + "github.com/spf13/pflag" ) -var Log = log.New(os.Stderr, "", log.LstdFlags) +// Deprecated: Log is a `log` logger, which is being phased out. +var Log = log.Default() + +// Write logs to stdout by default +var logOutput io.Writer = os.Stdout + +// SetOutput changes the global log output writer +func SetOutput(w io.Writer) { + logOutput = w +} + +var logLevel int + +// AddFlags adds log related flags to the supplied flag set +func AddFlags(fs *pflag.FlagSet) { + fs.IntVarP(&logLevel, + "log-level", "v", int(slog.LevelInfo), + "Set the logging verbosity. 8: >= ERROR, 4: >= WARN, 0: >=INFO, -4: >= DEBUG") +} + +// Initialize configures the global log and slog loggers to write JSON to stdout. +// +// Errors, warnings, info and debug messages are all logged to stdout. +// By default, log messages with level >= INFO will be written. +// If verbose logging is enabled, log messages with level >= DEBUG will be written. +// +// The log module doesn't support levels. All its messages will be logged in +// JSON format, at INFO level. +func Initialize() { + // This is a work around to remove the `vcert: ` prefix which is added by the vcert module. + // See https://github.com/Venafi/vcert/pull/512 + log.SetPrefix("") + slog.SetLogLoggerLevel(slog.LevelInfo) + + level := slog.Level(logLevel) + logger := slog.New( + slog.NewJSONHandler(logOutput, &slog.HandlerOptions{ + Level: level, + }), + ) + // This sets both the global slog logger and the global legacy log logger. + slog.SetDefault(logger) +}