Skip to content

Commit

Permalink
Add Msg.SlogRecord and use slog formatting to marshal it
Browse files Browse the repository at this point in the history
  • Loading branch information
anacrolix committed Aug 20, 2024
1 parent 82e1aec commit 295a78e
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 2 deletions.
4 changes: 2 additions & 2 deletions json-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ type JsonHandler struct {
SlogHandler slog.Handler
}

func NewJsonHandler(w io.Writer) *JsonHandler {
func NewJsonHandler(w io.Writer, minLevel Level) *JsonHandler {
return &JsonHandler{
SlogHandler: slog.NewJSONHandler(w, &slog.HandlerOptions{
AddSource: false,
Level: slog.LevelDebug - 4,
Level: toSlogMinLevel(minLevel),
ReplaceAttr: nil,
}),
}
Expand Down
2 changes: 2 additions & 0 deletions msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ type msgWithValues struct {
values []interface{}
}

// TODO: Support Msg.SlogRecord
func (me msgWithValues) Values(cb valueIterCallback) {
for _, v := range me.values {
if !cb(v) {
Expand Down Expand Up @@ -157,6 +158,7 @@ type msgWithText struct {
text func() string
}

// TODO: Support Msg.SlogRecord
func (me msgWithText) Text() string {
return me.text()
}
8 changes: 8 additions & 0 deletions msgimpl.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package log

import (
g "github.com/anacrolix/generics"
"log/slog"
"runtime"
)

Expand All @@ -15,6 +17,8 @@ type MsgImpl interface {
Callers(skip int, pc []uintptr) int
// Iterates over the values as added LIFO.
Values(callback valueIterCallback)
// Returns Some(slog.Record) if the Msg supports it.
SlogRecord() g.Option[slog.Record]
}

// maybe implement finalizer to ensure msgs are sunk
Expand All @@ -31,3 +35,7 @@ func (m rootMsgImpl) Callers(skip int, pc []uintptr) int {
}

func (m rootMsgImpl) Values(valueIterCallback) {}

func (m rootMsgImpl) SlogRecord() g.Option[slog.Record] {
return g.Some(slog.Record{Message: m.text()})
}
5 changes: 5 additions & 0 deletions slog-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package log

import (
"context"
g "github.com/anacrolix/generics"
"log/slog"
)

Expand Down Expand Up @@ -33,6 +34,10 @@ type slogMsg struct {
record slog.Record
}

func (s slogMsg) SlogRecord() g.Option[slog.Record] {
return g.Some(s.record)
}

func (s slogMsg) Text() string {
return s.record.Message
}
Expand Down
48 changes: 48 additions & 0 deletions slog-record-formatter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package log

import (
"bytes"
"context"
"log/slog"
"sync"
)

var (
gstbhLocker sync.Mutex
globalSlogTextBufferHandler = slogTextBufferHandler{}
)

func init() {
globalSlogTextBufferHandler.init()
}

func (me *slogTextBufferHandler) handleAppend(b []byte, r slog.Record) []byte {
me.buf.Reset()
err := me.handler.Handle(context.Background(), r)
if err != nil {
panic(err)
}
return append(b, me.buf.Bytes()...)
}

type slogTextBufferHandler struct {
buf bytes.Buffer
handler *slog.TextHandler
}

func (me *slogTextBufferHandler) init() {
me.handler = slog.NewTextHandler(&me.buf, &slog.HandlerOptions{
AddSource: false,
Level: toSlogMinLevel(NotSet),
ReplaceAttr: func(groups []string, a slog.Attr) (ret slog.Attr) {
if len(groups) == 0 {
switch a.Key {
case slog.TimeKey, slog.LevelKey:
return
}
}
ret = a
return
},
})
}
23 changes: 23 additions & 0 deletions slog.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package log

import (
"log/slog"
"math"
)

// Returns false if the level doesn't convert perfectly.
func toSlogLevel(level Level) (slog.Level, bool) {
switch level {
case Never:
Expand All @@ -27,6 +29,27 @@ func toSlogLevel(level Level) (slog.Level, bool) {
}
}

func toSlogMinLevel(level Level) slog.Level {
switch level {
case NotSet:
return math.MinInt
case Debug:
return slog.LevelDebug
case Info:
return slog.LevelInfo
case Warning:
return slog.LevelWarn
case Error:
return slog.LevelError
case Critical:
return slog.LevelError + 1
case Disabled:
return math.MaxInt
default:
panic(level)
}
}

func fromSlogLevel(sl slog.Level) Level {
switch sl {
case slog.LevelDebug:
Expand Down
8 changes: 8 additions & 0 deletions stream-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ func twoLineFormatter(msg Record) []byte {
b = append(b, name...)
}
b = append(b, "]\n "...)

slogRecord := msg.SlogRecord()
if slogRecord.Ok {
gstbhLocker.Lock()
defer gstbhLocker.Unlock()
return globalSlogTextBufferHandler.handleAppend(b, slogRecord.Value)
}

b = append(b, msg.Text()...)
msg.Values(func(value interface{}) (more bool) {
b = append(b, ' ')
Expand Down

0 comments on commit 295a78e

Please sign in to comment.