cloudflare/pint

Public

mirrored fromhttps://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.75.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/log/handler.go

127lines · modecode

1package log
2
3import (
4 "bytes"
5 "context"
6 "encoding/json"
7 "fmt"
8 "io"
9 "log/slog"
10 "strings"
11 "sync"
12
13 "github.com/cloudflare/pint/internal/output"
14)
15
16type handler struct {
17 dst io.Writer
18
19 escaper *strings.Replacer
20 level slog.Level
21 mtx sync.Mutex
22 noColor bool
23}
24
25func newHandler(dst io.Writer, level slog.Level, noColor bool) *handler {
26 h := handler{
27 mtx: sync.Mutex{},
28 dst: dst,
29 level: level,
30 noColor: noColor,
31 escaper: strings.NewReplacer(`"`, `\"`),
32 }
33 return &h
34}
35
36func (h *handler) Enabled(_ context.Context, level slog.Level) bool {
37 return level >= h.level
38}
39
40func (h *handler) Handle(_ context.Context, record slog.Record) error {
41 buf := bytes.NewBuffer(make([]byte, 0, 128))
42
43 var lc output.Color
44 switch record.Level {
45 case slog.LevelInfo:
46 lc = output.White
47 case slog.LevelError:
48 lc = output.Red
49 case slog.LevelWarn:
50 lc = output.Yellow
51 case slog.LevelDebug:
52 lc = output.Magenta
53 }
54 h.printKey(buf, "level")
55 h.printVal(buf, record.Level.String(), lc)
56 _, _ = buf.WriteRune(' ')
57 h.printKey(buf, "msg")
58 h.printVal(buf, record.Message, output.White)
59
60 record.Attrs(func(attr slog.Attr) bool {
61 _, _ = buf.WriteRune(' ')
62 h.appendAttr(buf, attr)
63 return true
64 })
65 _, _ = buf.WriteRune('\n')
66
67 h.mtx.Lock()
68 defer h.mtx.Unlock()
69
70 if _, err := buf.WriteTo(h.dst); err != nil {
71 return fmt.Errorf("failed to write buffer: %w", err)
72 }
73
74 return nil
75}
76
77func (h *handler) WithAttrs(_ []slog.Attr) slog.Handler {
78 return h
79}
80
81func (h *handler) WithGroup(_ string) slog.Handler {
82 return h
83}
84
85func (h *handler) printKey(buf *bytes.Buffer, s string) {
86 _, _ = buf.WriteString(output.MaybeColor(output.Dim, h.noColor, s+"="))
87}
88
89func (h *handler) printVal(buf *bytes.Buffer, s string, color output.Color) {
90 if !strings.HasPrefix(s, "[") && !strings.HasPrefix(s, "{") && strings.Contains(s, " ") {
91 s = "\"" + h.escaper.Replace(s) + "\""
92 }
93 _, _ = buf.WriteString(output.MaybeColor(color, h.noColor, s))
94}
95
96func (h *handler) appendAttr(buf *bytes.Buffer, attr slog.Attr) {
97 attr.Value = attr.Value.Resolve()
98
99 h.printKey(buf, attr.Key)
100
101 // nolint: exhaustive
102 switch attr.Value.Kind() {
103 case slog.KindAny:
104 switch attr.Value.Any().(type) {
105 case error:
106 h.printVal(buf, formatString(attr), output.Red)
107 default:
108 h.printVal(buf, formatAny(attr), output.Cyan)
109 }
110 case slog.KindString:
111 h.printVal(buf, formatString(attr), output.Cyan)
112 default:
113 h.printVal(buf, formatAny(attr), output.Blue)
114 }
115}
116
117func formatAny(attr slog.Attr) string {
118 data, err := json.Marshal(attr.Value.Any())
119 if err != nil {
120 return attr.Value.String()
121 }
122 return string(data)
123}
124
125func formatString(attr slog.Attr) string {
126 return strings.ReplaceAll(attr.Value.String(), "\n", "\\n")
127}
128