1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package trace
16
17 import (
18 "context"
19 "fmt"
20 "reflect"
21 "runtime"
22 rt "runtime/trace"
23 "strings"
24 "sync"
25 "time"
26 "unicode/utf8"
27
28 "go.opentelemetry.io/otel/attribute"
29 "go.opentelemetry.io/otel/codes"
30 "go.opentelemetry.io/otel/sdk/instrumentation"
31 "go.opentelemetry.io/otel/sdk/internal"
32 "go.opentelemetry.io/otel/sdk/resource"
33 semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
34 "go.opentelemetry.io/otel/trace"
35 "go.opentelemetry.io/otel/trace/embedded"
36 )
37
38
39
40
41
42
43 type ReadOnlySpan interface {
44
45 Name() string
46
47 SpanContext() trace.SpanContext
48
49
50
51 Parent() trace.SpanContext
52
53 SpanKind() trace.SpanKind
54
55 StartTime() time.Time
56
57
58 EndTime() time.Time
59
60
61 Attributes() []attribute.KeyValue
62
63 Links() []Link
64
65
66 Events() []Event
67
68 Status() Status
69
70
71 InstrumentationScope() instrumentation.Scope
72
73
74
75 InstrumentationLibrary() instrumentation.Library
76
77 Resource() *resource.Resource
78
79
80 DroppedAttributes() int
81
82
83 DroppedLinks() int
84
85
86 DroppedEvents() int
87
88
89 ChildSpanCount() int
90
91
92
93
94 private()
95 }
96
97
98
99
100
101
102
103
104 type ReadWriteSpan interface {
105 trace.Span
106 ReadOnlySpan
107 }
108
109
110
111 type recordingSpan struct {
112 embedded.Span
113
114
115 mu sync.Mutex
116
117
118 parent trace.SpanContext
119
120
121 spanKind trace.SpanKind
122
123
124 name string
125
126
127 startTime time.Time
128
129
130
131 endTime time.Time
132
133
134 status Status
135
136
137 childSpanCount int
138
139
140 spanContext trace.SpanContext
141
142
143
144
145
146
147
148 attributes []attribute.KeyValue
149 droppedAttributes int
150
151
152 events evictedQueue
153
154
155 links evictedQueue
156
157
158 executionTracerTaskEnd func()
159
160
161 tracer *tracer
162 }
163
164 var (
165 _ ReadWriteSpan = (*recordingSpan)(nil)
166 _ runtimeTracer = (*recordingSpan)(nil)
167 )
168
169
170 func (s *recordingSpan) SpanContext() trace.SpanContext {
171 if s == nil {
172 return trace.SpanContext{}
173 }
174 return s.spanContext
175 }
176
177
178
179 func (s *recordingSpan) IsRecording() bool {
180 if s == nil {
181 return false
182 }
183 s.mu.Lock()
184 defer s.mu.Unlock()
185
186 return s.endTime.IsZero()
187 }
188
189
190
191
192
193 func (s *recordingSpan) SetStatus(code codes.Code, description string) {
194 if !s.IsRecording() {
195 return
196 }
197 s.mu.Lock()
198 defer s.mu.Unlock()
199 if s.status.Code > code {
200 return
201 }
202
203 status := Status{Code: code}
204 if code == codes.Error {
205 status.Description = description
206 }
207
208 s.status = status
209 }
210
211
212
213
214
215
216
217
218
219
220
221 func (s *recordingSpan) SetAttributes(attributes ...attribute.KeyValue) {
222 if !s.IsRecording() {
223 return
224 }
225
226 s.mu.Lock()
227 defer s.mu.Unlock()
228
229 limit := s.tracer.provider.spanLimits.AttributeCountLimit
230 if limit == 0 {
231
232 s.droppedAttributes += len(attributes)
233 return
234 }
235
236
237
238 if limit > 0 && len(s.attributes)+len(attributes) > limit {
239 s.addOverCapAttrs(limit, attributes)
240 return
241 }
242
243
244
245 for _, a := range attributes {
246 if !a.Valid() {
247
248 s.droppedAttributes++
249 continue
250 }
251 a = truncateAttr(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a)
252 s.attributes = append(s.attributes, a)
253 }
254 }
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) {
270
271
272
273
274
275 exists := make(map[attribute.Key]int)
276 s.dedupeAttrsFromRecord(&exists)
277
278
279
280 for _, a := range attrs {
281 if !a.Valid() {
282
283 s.droppedAttributes++
284 continue
285 }
286
287 if idx, ok := exists[a.Key]; ok {
288
289 s.attributes[idx] = a
290 continue
291 }
292
293 if len(s.attributes) >= limit {
294
295
296 s.droppedAttributes++
297 } else {
298 a = truncateAttr(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a)
299 s.attributes = append(s.attributes, a)
300 exists[a.Key] = len(s.attributes) - 1
301 }
302 }
303 }
304
305
306
307
308
309
310
311 func truncateAttr(limit int, attr attribute.KeyValue) attribute.KeyValue {
312 if limit < 0 {
313 return attr
314 }
315 switch attr.Value.Type() {
316 case attribute.STRING:
317 if v := attr.Value.AsString(); len(v) > limit {
318 return attr.Key.String(safeTruncate(v, limit))
319 }
320 case attribute.STRINGSLICE:
321 v := attr.Value.AsStringSlice()
322 for i := range v {
323 if len(v[i]) > limit {
324 v[i] = safeTruncate(v[i], limit)
325 }
326 }
327 return attr.Key.StringSlice(v)
328 }
329 return attr
330 }
331
332
333 func safeTruncate(input string, limit int) string {
334 if trunc, ok := safeTruncateValidUTF8(input, limit); ok {
335 return trunc
336 }
337 trunc, _ := safeTruncateValidUTF8(strings.ToValidUTF8(input, ""), limit)
338 return trunc
339 }
340
341
342
343
344
345 func safeTruncateValidUTF8(input string, limit int) (string, bool) {
346 for cnt := 0; cnt <= limit; {
347 r, size := utf8.DecodeRuneInString(input[cnt:])
348 if r == utf8.RuneError {
349 return input, false
350 }
351
352 if cnt+size > limit {
353 return input[:cnt], true
354 }
355 cnt += size
356 }
357 return input, true
358 }
359
360
361
362
363
364
365
366
367
368 func (s *recordingSpan) End(options ...trace.SpanEndOption) {
369
370
371 if s == nil {
372 return
373 }
374
375
376
377 et := internal.MonotonicEndTime(s.startTime)
378
379
380
381 if !s.IsRecording() {
382 return
383 }
384
385 config := trace.NewSpanEndConfig(options...)
386 if recovered := recover(); recovered != nil {
387
388 defer panic(recovered)
389 opts := []trace.EventOption{
390 trace.WithAttributes(
391 semconv.ExceptionType(typeStr(recovered)),
392 semconv.ExceptionMessage(fmt.Sprint(recovered)),
393 ),
394 }
395
396 if config.StackTrace() {
397 opts = append(opts, trace.WithAttributes(
398 semconv.ExceptionStacktrace(recordStackTrace()),
399 ))
400 }
401
402 s.addEvent(semconv.ExceptionEventName, opts...)
403 }
404
405 if s.executionTracerTaskEnd != nil {
406 s.executionTracerTaskEnd()
407 }
408
409 s.mu.Lock()
410
411 if config.Timestamp().IsZero() {
412 s.endTime = et
413 } else {
414 s.endTime = config.Timestamp()
415 }
416 s.mu.Unlock()
417
418 sps := s.tracer.provider.getSpanProcessors()
419 if len(sps) == 0 {
420 return
421 }
422 snap := s.snapshot()
423 for _, sp := range sps {
424 sp.sp.OnEnd(snap)
425 }
426 }
427
428
429
430
431
432 func (s *recordingSpan) RecordError(err error, opts ...trace.EventOption) {
433 if s == nil || err == nil || !s.IsRecording() {
434 return
435 }
436
437 opts = append(opts, trace.WithAttributes(
438 semconv.ExceptionType(typeStr(err)),
439 semconv.ExceptionMessage(err.Error()),
440 ))
441
442 c := trace.NewEventConfig(opts...)
443 if c.StackTrace() {
444 opts = append(opts, trace.WithAttributes(
445 semconv.ExceptionStacktrace(recordStackTrace()),
446 ))
447 }
448
449 s.addEvent(semconv.ExceptionEventName, opts...)
450 }
451
452 func typeStr(i interface{}) string {
453 t := reflect.TypeOf(i)
454 if t.PkgPath() == "" && t.Name() == "" {
455
456 return t.String()
457 }
458 return fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
459 }
460
461 func recordStackTrace() string {
462 stackTrace := make([]byte, 2048)
463 n := runtime.Stack(stackTrace, false)
464
465 return string(stackTrace[0:n])
466 }
467
468
469
470 func (s *recordingSpan) AddEvent(name string, o ...trace.EventOption) {
471 if !s.IsRecording() {
472 return
473 }
474 s.addEvent(name, o...)
475 }
476
477 func (s *recordingSpan) addEvent(name string, o ...trace.EventOption) {
478 c := trace.NewEventConfig(o...)
479 e := Event{Name: name, Attributes: c.Attributes(), Time: c.Timestamp()}
480
481
482 limit := s.tracer.provider.spanLimits.AttributePerEventCountLimit
483 if limit == 0 {
484
485 e.DroppedAttributeCount = len(e.Attributes)
486 e.Attributes = nil
487 } else if limit > 0 && len(e.Attributes) > limit {
488
489 e.DroppedAttributeCount = len(e.Attributes) - limit
490 e.Attributes = e.Attributes[:limit]
491 }
492
493 s.mu.Lock()
494 s.events.add(e)
495 s.mu.Unlock()
496 }
497
498
499
500 func (s *recordingSpan) SetName(name string) {
501 if !s.IsRecording() {
502 return
503 }
504
505 s.mu.Lock()
506 defer s.mu.Unlock()
507 s.name = name
508 }
509
510
511 func (s *recordingSpan) Name() string {
512 s.mu.Lock()
513 defer s.mu.Unlock()
514 return s.name
515 }
516
517
518 func (s *recordingSpan) Parent() trace.SpanContext {
519 s.mu.Lock()
520 defer s.mu.Unlock()
521 return s.parent
522 }
523
524
525 func (s *recordingSpan) SpanKind() trace.SpanKind {
526 s.mu.Lock()
527 defer s.mu.Unlock()
528 return s.spanKind
529 }
530
531
532 func (s *recordingSpan) StartTime() time.Time {
533 s.mu.Lock()
534 defer s.mu.Unlock()
535 return s.startTime
536 }
537
538
539
540 func (s *recordingSpan) EndTime() time.Time {
541 s.mu.Lock()
542 defer s.mu.Unlock()
543 return s.endTime
544 }
545
546
547
548
549 func (s *recordingSpan) Attributes() []attribute.KeyValue {
550 s.mu.Lock()
551 defer s.mu.Unlock()
552 s.dedupeAttrs()
553 return s.attributes
554 }
555
556
557
558
559 func (s *recordingSpan) dedupeAttrs() {
560
561
562 exists := make(map[attribute.Key]int)
563 s.dedupeAttrsFromRecord(&exists)
564 }
565
566
567
568
569
570 func (s *recordingSpan) dedupeAttrsFromRecord(record *map[attribute.Key]int) {
571
572 unique := s.attributes[:0]
573 for _, a := range s.attributes {
574 if idx, ok := (*record)[a.Key]; ok {
575 unique[idx] = a
576 } else {
577 unique = append(unique, a)
578 (*record)[a.Key] = len(unique) - 1
579 }
580 }
581
582
583
584
585 s.attributes = unique
586 }
587
588
589 func (s *recordingSpan) Links() []Link {
590 s.mu.Lock()
591 defer s.mu.Unlock()
592 if len(s.links.queue) == 0 {
593 return []Link{}
594 }
595 return s.interfaceArrayToLinksArray()
596 }
597
598
599 func (s *recordingSpan) Events() []Event {
600 s.mu.Lock()
601 defer s.mu.Unlock()
602 if len(s.events.queue) == 0 {
603 return []Event{}
604 }
605 return s.interfaceArrayToEventArray()
606 }
607
608
609 func (s *recordingSpan) Status() Status {
610 s.mu.Lock()
611 defer s.mu.Unlock()
612 return s.status
613 }
614
615
616
617 func (s *recordingSpan) InstrumentationScope() instrumentation.Scope {
618 s.mu.Lock()
619 defer s.mu.Unlock()
620 return s.tracer.instrumentationScope
621 }
622
623
624
625 func (s *recordingSpan) InstrumentationLibrary() instrumentation.Library {
626 s.mu.Lock()
627 defer s.mu.Unlock()
628 return s.tracer.instrumentationScope
629 }
630
631
632
633 func (s *recordingSpan) Resource() *resource.Resource {
634 s.mu.Lock()
635 defer s.mu.Unlock()
636 return s.tracer.provider.resource
637 }
638
639 func (s *recordingSpan) addLink(link trace.Link) {
640 if !s.IsRecording() || !link.SpanContext.IsValid() {
641 return
642 }
643
644 l := Link{SpanContext: link.SpanContext, Attributes: link.Attributes}
645
646
647 limit := s.tracer.provider.spanLimits.AttributePerLinkCountLimit
648 if limit == 0 {
649
650 l.DroppedAttributeCount = len(l.Attributes)
651 l.Attributes = nil
652 } else if limit > 0 && len(l.Attributes) > limit {
653 l.DroppedAttributeCount = len(l.Attributes) - limit
654 l.Attributes = l.Attributes[:limit]
655 }
656
657 s.mu.Lock()
658 s.links.add(l)
659 s.mu.Unlock()
660 }
661
662
663
664 func (s *recordingSpan) DroppedAttributes() int {
665 s.mu.Lock()
666 defer s.mu.Unlock()
667 return s.droppedAttributes
668 }
669
670
671
672 func (s *recordingSpan) DroppedLinks() int {
673 s.mu.Lock()
674 defer s.mu.Unlock()
675 return s.links.droppedCount
676 }
677
678
679
680 func (s *recordingSpan) DroppedEvents() int {
681 s.mu.Lock()
682 defer s.mu.Unlock()
683 return s.events.droppedCount
684 }
685
686
687
688 func (s *recordingSpan) ChildSpanCount() int {
689 s.mu.Lock()
690 defer s.mu.Unlock()
691 return s.childSpanCount
692 }
693
694
695
696 func (s *recordingSpan) TracerProvider() trace.TracerProvider {
697 return s.tracer.provider
698 }
699
700
701 func (s *recordingSpan) snapshot() ReadOnlySpan {
702 var sd snapshot
703 s.mu.Lock()
704 defer s.mu.Unlock()
705
706 sd.endTime = s.endTime
707 sd.instrumentationScope = s.tracer.instrumentationScope
708 sd.name = s.name
709 sd.parent = s.parent
710 sd.resource = s.tracer.provider.resource
711 sd.spanContext = s.spanContext
712 sd.spanKind = s.spanKind
713 sd.startTime = s.startTime
714 sd.status = s.status
715 sd.childSpanCount = s.childSpanCount
716
717 if len(s.attributes) > 0 {
718 s.dedupeAttrs()
719 sd.attributes = s.attributes
720 }
721 sd.droppedAttributeCount = s.droppedAttributes
722 if len(s.events.queue) > 0 {
723 sd.events = s.interfaceArrayToEventArray()
724 sd.droppedEventCount = s.events.droppedCount
725 }
726 if len(s.links.queue) > 0 {
727 sd.links = s.interfaceArrayToLinksArray()
728 sd.droppedLinkCount = s.links.droppedCount
729 }
730 return &sd
731 }
732
733 func (s *recordingSpan) interfaceArrayToLinksArray() []Link {
734 linkArr := make([]Link, 0)
735 for _, value := range s.links.queue {
736 linkArr = append(linkArr, value.(Link))
737 }
738 return linkArr
739 }
740
741 func (s *recordingSpan) interfaceArrayToEventArray() []Event {
742 eventArr := make([]Event, 0)
743 for _, value := range s.events.queue {
744 eventArr = append(eventArr, value.(Event))
745 }
746 return eventArr
747 }
748
749 func (s *recordingSpan) addChild() {
750 if !s.IsRecording() {
751 return
752 }
753 s.mu.Lock()
754 s.childSpanCount++
755 s.mu.Unlock()
756 }
757
758 func (*recordingSpan) private() {}
759
760
761
762 func (s *recordingSpan) runtimeTrace(ctx context.Context) context.Context {
763 if !rt.IsEnabled() {
764
765 return ctx
766 }
767 nctx, task := rt.NewTask(ctx, s.name)
768
769 s.mu.Lock()
770 s.executionTracerTaskEnd = task.End
771 s.mu.Unlock()
772
773 return nctx
774 }
775
776
777
778
779 type nonRecordingSpan struct {
780 embedded.Span
781
782
783 tracer *tracer
784 sc trace.SpanContext
785 }
786
787 var _ trace.Span = nonRecordingSpan{}
788
789
790 func (s nonRecordingSpan) SpanContext() trace.SpanContext { return s.sc }
791
792
793 func (nonRecordingSpan) IsRecording() bool { return false }
794
795
796 func (nonRecordingSpan) SetStatus(codes.Code, string) {}
797
798
799 func (nonRecordingSpan) SetError(bool) {}
800
801
802 func (nonRecordingSpan) SetAttributes(...attribute.KeyValue) {}
803
804
805 func (nonRecordingSpan) End(...trace.SpanEndOption) {}
806
807
808 func (nonRecordingSpan) RecordError(error, ...trace.EventOption) {}
809
810
811 func (nonRecordingSpan) AddEvent(string, ...trace.EventOption) {}
812
813
814 func (nonRecordingSpan) SetName(string) {}
815
816
817
818 func (s nonRecordingSpan) TracerProvider() trace.TracerProvider { return s.tracer.provider }
819
820 func isRecording(s SamplingResult) bool {
821 return s.Decision == RecordOnly || s.Decision == RecordAndSample
822 }
823
824 func isSampled(s SamplingResult) bool {
825 return s.Decision == RecordAndSample
826 }
827
828
829 type Status struct {
830
831 Code codes.Code
832
833
834 Description string
835 }
836
View as plain text