-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdebug.go
More file actions
135 lines (122 loc) · 3.26 KB
/
Copy pathdebug.go
File metadata and controls
135 lines (122 loc) · 3.26 KB
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package sdk
import (
"encoding/json"
"fmt"
"log/slog"
"os"
"sort"
"strings"
"github.com/bubustack/bubu-sdk-go/runtime"
"github.com/bubustack/core/contracts"
)
const debugPreviewLimit = 2048
var truthyDebugValues = map[string]struct{}{
"1": {},
"true": {},
"t": {},
"yes": {},
"y": {},
"on": {},
"debug": {},
}
func isDebugEnabled() bool {
raw := strings.TrimSpace(os.Getenv(contracts.DebugEnv))
if raw == "" {
return false
}
_, ok := truthyDebugValues[strings.ToLower(raw)]
return ok
}
// DebugModeEnabled reports whether verbose logging should be forced regardless of logger level.
func DebugModeEnabled() bool {
return isDebugEnabled()
}
func newDefaultLogger() *slog.Logger {
opts := &slog.HandlerOptions{}
if isDebugEnabled() {
opts.Level = slog.LevelDebug
}
return slog.New(slog.NewJSONHandler(os.Stdout, opts))
}
func logExecutionContextDebug(logger *slog.Logger, data *runtime.ExecutionContextData) {
if !isDebugEnabled() || logger == nil || data == nil {
return
}
attrs := []slog.Attr{
slog.String("story", data.StoryInfo.StoryName),
slog.String("storyRun", data.StoryInfo.StoryRunID),
slog.String("step", data.StoryInfo.StepName),
slog.String("stepRun", data.StoryInfo.StepRunID),
slog.String("namespace", data.StoryInfo.StepRunNamespace),
slog.String("mode", data.Execution.Mode),
slog.Time("startedAt", data.StartedAt.Time),
}
if len(data.Inputs) > 0 {
attrs = append(attrs,
slog.Int("inputFields", len(data.Inputs)),
debugPreviewAttr("inputsPreview", data.Inputs),
)
}
if len(data.Config) > 0 {
attrs = append(attrs,
slog.Int("configFields", len(data.Config)),
debugPreviewAttr("configPreview", data.Config),
)
}
if len(data.Transports) > 0 {
names := make([]string, 0, len(data.Transports))
for _, t := range data.Transports {
if strings.TrimSpace(t.Name) != "" {
names = append(names, strings.TrimSpace(t.Name))
}
}
if len(names) > 0 {
sort.Strings(names)
attrs = append(attrs, slog.Any("transports", names))
}
}
if len(data.Secrets) > 0 {
attrs = append(attrs, secretKeysAttr("secretKeys", data.Secrets))
}
if data.Storage != nil {
attrs = append(attrs, slog.String("storageProvider", data.Storage.Provider))
}
args := make([]any, 0, len(attrs))
for _, attr := range attrs {
args = append(args, attr)
}
logger.Debug("Execution context hydrated", args...)
}
func debugPreviewAttr(key string, value any) slog.Attr {
if value == nil {
return slog.String(key, "<nil>")
}
payload, err := json.Marshal(value)
if err != nil {
return slog.String(key, fmt.Sprintf("<marshal error: %v>", err))
}
return slog.String(key, truncateDebugPayload(payload))
}
func debugBytesAttr(key string, data []byte) slog.Attr {
if len(data) == 0 {
return slog.String(key, "<empty>")
}
return slog.String(key, truncateDebugPayload(data))
}
func secretKeysAttr(key string, secrets map[string]string) slog.Attr {
if len(secrets) == 0 {
return slog.Any(key, []string{})
}
keys := make([]string, 0, len(secrets))
for k := range secrets {
keys = append(keys, k)
}
sort.Strings(keys)
return slog.Any(key, keys)
}
func truncateDebugPayload(data []byte) string {
if len(data) <= debugPreviewLimit {
return string(data)
}
return string(data[:debugPreviewLimit]) + "...(truncated)"
}