@@ -371,6 +371,17 @@ def _create_immutable_attributes(attributes):
371
371
return MappingProxyType (attributes .copy () if attributes else {})
372
372
373
373
374
+ def _check_span_ended (func ):
375
+ def wrapper (self , * args , ** kwargs ):
376
+ with self ._lock : # pylint: disable=protected-access
377
+ if self .end_time is not None :
378
+ logger .warning ("Calling %s on an ended span." , func .__name__ )
379
+ return
380
+ func (self , * args , ** kwargs )
381
+
382
+ return wrapper
383
+
384
+
374
385
class Span (trace_api .Span ):
375
386
"""See `opentelemetry.trace.Span`.
376
387
@@ -560,19 +571,18 @@ def get_span_context(self):
560
571
return self .context
561
572
562
573
def set_attribute (self , key : str , value : types .AttributeValue ) -> None :
563
- with self ._lock :
564
- if not self .is_recording ():
565
- return
566
- has_ended = self .end_time is not None
567
- if has_ended :
568
- logger .warning ("Setting attribute on ended span." )
574
+ if not _is_valid_attribute_value (value ):
569
575
return
570
576
571
577
if not key :
572
578
logger .warning ("invalid key (empty or null)" )
573
579
return
574
580
575
- if _is_valid_attribute_value (value ):
581
+ with self ._lock :
582
+ if self .end_time is not None :
583
+ logger .warning ("Setting attribute on ended span." )
584
+ return
585
+
576
586
# Freeze mutable sequences defensively
577
587
if isinstance (value , MutableSequence ):
578
588
value = tuple (value )
@@ -582,18 +592,10 @@ def set_attribute(self, key: str, value: types.AttributeValue) -> None:
582
592
except ValueError :
583
593
logger .warning ("Byte attribute could not be decoded." )
584
594
return
585
- with self ._lock :
586
- self .attributes [key ] = value
595
+ self .attributes [key ] = value
587
596
597
+ @_check_span_ended
588
598
def _add_event (self , event : EventBase ) -> None :
589
- with self ._lock :
590
- if not self .is_recording ():
591
- return
592
- has_ended = self .end_time is not None
593
-
594
- if has_ended :
595
- logger .warning ("Calling add_event() on an ended span." )
596
- return
597
599
self .events .append (event )
598
600
599
601
def add_event (
@@ -618,56 +620,39 @@ def start(
618
620
parent_context : Optional [context_api .Context ] = None ,
619
621
) -> None :
620
622
with self ._lock :
621
- if not self .is_recording ():
623
+ if self .start_time is not None :
624
+ logger .warning ("Calling start() on a started span." )
622
625
return
623
- has_started = self .start_time is not None
624
- if not has_started :
625
- self ._start_time = (
626
- start_time if start_time is not None else time_ns ()
627
- )
628
- if has_started :
629
- logger .warning ("Calling start() on a started span." )
630
- return
626
+ self ._start_time = (
627
+ start_time if start_time is not None else time_ns ()
628
+ )
629
+
631
630
self .span_processor .on_start (self , parent_context = parent_context )
632
631
633
632
def end (self , end_time : Optional [int ] = None ) -> None :
634
633
with self ._lock :
635
- if not self .is_recording ():
636
- return
637
634
if self .start_time is None :
638
635
raise RuntimeError ("Calling end() on a not started span." )
639
- has_ended = self .end_time is not None
640
- if not has_ended :
641
- if self .status is None :
642
- self .status = Status (canonical_code = StatusCanonicalCode .OK )
636
+ if self .end_time is not None :
637
+ logger .warning ("Calling end() on an ended span." )
638
+ return
643
639
644
- self ._end_time = (
645
- end_time if end_time is not None else time_ns ()
646
- )
640
+ if self .status is None :
641
+ self .status = Status (canonical_code = StatusCanonicalCode .OK )
647
642
648
- if has_ended :
649
- logger .warning ("Calling end() on an ended span." )
650
- return
643
+ self ._end_time = end_time if end_time is not None else time_ns ()
651
644
652
645
self .span_processor .on_end (self )
653
646
647
+ @_check_span_ended
654
648
def update_name (self , name : str ) -> None :
655
- with self ._lock :
656
- has_ended = self .end_time is not None
657
- if has_ended :
658
- logger .warning ("Calling update_name() on an ended span." )
659
- return
660
649
self .name = name
661
650
662
651
def is_recording (self ) -> bool :
663
652
return True
664
653
654
+ @_check_span_ended
665
655
def set_status (self , status : trace_api .Status ) -> None :
666
- with self ._lock :
667
- has_ended = self .end_time is not None
668
- if has_ended :
669
- logger .warning ("Calling set_status() on an ended span." )
670
- return
671
656
self .status = status
672
657
673
658
def __exit__ (
0 commit comments