Skip to content

Commit

Permalink
add draft for slog logger
Browse files Browse the repository at this point in the history
  • Loading branch information
glebnaz committed Nov 13, 2023
1 parent 8fc2cd9 commit be86c26
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 6 deletions.
12 changes: 6 additions & 6 deletions log/context.go → log/context_logrus.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ import (
// for fields
type ctxFieldsKey string

var key = ctxFieldsKey("logrusFields")
var ctxKeyLogrusFields = ctxFieldsKey("logrusFields")

// for logrus.Entry
type ctxEntryKey string
type ctxEntryKeyFields string

var entryKey = ctxEntryKey("logrusEntry")
var entryKey = ctxEntryKeyFields("logrusEntry")

// AddFieldsToCTX adds fields to ctx
func AddFieldsToCTX(ctx context.Context, fields logrus.Fields) context.Context {
return context.WithValue(ctx, key, fields)
return context.WithValue(ctx, ctxKeyLogrusFields, fields)
}

func GetFieldsFromCTX(ctx context.Context) logrus.Fields {
fields, ok := ctx.Value(key).(logrus.Fields)
fields, ok := ctx.Value(ctxKeyLogrusFields).(logrus.Fields)
if !ok {
fields = logrus.Fields{}
}
Expand All @@ -31,7 +31,7 @@ func GetFieldsFromCTX(ctx context.Context) logrus.Fields {

// NewFromCTX returns a new logrus.Entry with fields from ctx
func NewFromCTX(ctx context.Context) *logrus.Entry {
fields, ok := ctx.Value(key).(logrus.Fields)
fields, ok := ctx.Value(ctxKeyLogrusFields).(logrus.Fields)
if !ok {
fields = logrus.Fields{}
}
Expand Down
28 changes: 28 additions & 0 deletions log/context_slog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package log

import (
"context"
"log/slog"
)

type ctxKeySLOGAttr string

var ctxKeySlOGAttr = ctxKeySLOGAttr("attr")

// AddSLOGAttrToCTX adds slog attr to ctx
func AddSLOGAttrToCTX(ctx context.Context, attrs []slog.Attr) context.Context {
oldAttrs := GetSLOGAttrFromCTX(ctx)
if oldAttrs != nil {
attrs = append(oldAttrs, attrs...)
}
return context.WithValue(ctx, ctxKeySlOGAttr, attrs)
}

// GetSLOGAttrFromCTX returns slog attrs from ctx
func GetSLOGAttrFromCTX(ctx context.Context) []slog.Attr {
attrs, ok := ctx.Value(ctxKeySlOGAttr).([]slog.Attr)
if !ok {
attrs = nil
}
return attrs
}
35 changes: 35 additions & 0 deletions log/slog_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package log

import (
"context"
"log/slog"
)

type CTXAttrHandler struct {
slog.Handler
}

// NewCTXAttrHandler
//
// is a slog.Handler that adds slog.Attr to slog.Record from context.Context
func NewCTXAttrHandler(serviceName string, mainHandler slog.Handler) CTXAttrHandler {
mainHandler.WithAttrs([]slog.Attr{
slog.String("service", serviceName),
},
)

return CTXAttrHandler{
Handler: mainHandler,
}
}

func (p CTXAttrHandler) Handle(ctx context.Context, record slog.Record) error {
attrs := GetSLOGAttrFromCTX(ctx)
if attrs == nil {
return p.Handler.Handle(ctx, record)
}

record.AddAttrs(attrs...)

return p.Handler.Handle(ctx, record)
}
76 changes: 76 additions & 0 deletions log/slog_handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package log

import (
"bytes"
"context"
"log/slog"
"strings"
"testing"
)

func TestCTXAttrHandler(t *testing.T) {
type kv struct {
key string
value string
}

type args struct {
kv []kv
}
tests := []struct {
name string
args args
}{
{
name: "simple test with one attr in ctx",
args: args{
kv: []kv{
{
key: "req-id",
value: "123",
},
},
},
},
{
name: "simple test with two attr in ctx",
args: args{
kv: []kv{
{
key: "req-id",
value: "123",
},
{
key: "name",
value: "John Doe",
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
for _, kv := range tt.args.kv {
ctx = AddSLOGAttrToCTX(ctx, []slog.Attr{slog.String(kv.key, kv.value)})
}

buf := &bytes.Buffer{}
defer buf.Truncate(len(buf.Bytes()))

handler := NewCTXAttrHandler("test", slog.NewJSONHandler(buf, nil))
logger := slog.New(handler)
logger.InfoContext(ctx, "test")
str := buf.String()

for _, kv := range tt.args.kv {
if !strings.Contains(str, kv.key) {
t.Errorf("JSONCTXHandlerBase() = %v, want %v", str, kv.key)
}
if !strings.Contains(str, kv.value) {
t.Errorf("JSONCTXHandlerBase() = %v, want %v", str, kv.value)
}
}
})
}
}

0 comments on commit be86c26

Please sign in to comment.