Compare commits
No commits in common. "master" and "v1.1.0" have entirely different histories.
3 changed files with 0 additions and 117 deletions
|
|
@ -81,11 +81,3 @@ func WithAttrsFromTime(attrsFromTime func(time.Time) []slog.Attr) HandlerOption
|
||||||
jh.attrsFromTime = attrsFromTime
|
jh.attrsFromTime = attrsFromTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithAttrsFromLevel supplies a function which can optionally map the given
|
|
||||||
// log level onto zero or more attributes.
|
|
||||||
func WithAttrsFromLevel(attrsFromLevel func(slog.Level) []slog.Attr) HandlerOption {
|
|
||||||
return func(jh *JournalHandler) {
|
|
||||||
jh.attrsFromLevel = attrsFromLevel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -62,10 +62,6 @@ type JournalHandler struct {
|
||||||
// Time from an [slog.Record]. It may be nil.
|
// Time from an [slog.Record]. It may be nil.
|
||||||
attrsFromTime func(time.Time) []slog.Attr
|
attrsFromTime func(time.Time) []slog.Attr
|
||||||
|
|
||||||
// attrsFromLevel may return zero or more attributes to represent the
|
|
||||||
// log level. It may be nil.
|
|
||||||
attrsFromLevel func(slog.Level) []slog.Attr
|
|
||||||
|
|
||||||
// groups are the ordered group names added by WithGroup. We need to
|
// groups are the ordered group names added by WithGroup. We need to
|
||||||
// maintain the full list, not just a pre-rendered prefix string,
|
// maintain the full list, not just a pre-rendered prefix string,
|
||||||
// because of the API of replaceAttr.
|
// because of the API of replaceAttr.
|
||||||
|
|
@ -178,13 +174,6 @@ func (jh *JournalHandler) Handle(ctx context.Context, rec slog.Record) error {
|
||||||
}
|
}
|
||||||
addAttrs = append(addAttrs, jh.attrsFromContext(ctx)...)
|
addAttrs = append(addAttrs, jh.attrsFromContext(ctx)...)
|
||||||
}
|
}
|
||||||
if jh.attrsFromLevel != nil {
|
|
||||||
if addAttrs == nil {
|
|
||||||
addAttrs = attrPoolGet()
|
|
||||||
defer attrPoolPut(addAttrs)
|
|
||||||
}
|
|
||||||
addAttrs = append(addAttrs, jh.attrsFromLevel(rec.Level)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 for journal.Conn.Entry (MESSAGE and PRIORITY),
|
// 2 for journal.Conn.Entry (MESSAGE and PRIORITY),
|
||||||
// 3 for SRC_* (optional but we always allocate space)
|
// 3 for SRC_* (optional but we always allocate space)
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,7 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
"testing/slogtest"
|
|
||||||
"time"
|
|
||||||
"uuid"
|
|
||||||
|
|
||||||
"src.lwithers.me.uk/go/journal"
|
"src.lwithers.me.uk/go/journal"
|
||||||
"src.lwithers.me.uk/go/journal/testsink"
|
"src.lwithers.me.uk/go/journal/testsink"
|
||||||
|
|
@ -86,97 +82,3 @@ type slowValue string
|
||||||
func (s slowValue) LogValue() slog.Value {
|
func (s slowValue) LogValue() slog.Value {
|
||||||
return slog.StringValue(string(s))
|
return slog.StringValue(string(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestSlog integrates with [testing/slogtest].
|
|
||||||
func TestSlog(t *testing.T) {
|
|
||||||
tmpdir := t.TempDir()
|
|
||||||
|
|
||||||
attrsFromTime := func(t time.Time) []slog.Attr {
|
|
||||||
return []slog.Attr{
|
|
||||||
{
|
|
||||||
Key: "TEST_TIME",
|
|
||||||
Value: slog.StringValue(t.Format(time.RFC3339Nano)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
attrsFromLevel := func(l slog.Level) []slog.Attr {
|
|
||||||
return []slog.Attr{
|
|
||||||
{
|
|
||||||
Key: "TEST_LEVEL",
|
|
||||||
Value: slog.StringValue(l.String()),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: this relies on [slogtest.Run] executing its test cases
|
|
||||||
// completely sequentially
|
|
||||||
var curSink *testsink.Sink
|
|
||||||
|
|
||||||
newHandler := func(t *testing.T) slog.Handler {
|
|
||||||
sockpath := filepath.Join(tmpdir, uuid.New().String())
|
|
||||||
sink, err := testsink.New(sockpath)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create test sink: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := journal.Connect(sockpath)
|
|
||||||
if err != nil {
|
|
||||||
sink.Stop()
|
|
||||||
t.Fatalf("failed to connect to test sink socket: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
h, err := NewHandler(WithConn(conn), WithAttrsFromTime(attrsFromTime), WithAttrsFromLevel(attrsFromLevel), WithHandlerOptions(slog.HandlerOptions{
|
|
||||||
Level: slog.LevelInfo,
|
|
||||||
}))
|
|
||||||
if err != nil {
|
|
||||||
sink.Stop()
|
|
||||||
t.Fatalf("failed to create handler: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
curSink = sink
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
result := func(t *testing.T) map[string]any {
|
|
||||||
defer curSink.Stop()
|
|
||||||
|
|
||||||
m, err := curSink.Message(0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to fetch message from test sink: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, attrs, err := m.Decode()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to decode message from test sink: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
out := make(map[string]any)
|
|
||||||
out[slog.MessageKey] = msg
|
|
||||||
for i := range attrs {
|
|
||||||
k, v := attrs[i].Key, attrs[i].Val
|
|
||||||
switch k {
|
|
||||||
case "TEST_TIME":
|
|
||||||
out[slog.TimeKey] = v
|
|
||||||
case "TEST_LEVEL":
|
|
||||||
out[slog.LevelKey] = v
|
|
||||||
default:
|
|
||||||
parts := strings.Split(k, "_")
|
|
||||||
Ng := len(parts) - 1 // number of groups
|
|
||||||
g := out
|
|
||||||
for i := range Ng {
|
|
||||||
next, _ := g[parts[i]].(map[string]any)
|
|
||||||
if next == nil {
|
|
||||||
next = make(map[string]any)
|
|
||||||
g[parts[i]] = next
|
|
||||||
}
|
|
||||||
g = next
|
|
||||||
}
|
|
||||||
g[strings.ToLower(parts[Ng])] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
slogtest.Run(t, newHandler, result)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue