charmbracelet / charmbracelet/log
Improve rendering of pointers to structs inside of slices and maps
- Dominant language
- Go
- Stars
- 3.4k
- Forks
- 103
- PR merge metrics
- No merged PRs in 30d
Description
### Description
It would be great to be able to render pointers to structs contained inside slices and maps better.
This could be done either by an improved rendering by default or through some way to configure the way that attributes are rendered.
I wrote a simple helper to compare `devslog`, `log`, `slog` with text formatter and `slog` with `json` formatter:
```
go run telnesstech.com/cmd
[13:58:41] INFO devslog
S slice: 1 []*main.testingStruct
0: *main.testingStruct
Name: slice1
S ptr : *main.testingStruct
Name: test
M map : 1 map[string]*main.testingStruct
key: main.testingStruct
Name: test
2025/09/26 13:58:41 INFO charmbracelet/log slice=[0x140001260c0] ptr=&{Name:test} map=map[key:0x140001260e0]
time=2025-09-26T13:58:41.584+02:00 level=INFO msg=slog slice=[0x140001260c0] ptr=&{Name:test} map=map[key:0x140001260e0]
{"time":"2025-09-26T13:58:41.584822+02:00","level":"INFO","msg":"slog","slice":[{"Name":"slice1"}],"ptr":{"Name":"test"},"map":{"key":{"Name":"test"}}}
```
`devslog` does this by default which is very useful, especially as it mirrors what is likely to mirror the production-behavior when using `json` formatter. The relevant code from `devslogs` [starts around here](https://github.com/golang-cz/devslog/blob/master/devslog.go#L375-L386).
Another alternative would also be to have an option similar to slog's `ReplaceAttr` to allow the user themselves to configure how attributes are rendered, making this possible to implement yourself.
Code to print the demo above.
```go
package main
import (
"log/slog"
"os"
"github.com/charmbracelet/log"
"github.com/golang-cz/devslog"
)
func main() {
slice := []*testingStruct{{Name: "slice1"}}
ptr := &testingStruct{Name: "test"}
m := map[string]*testingStruct{"key": {Name: "test"}}
slog.New(devslog.NewHandler(os.Stdout, nil)).With("slice", slice, "ptr", ptr, "map", m).Info("devslog")
log.With("slice", slice, "ptr", ptr, "map", m).Info("charmbracelet/slog")
slog.New(slog.NewTextHandler(os.Stdout, nil)).With("slice", slice, "ptr", ptr, "map", m).Info("slog")
slog.New(slog.NewJSONHandler(os.Stdout, nil)).With("slice", slice, "ptr", ptr, "map", m).Info("slog")
}
type testingStruct struct {
Name string
}
```
Contributor guide
Research direction
Use the provided Go demo as the reproduction and compare the current output for pointers to structs in slices and maps with the linked devslog.go rendering logic. The change is done when those nested values render structurally like the JSON formatter, or when an equivalent user configuration is available; no repository file or test is named in the issue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- observability-sre
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100