-
Notifications
You must be signed in to change notification settings - Fork 6
/
debug.go
85 lines (76 loc) · 1.93 KB
/
debug.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package main
import (
"context"
"fmt"
"os"
"runtime"
"runtime/debug"
"strings"
"sync"
"time"
"golang.org/x/exp/slog"
)
var (
debugMode bool
initLogOnce sync.Once
logger *slog.Logger
)
// debugLog writes the provided message and key/value pairs to stdout using structured logging
func debugLog(msg string, kvs ...any) {
if !debugMode {
return
}
initLogOnce.Do(func() {
opts := slog.HandlerOptions{
AddSource: true,
Level: slog.LevelDebug,
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
switch a.Key {
case slog.SourceKey:
// trim "source" down to relative path within this module
val := a.Value.String()
if idx := strings.Index(val, "github.com/CrowdStrike/perseus/"); idx != -1 {
a.Value = slog.StringValue(val[idx+31:])
}
case slog.LevelKey:
// don't output "level" since we're only ever generating debug logs
a = slog.Attr{}
default:
}
return a
},
}
if inK8S() {
logger = slog.New(opts.NewJSONHandler(os.Stdout))
} else {
logger = slog.New(opts.NewTextHandler(os.Stdout))
}
})
// golang.org/x/exp is still technically unstable and we'd rather eat a panic than crash
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "panic caught while writing debug log\n\t%v\n%s", r, string(debug.Stack()))
}
}()
ctx := context.Background()
var pcs [1]uintptr
runtime.Callers(2, pcs[:])
rec := slog.NewRecord(time.Now().UTC(), slog.LevelDebug, msg, pcs[0])
if len(kvs) > 0 {
attrs := make([]slog.Attr, 0, len(kvs)/2)
for i := 0; i < len(kvs); i += 2 {
k, ok := kvs[i].(string)
if !ok {
k = fmt.Sprintf("%v", kvs[i])
}
attrs = append(attrs, slog.Any(k, kvs[i+1]))
}
rec.AddAttrs(attrs...)
}
// TODO: what should we do if this call to logger.Handler().Handle() fails?
_ = logger.Handler().Handle(ctx, rec)
}
func inK8S() bool {
_, ok := os.LookupEnv("KUBERNETES_SERVICE_HOST")
return ok
}