1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package trace
16
17 import (
18 "context"
19 crand "crypto/rand"
20 "encoding/binary"
21 "fmt"
22 "math/rand"
23 "sync"
24 "sync/atomic"
25 "time"
26
27 "go.opencensus.io/internal"
28 "go.opencensus.io/trace/tracestate"
29 )
30
31 type tracer struct{}
32
33 var _ Tracer = &tracer{}
34
35
36
37
38
39
40 type span struct {
41
42
43
44
45
46 data *SpanData
47 mu sync.Mutex
48 spanContext SpanContext
49
50
51
52 lruAttributes *lruMap
53
54
55 annotations *evictedQueue
56
57
58 messageEvents *evictedQueue
59
60
61 links *evictedQueue
62
63
64 *spanStore
65 endOnce sync.Once
66
67 executionTracerTaskEnd func()
68 }
69
70
71
72
73 func (s *span) IsRecordingEvents() bool {
74 if s == nil {
75 return false
76 }
77 return s.data != nil
78 }
79
80
81 type TraceOptions uint32
82
83
84 func (sc SpanContext) IsSampled() bool {
85 return sc.TraceOptions.IsSampled()
86 }
87
88
89 func (sc *SpanContext) setIsSampled(sampled bool) {
90 if sampled {
91 sc.TraceOptions |= 1
92 } else {
93 sc.TraceOptions &= ^TraceOptions(1)
94 }
95 }
96
97
98 func (t TraceOptions) IsSampled() bool {
99 return t&1 == 1
100 }
101
102
103
104
105
106 type SpanContext struct {
107 TraceID TraceID
108 SpanID SpanID
109 TraceOptions TraceOptions
110 Tracestate *tracestate.Tracestate
111 }
112
113 type contextKey struct{}
114
115
116 func (t *tracer) FromContext(ctx context.Context) *Span {
117 s, _ := ctx.Value(contextKey{}).(*Span)
118 return s
119 }
120
121
122 func (t *tracer) NewContext(parent context.Context, s *Span) context.Context {
123 return context.WithValue(parent, contextKey{}, s)
124 }
125
126
127 const (
128 SpanKindUnspecified = iota
129 SpanKindServer
130 SpanKindClient
131 )
132
133
134 type StartOptions struct {
135
136
137
138
139
140
141
142
143 Sampler Sampler
144
145
146
147 SpanKind int
148 }
149
150
151 type StartOption func(*StartOptions)
152
153
154 func WithSpanKind(spanKind int) StartOption {
155 return func(o *StartOptions) {
156 o.SpanKind = spanKind
157 }
158 }
159
160
161
162 func WithSampler(sampler Sampler) StartOption {
163 return func(o *StartOptions) {
164 o.Sampler = sampler
165 }
166 }
167
168
169
170
171
172
173 func (t *tracer) StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span) {
174 var opts StartOptions
175 var parent SpanContext
176 if p := t.FromContext(ctx); p != nil {
177 if ps, ok := p.internal.(*span); ok {
178 ps.addChild()
179 }
180 parent = p.SpanContext()
181 }
182 for _, op := range o {
183 op(&opts)
184 }
185 span := startSpanInternal(name, parent != SpanContext{}, parent, false, opts)
186
187 ctx, end := startExecutionTracerTask(ctx, name)
188 span.executionTracerTaskEnd = end
189 extSpan := NewSpan(span)
190 return t.NewContext(ctx, extSpan), extSpan
191 }
192
193
194
195
196
197
198
199
200 func (t *tracer) StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o ...StartOption) (context.Context, *Span) {
201 var opts StartOptions
202 for _, op := range o {
203 op(&opts)
204 }
205 span := startSpanInternal(name, parent != SpanContext{}, parent, true, opts)
206 ctx, end := startExecutionTracerTask(ctx, name)
207 span.executionTracerTaskEnd = end
208 extSpan := NewSpan(span)
209 return t.NewContext(ctx, extSpan), extSpan
210 }
211
212 func startSpanInternal(name string, hasParent bool, parent SpanContext, remoteParent bool, o StartOptions) *span {
213 s := &span{}
214 s.spanContext = parent
215
216 cfg := config.Load().(*Config)
217 if gen, ok := cfg.IDGenerator.(*defaultIDGenerator); ok {
218
219 gen.init()
220 }
221
222 if !hasParent {
223 s.spanContext.TraceID = cfg.IDGenerator.NewTraceID()
224 }
225 s.spanContext.SpanID = cfg.IDGenerator.NewSpanID()
226 sampler := cfg.DefaultSampler
227
228 if !hasParent || remoteParent || o.Sampler != nil {
229
230
231
232
233
234 if o.Sampler != nil {
235 sampler = o.Sampler
236 }
237 s.spanContext.setIsSampled(sampler(SamplingParameters{
238 ParentContext: parent,
239 TraceID: s.spanContext.TraceID,
240 SpanID: s.spanContext.SpanID,
241 Name: name,
242 HasRemoteParent: remoteParent}).Sample)
243 }
244
245 if !internal.LocalSpanStoreEnabled && !s.spanContext.IsSampled() {
246 return s
247 }
248
249 s.data = &SpanData{
250 SpanContext: s.spanContext,
251 StartTime: time.Now(),
252 SpanKind: o.SpanKind,
253 Name: name,
254 HasRemoteParent: remoteParent,
255 }
256 s.lruAttributes = newLruMap(cfg.MaxAttributesPerSpan)
257 s.annotations = newEvictedQueue(cfg.MaxAnnotationEventsPerSpan)
258 s.messageEvents = newEvictedQueue(cfg.MaxMessageEventsPerSpan)
259 s.links = newEvictedQueue(cfg.MaxLinksPerSpan)
260
261 if hasParent {
262 s.data.ParentSpanID = parent.SpanID
263 }
264 if internal.LocalSpanStoreEnabled {
265 var ss *spanStore
266 ss = spanStoreForNameCreateIfNew(name)
267 if ss != nil {
268 s.spanStore = ss
269 ss.add(s)
270 }
271 }
272
273 return s
274 }
275
276
277 func (s *span) End() {
278 if s == nil {
279 return
280 }
281 if s.executionTracerTaskEnd != nil {
282 s.executionTracerTaskEnd()
283 }
284 if !s.IsRecordingEvents() {
285 return
286 }
287 s.endOnce.Do(func() {
288 exp, _ := exporters.Load().(exportersMap)
289 mustExport := s.spanContext.IsSampled() && len(exp) > 0
290 if s.spanStore != nil || mustExport {
291 sd := s.makeSpanData()
292 sd.EndTime = internal.MonotonicEndTime(sd.StartTime)
293 if s.spanStore != nil {
294 s.spanStore.finished(s, sd)
295 }
296 if mustExport {
297 for e := range exp {
298 e.ExportSpan(sd)
299 }
300 }
301 }
302 })
303 }
304
305
306
307 func (s *span) makeSpanData() *SpanData {
308 var sd SpanData
309 s.mu.Lock()
310 sd = *s.data
311 if s.lruAttributes.len() > 0 {
312 sd.Attributes = s.lruAttributesToAttributeMap()
313 sd.DroppedAttributeCount = s.lruAttributes.droppedCount
314 }
315 if len(s.annotations.queue) > 0 {
316 sd.Annotations = s.interfaceArrayToAnnotationArray()
317 sd.DroppedAnnotationCount = s.annotations.droppedCount
318 }
319 if len(s.messageEvents.queue) > 0 {
320 sd.MessageEvents = s.interfaceArrayToMessageEventArray()
321 sd.DroppedMessageEventCount = s.messageEvents.droppedCount
322 }
323 if len(s.links.queue) > 0 {
324 sd.Links = s.interfaceArrayToLinksArray()
325 sd.DroppedLinkCount = s.links.droppedCount
326 }
327 s.mu.Unlock()
328 return &sd
329 }
330
331
332 func (s *span) SpanContext() SpanContext {
333 if s == nil {
334 return SpanContext{}
335 }
336 return s.spanContext
337 }
338
339
340 func (s *span) SetName(name string) {
341 if !s.IsRecordingEvents() {
342 return
343 }
344 s.mu.Lock()
345 s.data.Name = name
346 s.mu.Unlock()
347 }
348
349
350 func (s *span) SetStatus(status Status) {
351 if !s.IsRecordingEvents() {
352 return
353 }
354 s.mu.Lock()
355 s.data.Status = status
356 s.mu.Unlock()
357 }
358
359 func (s *span) interfaceArrayToLinksArray() []Link {
360 linksArr := make([]Link, 0, len(s.links.queue))
361 for _, value := range s.links.queue {
362 linksArr = append(linksArr, value.(Link))
363 }
364 return linksArr
365 }
366
367 func (s *span) interfaceArrayToMessageEventArray() []MessageEvent {
368 messageEventArr := make([]MessageEvent, 0, len(s.messageEvents.queue))
369 for _, value := range s.messageEvents.queue {
370 messageEventArr = append(messageEventArr, value.(MessageEvent))
371 }
372 return messageEventArr
373 }
374
375 func (s *span) interfaceArrayToAnnotationArray() []Annotation {
376 annotationArr := make([]Annotation, 0, len(s.annotations.queue))
377 for _, value := range s.annotations.queue {
378 annotationArr = append(annotationArr, value.(Annotation))
379 }
380 return annotationArr
381 }
382
383 func (s *span) lruAttributesToAttributeMap() map[string]interface{} {
384 attributes := make(map[string]interface{}, s.lruAttributes.len())
385 for _, key := range s.lruAttributes.keys() {
386 value, ok := s.lruAttributes.get(key)
387 if ok {
388 keyStr := key.(string)
389 attributes[keyStr] = value
390 }
391 }
392 return attributes
393 }
394
395 func (s *span) copyToCappedAttributes(attributes []Attribute) {
396 for _, a := range attributes {
397 s.lruAttributes.add(a.key, a.value)
398 }
399 }
400
401 func (s *span) addChild() {
402 if !s.IsRecordingEvents() {
403 return
404 }
405 s.mu.Lock()
406 s.data.ChildSpanCount++
407 s.mu.Unlock()
408 }
409
410
411
412
413 func (s *span) AddAttributes(attributes ...Attribute) {
414 if !s.IsRecordingEvents() {
415 return
416 }
417 s.mu.Lock()
418 s.copyToCappedAttributes(attributes)
419 s.mu.Unlock()
420 }
421
422 func (s *span) printStringInternal(attributes []Attribute, str string) {
423 now := time.Now()
424 var am map[string]interface{}
425 if len(attributes) != 0 {
426 am = make(map[string]interface{}, len(attributes))
427 for _, attr := range attributes {
428 am[attr.key] = attr.value
429 }
430 }
431 s.mu.Lock()
432 s.annotations.add(Annotation{
433 Time: now,
434 Message: str,
435 Attributes: am,
436 })
437 s.mu.Unlock()
438 }
439
440
441
442 func (s *span) Annotate(attributes []Attribute, str string) {
443 if !s.IsRecordingEvents() {
444 return
445 }
446 s.printStringInternal(attributes, str)
447 }
448
449
450 func (s *span) Annotatef(attributes []Attribute, format string, a ...interface{}) {
451 if !s.IsRecordingEvents() {
452 return
453 }
454 s.printStringInternal(attributes, fmt.Sprintf(format, a...))
455 }
456
457
458
459
460
461
462
463 func (s *span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
464 if !s.IsRecordingEvents() {
465 return
466 }
467 now := time.Now()
468 s.mu.Lock()
469 s.messageEvents.add(MessageEvent{
470 Time: now,
471 EventType: MessageEventTypeSent,
472 MessageID: messageID,
473 UncompressedByteSize: uncompressedByteSize,
474 CompressedByteSize: compressedByteSize,
475 })
476 s.mu.Unlock()
477 }
478
479
480
481
482
483
484
485 func (s *span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
486 if !s.IsRecordingEvents() {
487 return
488 }
489 now := time.Now()
490 s.mu.Lock()
491 s.messageEvents.add(MessageEvent{
492 Time: now,
493 EventType: MessageEventTypeRecv,
494 MessageID: messageID,
495 UncompressedByteSize: uncompressedByteSize,
496 CompressedByteSize: compressedByteSize,
497 })
498 s.mu.Unlock()
499 }
500
501
502 func (s *span) AddLink(l Link) {
503 if !s.IsRecordingEvents() {
504 return
505 }
506 s.mu.Lock()
507 s.links.add(l)
508 s.mu.Unlock()
509 }
510
511 func (s *span) String() string {
512 if s == nil {
513 return "<nil>"
514 }
515 if s.data == nil {
516 return fmt.Sprintf("span %s", s.spanContext.SpanID)
517 }
518 s.mu.Lock()
519 str := fmt.Sprintf("span %s %q", s.spanContext.SpanID, s.data.Name)
520 s.mu.Unlock()
521 return str
522 }
523
524 var config atomic.Value
525
526 func init() {
527 config.Store(&Config{
528 DefaultSampler: ProbabilitySampler(defaultSamplingProbability),
529 IDGenerator: &defaultIDGenerator{},
530 MaxAttributesPerSpan: DefaultMaxAttributesPerSpan,
531 MaxAnnotationEventsPerSpan: DefaultMaxAnnotationEventsPerSpan,
532 MaxMessageEventsPerSpan: DefaultMaxMessageEventsPerSpan,
533 MaxLinksPerSpan: DefaultMaxLinksPerSpan,
534 })
535 }
536
537 type defaultIDGenerator struct {
538 sync.Mutex
539
540
541
542
543
544
545
546
547
548 nextSpanID uint64
549 spanIDInc uint64
550
551 traceIDAdd [2]uint64
552 traceIDRand *rand.Rand
553
554 initOnce sync.Once
555 }
556
557
558
559 func (gen *defaultIDGenerator) init() {
560 gen.initOnce.Do(func() {
561
562 var rngSeed int64
563 for _, p := range []interface{}{
564 &rngSeed, &gen.traceIDAdd, &gen.nextSpanID, &gen.spanIDInc,
565 } {
566 binary.Read(crand.Reader, binary.LittleEndian, p)
567 }
568 gen.traceIDRand = rand.New(rand.NewSource(rngSeed))
569 gen.spanIDInc |= 1
570 })
571 }
572
573
574 func (gen *defaultIDGenerator) NewSpanID() [8]byte {
575 var id uint64
576 for id == 0 {
577 id = atomic.AddUint64(&gen.nextSpanID, gen.spanIDInc)
578 }
579 var sid [8]byte
580 binary.LittleEndian.PutUint64(sid[:], id)
581 return sid
582 }
583
584
585
586 func (gen *defaultIDGenerator) NewTraceID() [16]byte {
587 var tid [16]byte
588
589
590 gen.Lock()
591 binary.LittleEndian.PutUint64(tid[0:8], gen.traceIDRand.Uint64()+gen.traceIDAdd[0])
592 binary.LittleEndian.PutUint64(tid[8:16], gen.traceIDRand.Uint64()+gen.traceIDAdd[1])
593 gen.Unlock()
594 return tid
595 }
596
View as plain text