log
log copied to clipboard
improve json handling of `slog.Group` fields
was checking this out as a way of improving displayed logs however noticed that slog.Group
fields are represented differently for both the text and json formatter
Here is the output from the sample code included below
INFO charm text formatter req="[method=POST url=example.com]" map=map[foo:bar] list="[1 2 3]"
level=INFO msg="slog text formatter" req.method=POST req.url=example.com map=map[foo:bar] list="[1 2 3]"
{"level":"info","list":"[1 2 3]","map":"map[foo:bar]","msg":"charm json formatter","req":"[method=POST url=example.com]"}
{"level":"INFO","msg":"slog json formatter","req":{"method":"POST","url":"example.com"},"map":{"foo":"bar"},"list":[1,2,3]}
for the text formatter while req.method & req.url
would be preferred it is still usable. however for the json output the representation is not a nested map, this becomes less valuable since parsing that data becomes more difficult as cannot use the same json parsing/selecting expressions with jq
ex. to get the method i could use jq '.req.method'
however that will no longer work with the charm json formatter
Update: seems to not be specific to group
using map or list
value also does not get encoded as json
Here is the sample code for reproduction
package main
import (
"log/slog"
"os"
"github.com/charmbracelet/log"
)
func RemoveTime(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey && len(groups) == 0 {
return slog.Attr{}
}
return a
}
func main() {
ct := slog.New(log.NewWithOptions(os.Stdout, log.Options{}))
cj := slog.New(log.NewWithOptions(os.Stdout, log.Options{Formatter: log.JSONFormatter}))
st := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{ReplaceAttr: RemoveTime}))
sj := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: RemoveTime}))
g := slog.Group("req",
slog.String("method", "POST"),
slog.String("url", "example.com"),
)
m := map[string]string{"foo": "bar"}
l := []int{1, 2, 3}
ct.Info("charm text formatter", g, "map", m, "list", l)
st.Info("slog text formatter", g, "map", m, "list", l)
cj.Info("charm json formatter", g, "map", m, "list", l)
sj.Info("slog json formatter", g, "map", m, "list", l)
}