-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlog.go
More file actions
113 lines (98 loc) · 2.31 KB
/
log.go
File metadata and controls
113 lines (98 loc) · 2.31 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
package tracing
import (
"context"
"encoding/json"
"fmt"
"log/slog"
"sort"
"time"
)
type Log struct {
Time time.Time `json:"time"`
Level slog.Level `json:"level"`
Message string `json:"msg"`
Attributes map[string]any `json:"attributes,omitempty"`
}
func (l *Log) UnmarshalJSON(data []byte) error {
var rawMap map[string]json.RawMessage
if err := json.Unmarshal(data, &rawMap); err != nil {
return err
}
l.Attributes = make(map[string]any)
for k, v := range rawMap {
switch k {
case "time":
if err := json.Unmarshal(v, &l.Time); err != nil {
return fmt.Errorf("unmarshal %q: %w", k, err)
}
case "msg":
if err := json.Unmarshal(v, &l.Message); err != nil {
return fmt.Errorf("unmarshal %q: %w", k, err)
}
case "level":
if err := json.Unmarshal(v, &l.Level); err != nil {
return fmt.Errorf("unmarshal %q: %w", k, err)
}
default:
var value any
if err := json.Unmarshal(v, &value); err != nil {
return fmt.Errorf("unmarshal %q: %w", k, err)
}
l.Attributes[k] = value
}
}
return nil
}
func ExtractLogs(ctx context.Context, logger *slog.Logger, span *Span) error {
logs, err := span.getLogs()
if err != nil {
return err
}
sort.Slice(logs, func(i, j int) bool {
return logs[i].Time.Before(logs[j].Time)
})
for _, log := range logs {
attrs := make([]slog.Attr, 0, len(log.Attributes))
for k, v := range log.Attributes {
attrs = append(attrs, slog.Any(k, v))
}
record := slog.Record{
Level: log.Level,
Message: log.Message,
Time: log.Time,
}
record.AddAttrs(attrs...)
_ = logger.Handler().Handle(ctx, record)
}
return nil
}
func (s *Span) getLogs() ([]*Log, error) {
logs := make([]*Log, len(s.Logs))
for i, log := range s.Logs {
if err := json.Unmarshal(log, &logs[i]); err != nil {
return nil, err
}
}
for _, child := range s.Children {
childLogs, err := child.getLogs()
if err != nil {
return nil, err
}
logs = append(logs, childLogs...)
}
if s.Metadata != nil {
if msg, ok := s.Metadata["exception.message"].(string); ok {
attrs := make(map[string]any)
for k, v := range s.Annotations {
attrs[k] = v
}
logs = append(logs, &Log{
Time: s.EndTime,
Level: slog.LevelError,
Message: msg,
Attributes: attrs,
})
}
}
return logs, nil
}