forked from getsentry/sentry-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
span_recorder.go
57 lines (51 loc) · 1.47 KB
/
span_recorder.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
package sentry
import (
"sync"
)
// maxSpans limits the number of recorded spans per transaction. The limit is
// meant to bound memory usage and prevent too large transaction events that
// would be rejected by Sentry.
const maxSpans = 1000
// A spanRecorder stores a span tree that makes up a transaction. Safe for
// concurrent use. It is okay to add child spans from multiple goroutines.
type spanRecorder struct {
mu sync.Mutex
spans []*Span
overflowOnce sync.Once
}
// record stores a span. The first stored span is assumed to be the root of a
// span tree.
func (r *spanRecorder) record(s *Span) {
r.mu.Lock()
defer r.mu.Unlock()
if len(r.spans) >= maxSpans {
r.overflowOnce.Do(func() {
root := r.spans[0]
Logger.Printf("Too many spans: dropping spans from transaction with TraceID=%s SpanID=%s limit=%d",
root.TraceID, root.SpanID, maxSpans)
})
// TODO(tracing): mark the transaction event in some way to
// communicate that spans were dropped.
return
}
r.spans = append(r.spans, s)
}
// root returns the first recorded span. Returns nil if none have been recorded.
func (r *spanRecorder) root() *Span {
r.mu.Lock()
defer r.mu.Unlock()
if len(r.spans) == 0 {
return nil
}
return r.spans[0]
}
// children returns a list of all recorded spans, except the root. Returns nil
// if there are no children.
func (r *spanRecorder) children() []*Span {
r.mu.Lock()
defer r.mu.Unlock()
if len(r.spans) < 2 {
return nil
}
return r.spans[1:]
}