From 9e654521ae12debf40f181dfe291ad4ded0f7524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20T=C3=B6lle?= Date: Sat, 4 May 2024 23:45:58 +0200 Subject: [PATCH] feat(cli): hide redundant log attributes --- cmd/root.go | 28 ++++++++++++++++++------- internal/ui/slog_handler.go | 42 +++++++++++++++++++++++++++++++++++++ main.go | 8 ------- 3 files changed, 63 insertions(+), 15 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index feacb5c..9863f51 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -37,13 +37,7 @@ var rootCmd = &cobra.Command{ PersistentPreRun: func(cmd *cobra.Command, _ []string) { ctx := cmd.Context() - logLevel := slog.LevelInfo - if verbose >= 1 { - logLevel = slog.LevelDebug - } - slog.SetDefault(slog.New(ui.NewHandler(os.Stdout, &ui.HandlerOptions{ - Level: logLevel, - }))) + slog.SetDefault(initLogger()) // Add logger to command context logger := slog.Default() @@ -54,6 +48,26 @@ var rootCmd = &cobra.Command{ }, } +func initLogger() *slog.Logger { + logLevel := slog.LevelInfo + if verbose >= 1 { + logLevel = slog.LevelDebug + } + + return slog.New(ui.NewHandler(os.Stdout, &ui.HandlerOptions{ + Level: logLevel, + ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { + // Remove attributes that are unnecessary for the cli context + if a.Key == "library" || a.Key == "method" { + return slog.Attr{} + } + + return a + }, + })) + +} + func newClient(ctx context.Context) *hcloudimages.Client { logger := contextlogger.From(ctx) // Build hcloud-go client diff --git a/internal/ui/slog_handler.go b/internal/ui/slog_handler.go index d688d3d..6b6dd96 100644 --- a/internal/ui/slog_handler.go +++ b/internal/ui/slog_handler.go @@ -8,6 +8,9 @@ import ( "sync" ) +// Developed with guidance from golang docs: +// https://github.com/golang/example/blob/32022caedd6a177a7717aa8680cbe179e1045935/slog-handler-guide/README.md + const ( ansiClear = "\033[0m" ansiBold = "\033[1m" @@ -23,8 +26,41 @@ type Handler struct { out io.Writer } +// HandlerOptions are a subset of [slog.HandlerOptions] that are implemented for the UI handler. type HandlerOptions struct { + // Level reports the minimum record level that will be logged. + // The handler discards records with lower levels. + // If Level is nil, the handler assumes LevelInfo. + // The handler calls Level.Level for each record processed; + // to adjust the minimum level dynamically, use a LevelVar. Level slog.Leveler + + // ReplaceAttr is called to rewrite each non-group attribute before it is logged. + // The attribute's value has been resolved (see [Value.Resolve]). + // If ReplaceAttr returns a zero Attr, the attribute is discarded. + // + // The built-in attributes with keys "time", "level", "source", and "msg" + // are passed to this function, except that time is omitted + // if zero, and source is omitted if AddSource is false. + // + // The first argument is a list of currently open groups that contain the + // Attr. It must not be retained or modified. ReplaceAttr is never called + // for Group attributes, only their contents. For example, the attribute + // list + // + // Int("a", 1), Group("g", Int("b", 2)), Int("c", 3) + // + // results in consecutive calls to ReplaceAttr with the following arguments: + // + // nil, Int("a", 1) + // []string{"g"}, Int("b", 2) + // nil, Int("c", 3) + // + // ReplaceAttr can be used to change the default keys of the built-in + // attributes, convert types (for example, to replace a `time.Time` with the + // integer seconds since the Unix epoch), sanitize personal information, or + // remove attributes from the output. + ReplaceAttr func(groups []string, a slog.Attr) slog.Attr } // groupOrAttrs holds either a group name or a list of [slog.Attr]. @@ -108,6 +144,12 @@ func (h *Handler) Handle(_ context.Context, record slog.Record) error { func (h *Handler) appendAttr(buf []byte, group string, a slog.Attr) []byte { a.Value = a.Value.Resolve() + + if h.opts.ReplaceAttr != nil { + a = h.opts.ReplaceAttr([]string{group}, a) + } + + // No-op if null attr if a.Equal(slog.Attr{}) { return buf } diff --git a/main.go b/main.go index afb6e32..4e74f2c 100644 --- a/main.go +++ b/main.go @@ -1,17 +1,9 @@ package main import ( - "log/slog" - "os" - "github.com/apricote/hcloud-upload-image/cmd" - "github.com/apricote/hcloud-upload-image/internal/ui" ) -func init() { - slog.SetDefault(slog.New(ui.NewHandler(os.Stdout, &ui.HandlerOptions{Level: slog.LevelDebug}))) -} - func main() { cmd.Execute() }