@@ -17,6 +17,7 @@ import (
17
17
18
18
"go.opentelemetry.io/otel/attribute"
19
19
"go.opentelemetry.io/otel/codes"
20
+ "go.opentelemetry.io/otel/internal/epoch"
20
21
"go.opentelemetry.io/otel/internal/global"
21
22
"go.opentelemetry.io/otel/sdk/instrumentation"
22
23
"go.opentelemetry.io/otel/sdk/resource"
@@ -114,11 +115,11 @@ type recordingSpan struct {
114
115
name string
115
116
116
117
// startTime is the time at which this span was started.
117
- startTime time. Time
118
+ startTime epoch. Nanos
118
119
119
- // endTime is the time at which this span was ended. It contains the zero
120
- // value of time.Time until the span is ended.
121
- endTime time. Time
120
+ // endTime is the time at which this span was ended. It contains zero until
121
+ // the span is ended.
122
+ endTime epoch. Nanos
122
123
123
124
// status is the status of this span.
124
125
status Status
@@ -168,40 +169,19 @@ func (s *recordingSpan) SpanContext() trace.SpanContext {
168
169
// IsRecording returns if this span is being recorded. If this span has ended
169
170
// this will return false.
170
171
func (s * recordingSpan ) IsRecording () bool {
171
- if s == nil {
172
- return false
173
- }
174
- s .mu .Lock ()
175
- defer s .mu .Unlock ()
176
-
177
- return s .isRecording ()
178
- }
179
-
180
- // isRecording returns if this span is being recorded. If this span has ended
181
- // this will return false.
182
- //
183
- // This method assumes s.mu.Lock is held by the caller.
184
- func (s * recordingSpan ) isRecording () bool {
185
- if s == nil {
186
- return false
187
- }
188
- return s .endTime .IsZero ()
172
+ return s != nil && (& s .endTime ).Load () == 0
189
173
}
190
174
191
175
// SetStatus sets the status of the Span in the form of a code and a
192
176
// description, overriding previous values set. The description is only
193
177
// included in the set status when the code is for an error. If this span is
194
178
// not being recorded than this method does nothing.
195
179
func (s * recordingSpan ) SetStatus (code codes.Code , description string ) {
196
- if s == nil {
180
+ if ! s . IsRecording () {
197
181
return
198
182
}
199
-
200
183
s .mu .Lock ()
201
184
defer s .mu .Unlock ()
202
- if ! s .isRecording () {
203
- return
204
- }
205
185
if s .status .Code > code {
206
186
return
207
187
}
@@ -225,15 +205,12 @@ func (s *recordingSpan) SetStatus(code codes.Code, description string) {
225
205
// attributes the span is configured to have, the last added attributes will
226
206
// be dropped.
227
207
func (s * recordingSpan ) SetAttributes (attributes ... attribute.KeyValue ) {
228
- if s == nil || len (attributes ) == 0 {
208
+ if ! s . IsRecording () || len (attributes ) == 0 {
229
209
return
230
210
}
231
211
232
212
s .mu .Lock ()
233
213
defer s .mu .Unlock ()
234
- if ! s .isRecording () {
235
- return
236
- }
237
214
238
215
limit := s .tracer .provider .spanLimits .AttributeCountLimit
239
216
if limit == 0 {
@@ -444,24 +421,17 @@ func truncate(limit int, s string) string {
444
421
// If this method is called while panicking an error event is added to the
445
422
// Span before ending it and the panic is continued.
446
423
func (s * recordingSpan ) End (options ... trace.SpanEndOption ) {
447
- // Do not start by checking if the span is being recorded which requires
448
- // acquiring a lock. Make a minimal check that the span is not nil.
449
424
if s == nil {
450
425
return
451
426
}
452
427
453
- // Store the end time as soon as possible to avoid artificially increasing
454
- // the span's duration in case some operation below takes a while.
455
- et := monotonicEndTime (s .startTime )
456
-
457
- // Lock the span now that we have an end time and see if we need to do any more processing.
458
- s .mu .Lock ()
459
- if ! s .isRecording () {
460
- s .mu .Unlock ()
428
+ config := trace .NewSpanEndConfig (options ... )
429
+ endTime := epoch .NanosNowOrDefault (config .Timestamp ())
430
+ // Only the first call to End sets the time using atomic compare-and-swap.
431
+ if ! (& s .endTime ).SwapIfZero (endTime ) {
461
432
return
462
433
}
463
434
464
- config := trace .NewSpanEndConfig (options ... )
465
435
if recovered := recover (); recovered != nil {
466
436
// Record but don't stop the panic.
467
437
defer panic (recovered )
@@ -482,19 +452,9 @@ func (s *recordingSpan) End(options ...trace.SpanEndOption) {
482
452
}
483
453
484
454
if s .executionTracerTaskEnd != nil {
485
- s .mu .Unlock ()
486
455
s .executionTracerTaskEnd ()
487
- s .mu .Lock ()
488
456
}
489
457
490
- // Setting endTime to non-zero marks the span as ended and not recording.
491
- if config .Timestamp ().IsZero () {
492
- s .endTime = et
493
- } else {
494
- s .endTime = config .Timestamp ()
495
- }
496
- s .mu .Unlock ()
497
-
498
458
sps := s .tracer .provider .getSpanProcessors ()
499
459
if len (sps ) == 0 {
500
460
return
@@ -505,30 +465,17 @@ func (s *recordingSpan) End(options ...trace.SpanEndOption) {
505
465
}
506
466
}
507
467
508
- // monotonicEndTime returns the end time at present but offset from start,
509
- // monotonically.
510
- //
511
- // The monotonic clock is used in subtractions hence the duration since start
512
- // added back to start gives end as a monotonic time. See
513
- // https://golang.org/pkg/time/#hdr-Monotonic_Clocks
514
- func monotonicEndTime (start time.Time ) time.Time {
515
- return start .Add (time .Since (start ))
516
- }
517
-
518
468
// RecordError will record err as a span event for this span. An additional call to
519
469
// SetStatus is required if the Status of the Span should be set to Error, this method
520
470
// does not change the Span status. If this span is not being recorded or err is nil
521
471
// than this method does nothing.
522
472
func (s * recordingSpan ) RecordError (err error , opts ... trace.EventOption ) {
523
- if s == nil || err == nil {
473
+ if err == nil || ! s . IsRecording () {
524
474
return
525
475
}
526
476
527
477
s .mu .Lock ()
528
478
defer s .mu .Unlock ()
529
- if ! s .isRecording () {
530
- return
531
- }
532
479
533
480
opts = append (opts , trace .WithAttributes (
534
481
semconv .ExceptionType (typeStr (err )),
@@ -564,15 +511,12 @@ func recordStackTrace() string {
564
511
// AddEvent adds an event with the provided name and options. If this span is
565
512
// not being recorded then this method does nothing.
566
513
func (s * recordingSpan ) AddEvent (name string , o ... trace.EventOption ) {
567
- if s == nil {
514
+ if ! s . IsRecording () {
568
515
return
569
516
}
570
517
571
518
s .mu .Lock ()
572
519
defer s .mu .Unlock ()
573
- if ! s .isRecording () {
574
- return
575
- }
576
520
s .addEvent (name , o ... )
577
521
}
578
522
@@ -601,15 +545,12 @@ func (s *recordingSpan) addEvent(name string, o ...trace.EventOption) {
601
545
// SetName sets the name of this span. If this span is not being recorded than
602
546
// this method does nothing.
603
547
func (s * recordingSpan ) SetName (name string ) {
604
- if s == nil {
548
+ if ! s . IsRecording () {
605
549
return
606
550
}
607
551
608
552
s .mu .Lock ()
609
553
defer s .mu .Unlock ()
610
- if ! s .isRecording () {
611
- return
612
- }
613
554
s .name = name
614
555
}
615
556
@@ -638,15 +579,13 @@ func (s *recordingSpan) SpanKind() trace.SpanKind {
638
579
func (s * recordingSpan ) StartTime () time.Time {
639
580
s .mu .Lock ()
640
581
defer s .mu .Unlock ()
641
- return s .startTime
582
+ return s .startTime . ToTime ()
642
583
}
643
584
644
585
// EndTime returns the time this span ended. For spans that have not yet
645
586
// ended, the returned value will be the zero value of time.Time.
646
587
func (s * recordingSpan ) EndTime () time.Time {
647
- s .mu .Lock ()
648
- defer s .mu .Unlock ()
649
- return s .endTime
588
+ return (& s .endTime ).Load ().ToTime ()
650
589
}
651
590
652
591
// Attributes returns the attributes of this span.
@@ -740,7 +679,7 @@ func (s *recordingSpan) Resource() *resource.Resource {
740
679
}
741
680
742
681
func (s * recordingSpan ) AddLink (link trace.Link ) {
743
- if s == nil {
682
+ if ! s . IsRecording () {
744
683
return
745
684
}
746
685
if ! link .SpanContext .IsValid () && len (link .Attributes ) == 0 &&
@@ -750,9 +689,6 @@ func (s *recordingSpan) AddLink(link trace.Link) {
750
689
751
690
s .mu .Lock ()
752
691
defer s .mu .Unlock ()
753
- if ! s .isRecording () {
754
- return
755
- }
756
692
757
693
l := Link {SpanContext : link .SpanContext , Attributes : link .Attributes }
758
694
@@ -814,14 +750,14 @@ func (s *recordingSpan) snapshot() ReadOnlySpan {
814
750
s .mu .Lock ()
815
751
defer s .mu .Unlock ()
816
752
817
- sd .endTime = s .endTime
753
+ sd .endTime = s .endTime . ToTime ()
818
754
sd .instrumentationScope = s .tracer .instrumentationScope
819
755
sd .name = s .name
820
756
sd .parent = s .parent
821
757
sd .resource = s .tracer .provider .resource
822
758
sd .spanContext = s .spanContext
823
759
sd .spanKind = s .spanKind
824
- sd .startTime = s .startTime
760
+ sd .startTime = s .startTime . ToTime ()
825
761
sd .status = s .status
826
762
sd .childSpanCount = s .childSpanCount
827
763
@@ -842,15 +778,12 @@ func (s *recordingSpan) snapshot() ReadOnlySpan {
842
778
}
843
779
844
780
func (s * recordingSpan ) addChild () {
845
- if s == nil {
781
+ if ! s . IsRecording () {
846
782
return
847
783
}
848
784
849
785
s .mu .Lock ()
850
786
defer s .mu .Unlock ()
851
- if ! s .isRecording () {
852
- return
853
- }
854
787
s .childSpanCount ++
855
788
}
856
789
0 commit comments