Piping JSON output through jq is worth exploring. This much is enough to be nicer to human eyes:
cat log.json | jq -c 'del(.time)' There's a nice Go implementation at https://github.com/itchyny/gojq. On Tuesday, August 29, 2023 at 12:59:55 AM UTC-7 Marcello H wrote: > After playing with it some more: > > This also does the trick > > h := NewHandler(os.Stdout, &MyOptions{Level: slog.LevelDebug, TimeFormat: > time.DateTime}) > l := slog.New(h) > slog.SetDefault(l) > > slog.Debug("hello") > slog.Info("hello") > slog.Warn("hello") > slog.Error("hello") > > > > > > type MyOptions struct { > // Enable source code location (Default: false) > AddSource bool > > // Minimum level to log (Default: slog.LevelInfo) > Level slog.Leveler > > // ReplaceAttr is called to rewrite each non-group attribute before it is > logged. > // See https://pkg.go.dev/log/slog#HandlerOptions for details. > ReplaceAttr func(groups []string, attr slog.Attr) slog.Attr > > // Time format (Default: time.StampMilli) > TimeFormat string > } > > type MyHandler struct { > opts MyOptions > prefix string // preformatted group names followed by a dot > preformat string // preformatted Attrs, with an initial space > timeFormat string > > mu sync.Mutex > w io.Writer > } > > func NewHandler(w io.Writer, opts *MyOptions) *MyHandler { > h := &MyHandler{w: w} > if opts != nil { > h.opts = *opts > } > if h.opts.ReplaceAttr == nil { > h.opts.ReplaceAttr = func(_ []string, a slog.Attr) slog.Attr { return a } > } > if opts.TimeFormat != "" { > h.timeFormat = opts.TimeFormat > } > > return h > } > > func (h *MyHandler) Enabled(ctx context.Context, level slog.Level) bool { > minLevel := slog.LevelInfo > if h.opts.Level != nil { > minLevel = h.opts.Level.Level() > } > return level >= minLevel > } > > func (h *MyHandler) WithGroup(name string) slog.Handler { > return &MyHandler{ > w: h.w, > opts: h.opts, > preformat: h.preformat, > prefix: h.prefix + name + ".", > } > } > > func (h *MyHandler) WithAttrs(attrs []slog.Attr) slog.Handler { > var buf []byte > for _, a := range attrs { > buf = h.appendAttr(buf, h.prefix, a) > } > return &MyHandler{ > w: h.w, > opts: h.opts, > prefix: h.prefix, > preformat: h.preformat + string(buf), > } > } > > func (h *MyHandler) Handle(ctx context.Context, r slog.Record) error { > var buf []byte > if !r.Time.IsZero() { > buf = r.Time.AppendFormat(buf, h.timeFormat) > buf = append(buf, ' ') > } > > levText := (r.Level.String() + " ")[0:5] > > buf = append(buf, levText...) > buf = append(buf, ' ') > if h.opts.AddSource && r.PC != 0 { > fs := runtime.CallersFrames([]uintptr{r.PC}) > f, _ := fs.Next() > buf = append(buf, f.File...) > buf = append(buf, ':') > buf = strconv.AppendInt(buf, int64(f.Line), 10) > buf = append(buf, ' ') > } > buf = append(buf, r.Message...) > buf = append(buf, h.preformat...) > r.Attrs(func(a slog.Attr) bool { > buf = h.appendAttr(buf, h.prefix, a) > return true > }) > buf = append(buf, '\n') > h.mu.Lock() > defer h.mu.Unlock() > _, err := h.w.Write(buf) > return err > } > > func (h *MyHandler) appendAttr(buf []byte, prefix string, a slog.Attr) [] > byte { > if a.Equal(slog.Attr{}) { > return buf > } > if a.Value.Kind() != slog.KindGroup { > buf = append(buf, ' ') > buf = append(buf, prefix...) > buf = append(buf, a.Key...) > buf = append(buf, '=') > return fmt.Appendf(buf, "%v", a.Value.Any()) > } > // Group > if a.Key != "" { > prefix += a.Key + "." > } > for _, a := range a.Value.Group() { > buf = h.appendAttr(buf, prefix, a) > } > return buf > } > > > Op di 29 aug 2023 om 09:16 schreef 'Sean Liao' via golang-nuts < > golan...@googlegroups.com>: > >> cycle: >> https://go.dev//issues/61892 >> >> default handler, copied/exported: >> https://pkg.go.dev/github.com/jba/slog/handlers/loghandler >> >> - sean >> >> >> On Tue, Aug 29, 2023 at 7:53 AM Marcello H <marc...@gmail.com> wrote: >> >>> Yesterday, I came up with the same question and found this: >>> "github.com/lmittmann/tint" >>> >>> (This solution still uses os.Stdout, but I think this can do what you >>> need.) >>> >>> An example: >>> logOptions := &tint.Options{ >>> NoColor: true, >>> Level: slog.LevelError, >>> TimeFormat: time.DateTime, >>> } >>> logHandler := tint.NewHandler(os.Stdout, logOptions) >>> logger := slog.New(logHandler) >>> slog.SetDefault(logger) >>> slog.Info("this does not show") >>> slog.Debug("this debug info does not show") >>> logOptions.Level = slog.LevelInfo >>> slog.Info("this is now visible") >>> slog.Debug("this debug info still does not show") >>> logOptions.Level = slog.LevelDebug >>> slog.Info("this is still visible") >>> slog.Debug("this debug info also shows") >>> Op dinsdag 29 augustus 2023 om 03:00:01 UTC+2 schreef Mike Schinkel: >>> >>>> Hi Tamás, >>>> >>>> Have you actually tried that and gotten it to work? It does not compile >>>> for me but this does (note method call vs. property reference): >>>> >>>> slog.SetDefault(slog.New(myHandler{Handler:slog.Default().Handler()})) >>>> >>>> However, when delegating the Handle() method it seems to cause an >>>> infinite >>>> loop: >>>> >>>> func (m MyHandler) Handle(ctx context.Context, r slog.Record) error { >>>> return m.Handler.Handle(ctx, r) >>>> } >>>> >>>> See https://goplay.tools/snippet/qw07m0YflLd >>>> >>>> I know about this because just this past weekend I was trying to write a >>>> TeeHandler to output the default to the screen and JSON to a file just >>>> this >>>> past weekend and ran into an infinite loop problem with the default >>>> handler. >>>> >>>> I tried my best to figure out why it needed to be structured the way it >>>> was >>>> in that it seems to call itself recursively. I wanted to post a >>>> question to >>>> this list to see if there was a workaround, or if not to see if there >>>> might >>>> be interest in allowing it to work, but I could not get my head around >>>> it so >>>> eventually gave up and just used the TextHandler instead. >>>> >>>> Shame though. It would be nice to be able to reuse the default handler >>>> but >>>> AFACT it is not possible (though if I am wrong I would love for someone >>>> to >>>> show me how to get it to work.) >>>> >>>> -Mike >>>> >>>> >>>> On Monday, August 28, 2023 at 12:50:50 PM UTC-4 Tamás Gulácsi wrote: >>>> >>>> slog.SetDefault(slog.New(myHandler{Handler:slog.Default().Handler})) >>>> >>>> vl...@mailbox.org a következőt írta (2023. augusztus 28., hétfő, >>>> 15:06:37 UTC+2): >>>> >>>> Hi, >>>> >>>> When reading trough the log/slog documentation, it seems one can create >>>> a logger with a different handler, which is either NewTextHandler or >>>> NewJSONHandler. >>>> >>>> Why can't I configure the defaultHandler? Let's say I want my logger to >>>> behave exactly like the defaultHandler, but output to a logfile or >>>> Stdout instead. >>>> >>>> The defaultHandler's output is different compared to the >>>> NewTextHandler: >>>> >>>> slog.Info("ok"), gives me: >>>> >>>> INFO ok >>>> >>>> The NextTextHandler gives me: >>>> >>>> level=INFO msg="ok" >>>> >>>> >>>> Regards, >>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "golang-nuts" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to golang-nuts...@googlegroups.com. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/golang-nuts/df136f1e-0283-46fa-a0b7-ce17a0722fd9n%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/golang-nuts/df136f1e-0283-46fa-a0b7-ce17a0722fd9n%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- >> > You received this message because you are subscribed to a topic in the >> Google Groups "golang-nuts" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/golang-nuts/aJPXT2NF-Lc/unsubscribe. >> To unsubscribe from this group and all its topics, send an email to >> golang-nuts...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/CAGabyPo9NZJBf%3Dj-W_8tUS%3DqkmwHRWVpjCbFz04jZW_P8KEOow%40mail.gmail.com >> >> <https://groups.google.com/d/msgid/golang-nuts/CAGabyPo9NZJBf%3Dj-W_8tUS%3DqkmwHRWVpjCbFz04jZW_P8KEOow%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/0808c106-f722-462e-bb50-238530a7837an%40googlegroups.com.