-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathenrich.go
More file actions
67 lines (59 loc) · 2.03 KB
/
Copy pathenrich.go
File metadata and controls
67 lines (59 loc) · 2.03 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
package logger
import "context"
// --- request-scoped bound fields (MDC-equivalent) --------------------------
type ctxFieldsKey struct{}
// ContextWith returns a context carrying fields that EnrichProcessor will
// merge into every record logged with that context — the idiomatic-Go
// replacement for thread-local MDC. Repeated calls accumulate.
func ContextWith(ctx context.Context, fields ...Field) context.Context {
prev, _ := ctx.Value(ctxFieldsKey{}).([]Field)
merged := append(append(make([]Field, 0, len(prev)+len(fields)), prev...), fields...)
return context.WithValue(ctx, ctxFieldsKey{}, merged)
}
// TraceExtractor pulls correlation IDs out of a context. The core stays
// zero-dependency: contrib/otel registers a real OTEL/W3C extractor; tests or
// custom propagation can register their own.
type TraceExtractor func(ctx context.Context) (traceID, spanID string, ok bool)
// EnrichProcessor injects ctx-bound fields + trace correlation into every
// record. Place it early in the pipeline so redaction/sampling see the
// enriched record.
type EnrichProcessor struct {
Extractors []TraceExtractor
TraceKey string // default "trace_id"
SpanKey string // default "span_id"
}
// NewEnrichProcessor builds an enricher with optional trace extractors.
func NewEnrichProcessor(ex ...TraceExtractor) *EnrichProcessor {
return &EnrichProcessor{Extractors: ex, TraceKey: "trace_id", SpanKey: "span_id"}
}
// Process implements Processor.
func (e *EnrichProcessor) Process(ctx context.Context, r *Record) error {
if ctx == nil {
ctx = r.Ctx
}
if ctx == nil {
return nil
}
if bound, ok := ctx.Value(ctxFieldsKey{}).([]Field); ok && len(bound) > 0 {
r.Fields = append(r.Fields, bound...)
}
tk, sk := e.TraceKey, e.SpanKey
if tk == "" {
tk = "trace_id"
}
if sk == "" {
sk = "span_id"
}
for _, ex := range e.Extractors {
if tid, sid, ok := ex(ctx); ok {
if tid != "" {
r.Fields = append(r.Fields, String(tk, tid))
}
if sid != "" {
r.Fields = append(r.Fields, String(sk, sid))
}
break
}
}
return nil
}