1
2
3
4
5 package benchmarks
6
7
8
9 import (
10 "context"
11 "fmt"
12 "io"
13 "log/slog"
14 "log/slog/internal/buffer"
15 "strconv"
16 "time"
17 )
18
19
20
21
22
23
24
25
26 type fastTextHandler struct {
27 w io.Writer
28 }
29
30 func newFastTextHandler(w io.Writer) slog.Handler {
31 return &fastTextHandler{w: w}
32 }
33
34 func (h *fastTextHandler) Enabled(context.Context, slog.Level) bool { return true }
35
36 func (h *fastTextHandler) Handle(_ context.Context, r slog.Record) error {
37 buf := buffer.New()
38 defer buf.Free()
39
40 if !r.Time.IsZero() {
41 buf.WriteString("time=")
42 h.appendTime(buf, r.Time)
43 buf.WriteByte(' ')
44 }
45 buf.WriteString("level=")
46 *buf = strconv.AppendInt(*buf, int64(r.Level), 10)
47 buf.WriteByte(' ')
48 buf.WriteString("msg=")
49 buf.WriteString(r.Message)
50 r.Attrs(func(a slog.Attr) bool {
51 buf.WriteByte(' ')
52 buf.WriteString(a.Key)
53 buf.WriteByte('=')
54 h.appendValue(buf, a.Value)
55 return true
56 })
57 buf.WriteByte('\n')
58 _, err := h.w.Write(*buf)
59 return err
60 }
61
62 func (h *fastTextHandler) appendValue(buf *buffer.Buffer, v slog.Value) {
63 switch v.Kind() {
64 case slog.KindString:
65 buf.WriteString(v.String())
66 case slog.KindInt64:
67 *buf = strconv.AppendInt(*buf, v.Int64(), 10)
68 case slog.KindUint64:
69 *buf = strconv.AppendUint(*buf, v.Uint64(), 10)
70 case slog.KindFloat64:
71 *buf = strconv.AppendFloat(*buf, v.Float64(), 'g', -1, 64)
72 case slog.KindBool:
73 *buf = strconv.AppendBool(*buf, v.Bool())
74 case slog.KindDuration:
75 *buf = strconv.AppendInt(*buf, v.Duration().Nanoseconds(), 10)
76 case slog.KindTime:
77 h.appendTime(buf, v.Time())
78 case slog.KindAny:
79 a := v.Any()
80 switch a := a.(type) {
81 case error:
82 buf.WriteString(a.Error())
83 default:
84 fmt.Fprint(buf, a)
85 }
86 default:
87 panic(fmt.Sprintf("bad kind: %s", v.Kind()))
88 }
89 }
90
91 func (h *fastTextHandler) appendTime(buf *buffer.Buffer, t time.Time) {
92 *buf = strconv.AppendInt(*buf, t.Unix(), 10)
93 }
94
95 func (h *fastTextHandler) WithAttrs([]slog.Attr) slog.Handler {
96 panic("fastTextHandler: With unimplemented")
97 }
98
99 func (*fastTextHandler) WithGroup(string) slog.Handler {
100 panic("fastTextHandler: WithGroup unimplemented")
101 }
102
103
104
105
106
107
108
109
110
111 type asyncHandler struct {
112 ringBuffer [100]slog.Record
113 next int
114 }
115
116 func newAsyncHandler() *asyncHandler {
117 return &asyncHandler{}
118 }
119
120 func (*asyncHandler) Enabled(context.Context, slog.Level) bool { return true }
121
122 func (h *asyncHandler) Handle(_ context.Context, r slog.Record) error {
123 h.ringBuffer[h.next] = r.Clone()
124 h.next = (h.next + 1) % len(h.ringBuffer)
125 return nil
126 }
127
128 func (*asyncHandler) WithAttrs([]slog.Attr) slog.Handler {
129 panic("asyncHandler: With unimplemented")
130 }
131
132 func (*asyncHandler) WithGroup(string) slog.Handler {
133 panic("asyncHandler: WithGroup unimplemented")
134 }
135
136
137 type disabledHandler struct{}
138
139 func (disabledHandler) Enabled(context.Context, slog.Level) bool { return false }
140 func (disabledHandler) Handle(context.Context, slog.Record) error { panic("should not be called") }
141
142 func (disabledHandler) WithAttrs([]slog.Attr) slog.Handler {
143 panic("disabledHandler: With unimplemented")
144 }
145
146 func (disabledHandler) WithGroup(string) slog.Handler {
147 panic("disabledHandler: WithGroup unimplemented")
148 }
149
View as plain text