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.

Reply via email to