Skip to content

Commit

Permalink
feat: support slog attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
op committed May 7, 2024
1 parent 77a8113 commit c335f00
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 4 deletions.
25 changes: 23 additions & 2 deletions json.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,18 @@ func (l *Logger) jsonFormatter(keyvals ...interface{}) {
jw := &jsonWriter{w: &l.b}
jw.start()

for i := 0; i < len(keyvals); i += 2 {
l.jsonFormatterKeyVal(jw, keyvals[i], keyvals[i+1])
i := 0
for i < len(keyvals) {
switch kv := keyvals[i].(type) {
case slogAttr:
l.jsonFormatterKeyVal(jw, kv.Key, kv.Value)
i++
default:
if i+1 < len(keyvals) {
l.jsonFormatterKeyVal(jw, keyvals[i], keyvals[i+1])
}
i += 2
}
}

jw.end()
Expand Down Expand Up @@ -53,6 +63,17 @@ func (l *Logger) jsonFormatterKeyVal(jw *jsonWriter, anyKey, value any) {
switch v := value.(type) {
case error:
jw.objectValue(v.Error())
case slogValue:
switch v.Kind() {
case slogKindGroup:
jw.start()
for _, attr := range v.Group() {
l.jsonFormatterKeyVal(jw, attr.Key, attr.Value)
}
jw.end()
default:
jw.objectValue(v.String())
}
case fmt.Stringer:
jw.objectValue(v.String())
default:
Expand Down
15 changes: 15 additions & 0 deletions json_121.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//go:build go1.21
// +build go1.21

package log

import "log/slog"

type (
slogAttr = slog.Attr
slogValue = slog.Value
)

const (
slogKindGroup = slog.KindGroup
)
27 changes: 27 additions & 0 deletions json_no121.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//go:build !go1.21
// +build !go1.21

package log

type (
slogAttr struct {
Key string
Value slogValue
}
slogValue struct{}
slogKind int
)

const slogKindGroup slogKind = iota

func (slogValue) String() string {
panic("should not be reached")
}

func (slogValue) Group() []slogAttr {
panic("should not be reached")
}

func (slogValue) Kind() slogKind {
panic("should not be reached")
}
28 changes: 26 additions & 2 deletions logger_121_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ package log
import (
"bytes"
"context"
"log/slog"
"testing"
"time"

"log/slog"

"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -183,3 +182,28 @@ func TestSlogCustomLevel(t *testing.T) {
})
}
}

func TestSlogAttr(t *testing.T) {
cases := []struct {
name string
expected string
keyvals []interface{}
}{
{
name: "group",
expected: `{"level":"info","msg":"message","g":{"b":"true"}}` + "\n",
keyvals: []any{slog.Group("g", slog.Bool("b", true))},
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
t.Parallel()

var buf bytes.Buffer
l := NewWithOptions(&buf, Options{Formatter: JSONFormatter})
l.Info("message", c.keyvals...)
assert.Equal(t, c.expected, buf.String())
})
}
}

0 comments on commit c335f00

Please sign in to comment.