Skip to content

Commit d1df6e1

Browse files
committed
updated NewHandler(io.Writer) to NewHandler(io.Writer, *Options)
* dropped `Options.NewHandler` * use `slog.Source` instead of `runtime.Frame`
1 parent a6123dc commit d1df6e1

3 files changed

Lines changed: 48 additions & 41 deletions

File tree

buffer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ type buffer []byte
77
var bufPool = sync.Pool{
88
New: func() any {
99
b := make(buffer, 0, 1024)
10-
return &b
10+
return (*buffer)(&b)
1111
},
1212
}
1313

handler.go

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ const (
3838
const keyErr = "err"
3939

4040
var (
41-
defaultTimeFormat = time.StampMilli
4241
defaultLevel = slog.LevelInfo
42+
defaultTimeFormat = time.StampMilli
4343
)
4444

4545
// Options for a slog.Handler that writes tinted logs. A zero Options consists
@@ -64,32 +64,30 @@ type Options struct {
6464
NoColor bool
6565
}
6666

67-
// NewHandler creates a [slog.Handler] that writes tinted logs to Writer w with
68-
// the given options.
69-
func (opts Options) NewHandler(w io.Writer) slog.Handler {
67+
// NewHandler creates a [slog.Handler] that writes tinted logs to Writer w,
68+
// using the default options. If opts is nil, the default options are used.
69+
func NewHandler(w io.Writer, opts *Options) slog.Handler {
7070
h := &handler{
71-
w: w,
72-
addSource: opts.AddSource,
73-
level: defaultLevel,
74-
replaceAttr: opts.ReplaceAttr,
75-
timeFormat: defaultTimeFormat,
76-
noColor: opts.NoColor,
71+
w: w,
72+
level: defaultLevel,
73+
timeFormat: defaultTimeFormat,
7774
}
75+
if opts == nil {
76+
return h
77+
}
78+
79+
h.addSource = opts.AddSource
7880
if opts.Level != nil {
7981
h.level = opts.Level.Level()
8082
}
83+
h.replaceAttr = opts.ReplaceAttr
8184
if opts.TimeFormat != "" {
8285
h.timeFormat = opts.TimeFormat
8386
}
87+
h.noColor = opts.NoColor
8488
return h
8589
}
8690

87-
// NewHandler creates a [slog.Handler] that writes tinted logs to Writer w,
88-
// using the default options.
89-
func NewHandler(w io.Writer) slog.Handler {
90-
return Options{}.NewHandler(w)
91-
}
92-
9391
// handler implements a [slog.Handler].
9492
type handler struct {
9593
attrs string
@@ -165,10 +163,16 @@ func (h *handler) Handle(_ context.Context, r slog.Record) error {
165163
fs := runtime.CallersFrames([]uintptr{r.PC})
166164
f, _ := fs.Next()
167165
if f.File != "" {
166+
src := &slog.Source{
167+
Function: f.Function,
168+
File: f.File,
169+
Line: f.Line,
170+
}
171+
168172
if rep == nil {
169-
h.appendSource(buf, f)
173+
h.appendSource(buf, src)
170174
buf.WriteByte(' ')
171-
} else if a := rep(h.groupsSlice, slog.Any(slog.SourceKey, f)); a.Key != "" {
175+
} else if a := rep(h.groupsSlice, slog.Any(slog.SourceKey, src)); a.Key != "" {
172176
appendValue(buf, a.Value, false)
173177
buf.WriteByte(' ')
174178
}
@@ -277,13 +281,13 @@ func (h *handler) appendLevel(buf *buffer, level slog.Level) {
277281
}
278282
}
279283

280-
func (h *handler) appendSource(buf *buffer, f runtime.Frame) {
281-
dir, file := filepath.Split(f.File)
284+
func (h *handler) appendSource(buf *buffer, src *slog.Source) {
285+
dir, file := filepath.Split(src.File)
282286

283287
buf.WriteStringIf(!h.noColor, ansiFaint)
284288
buf.WriteString(filepath.Join(filepath.Base(dir), file))
285289
buf.WriteByte(':')
286-
buf.WriteString(strconv.Itoa(f.Line))
290+
buf.WriteString(strconv.Itoa(src.Line))
287291
buf.WriteStringIf(!h.noColor, ansiReset)
288292
}
289293

handler_test.go

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ import (
1818
var faketime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
1919

2020
func Example() {
21-
slog.SetDefault(slog.New(tint.Options{
21+
slog.SetDefault(slog.New(tint.NewHandler(os.Stderr, &tint.Options{
2222
Level: slog.LevelDebug,
2323
TimeFormat: time.Kitchen,
24-
}.NewHandler(os.Stderr)))
24+
})))
2525

2626
slog.Info("Starting server", "addr", ":8080", "env", "production")
2727
slog.Debug("Connected to DB", "db", "myapp", "host", "localhost:5432")
@@ -39,7 +39,7 @@ func TestHandler(t *testing.T) {
3939
}
4040

4141
tests := []struct {
42-
Opts tint.Options
42+
Opts *tint.Options
4343
F func(l *slog.Logger)
4444
Want string
4545
}{
@@ -92,7 +92,7 @@ func TestHandler(t *testing.T) {
9292
Want: `Nov 10 23:00:00.000 INF test slice="[a b c]" map="map[a:1 b:2 c:3]"`,
9393
},
9494
{
95-
Opts: tint.Options{
95+
Opts: &tint.Options{
9696
AddSource: true,
9797
},
9898
F: func(l *slog.Logger) {
@@ -101,7 +101,7 @@ func TestHandler(t *testing.T) {
101101
Want: `Nov 10 23:00:00.000 INF tint/handler_test.go:99 test key=val`,
102102
},
103103
{
104-
Opts: tint.Options{
104+
Opts: &tint.Options{
105105
TimeFormat: time.Kitchen,
106106
},
107107
F: func(l *slog.Logger) {
@@ -110,7 +110,7 @@ func TestHandler(t *testing.T) {
110110
Want: `11:00PM INF test key=val`,
111111
},
112112
{
113-
Opts: tint.Options{
113+
Opts: &tint.Options{
114114
ReplaceAttr: drop(slog.TimeKey),
115115
},
116116
F: func(l *slog.Logger) {
@@ -119,7 +119,7 @@ func TestHandler(t *testing.T) {
119119
Want: `INF test key=val`,
120120
},
121121
{
122-
Opts: tint.Options{
122+
Opts: &tint.Options{
123123
ReplaceAttr: drop(slog.LevelKey),
124124
},
125125
F: func(l *slog.Logger) {
@@ -128,7 +128,7 @@ func TestHandler(t *testing.T) {
128128
Want: `Nov 10 23:00:00.000 test key=val`,
129129
},
130130
{
131-
Opts: tint.Options{
131+
Opts: &tint.Options{
132132
ReplaceAttr: drop(slog.MessageKey),
133133
},
134134
F: func(l *slog.Logger) {
@@ -137,7 +137,7 @@ func TestHandler(t *testing.T) {
137137
Want: `Nov 10 23:00:00.000 INF key=val`,
138138
},
139139
{
140-
Opts: tint.Options{
140+
Opts: &tint.Options{
141141
ReplaceAttr: drop(slog.TimeKey, slog.LevelKey, slog.MessageKey),
142142
},
143143
F: func(l *slog.Logger) {
@@ -146,7 +146,7 @@ func TestHandler(t *testing.T) {
146146
Want: `key=val`,
147147
},
148148
{
149-
Opts: tint.Options{
149+
Opts: &tint.Options{
150150
ReplaceAttr: drop("key"),
151151
},
152152
F: func(l *slog.Logger) {
@@ -155,7 +155,7 @@ func TestHandler(t *testing.T) {
155155
Want: `Nov 10 23:00:00.000 INF test`,
156156
},
157157
{
158-
Opts: tint.Options{
158+
Opts: &tint.Options{
159159
ReplaceAttr: drop("key"),
160160
},
161161
F: func(l *slog.Logger) {
@@ -164,7 +164,7 @@ func TestHandler(t *testing.T) {
164164
Want: `Nov 10 23:00:00.000 INF test group.key=val group.key2=val2`,
165165
},
166166
{
167-
Opts: tint.Options{
167+
Opts: &tint.Options{
168168
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
169169
if a.Key == "key" && len(groups) == 1 && groups[0] == "group" {
170170
return slog.Attr{}
@@ -178,7 +178,7 @@ func TestHandler(t *testing.T) {
178178
Want: `Nov 10 23:00:00.000 INF test group.key2=val2`,
179179
},
180180
{
181-
Opts: tint.Options{
181+
Opts: &tint.Options{
182182
ReplaceAttr: replace(slog.IntValue(42), slog.TimeKey),
183183
},
184184
F: func(l *slog.Logger) {
@@ -187,7 +187,7 @@ func TestHandler(t *testing.T) {
187187
Want: `42 INF test key=val`,
188188
},
189189
{
190-
Opts: tint.Options{
190+
Opts: &tint.Options{
191191
ReplaceAttr: replace(slog.StringValue("INFO"), slog.LevelKey),
192192
},
193193
F: func(l *slog.Logger) {
@@ -196,7 +196,7 @@ func TestHandler(t *testing.T) {
196196
Want: `Nov 10 23:00:00.000 INFO test key=val`,
197197
},
198198
{
199-
Opts: tint.Options{
199+
Opts: &tint.Options{
200200
ReplaceAttr: replace(slog.IntValue(42), slog.MessageKey),
201201
},
202202
F: func(l *slog.Logger) {
@@ -205,7 +205,7 @@ func TestHandler(t *testing.T) {
205205
Want: `Nov 10 23:00:00.000 INF 42 key=val`,
206206
},
207207
{
208-
Opts: tint.Options{
208+
Opts: &tint.Options{
209209
ReplaceAttr: replace(slog.IntValue(42), "key"),
210210
},
211211
F: func(l *slog.Logger) {
@@ -214,7 +214,7 @@ func TestHandler(t *testing.T) {
214214
Want: `Nov 10 23:00:00.000 INF test key=42 key2=val2`,
215215
},
216216
{
217-
Opts: tint.Options{
217+
Opts: &tint.Options{
218218
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
219219
return slog.Attr{}
220220
},
@@ -266,8 +266,11 @@ func TestHandler(t *testing.T) {
266266
for i, test := range tests {
267267
t.Run(strconv.Itoa(i), func(t *testing.T) {
268268
var buf bytes.Buffer
269+
if test.Opts == nil {
270+
test.Opts = &tint.Options{}
271+
}
269272
test.Opts.NoColor = true
270-
l := slog.New(test.Opts.NewHandler(&buf))
273+
l := slog.New(tint.NewHandler(&buf, test.Opts))
271274
test.F(l)
272275

273276
got := strings.TrimRight(buf.String(), "\n")
@@ -319,7 +322,7 @@ func BenchmarkLogAttrs(b *testing.B) {
319322
Name string
320323
H slog.Handler
321324
}{
322-
{"tint", tint.NewHandler(io.Discard)},
325+
{"tint", tint.NewHandler(io.Discard, nil)},
323326
{"text", slog.NewTextHandler(io.Discard, nil)},
324327
{"json", slog.NewJSONHandler(io.Discard, nil)},
325328
{"discard", new(discarder)},

0 commit comments

Comments
 (0)