2121import threading
2222import traceback
2323import typing
24- from collections import OrderedDict
2524from contextlib import contextmanager
2625from os import environ
2726from time import time_ns
3130 Callable ,
3231 Dict ,
3332 Iterator ,
33+ List ,
3434 Optional ,
3535 Sequence ,
3636 Tuple ,
@@ -353,19 +353,19 @@ class ReadableSpan:
353353
354354 def __init__ (
355355 self ,
356- name : str = None ,
357- context : trace_api .SpanContext = None ,
356+ name : str ,
357+ context : Optional [ trace_api .SpanContext ] = None ,
358358 parent : Optional [trace_api .SpanContext ] = None ,
359- resource : Resource = None ,
359+ resource : Optional [ Resource ] = None ,
360360 attributes : types .Attributes = None ,
361361 events : Sequence [Event ] = (),
362362 links : Sequence [trace_api .Link ] = (),
363363 kind : trace_api .SpanKind = trace_api .SpanKind .INTERNAL ,
364- instrumentation_info : InstrumentationInfo = None ,
364+ instrumentation_info : Optional [ InstrumentationInfo ] = None ,
365365 status : Status = Status (StatusCode .UNSET ),
366366 start_time : Optional [int ] = None ,
367367 end_time : Optional [int ] = None ,
368- instrumentation_scope : InstrumentationScope = None ,
368+ instrumentation_scope : Optional [ InstrumentationScope ] = None ,
369369 ) -> None :
370370 self ._name = name
371371 self ._context = context
@@ -386,19 +386,19 @@ def __init__(
386386
387387 @property
388388 def dropped_attributes (self ) -> int :
389- if self ._attributes :
389+ if isinstance ( self ._attributes , BoundedAttributes ) :
390390 return self ._attributes .dropped
391391 return 0
392392
393393 @property
394394 def dropped_events (self ) -> int :
395- if self ._events :
395+ if isinstance ( self ._events , BoundedList ) :
396396 return self ._events .dropped
397397 return 0
398398
399399 @property
400400 def dropped_links (self ) -> int :
401- if self ._links :
401+ if isinstance ( self ._links , BoundedList ) :
402402 return self ._links .dropped
403403 return 0
404404
@@ -435,7 +435,7 @@ def status(self) -> trace_api.Status:
435435
436436 @property
437437 def attributes (self ) -> types .Attributes :
438- return MappingProxyType (self ._attributes )
438+ return MappingProxyType (self ._attributes or {} )
439439
440440 @property
441441 def events (self ) -> Sequence [Event ]:
@@ -453,23 +453,17 @@ def resource(self) -> Resource:
453453 @deprecated (
454454 version = "1.11.1" , reason = "You should use instrumentation_scope"
455455 )
456- def instrumentation_info (self ) -> InstrumentationInfo :
456+ def instrumentation_info (self ) -> Optional [ InstrumentationInfo ] :
457457 return self ._instrumentation_info
458458
459459 @property
460- def instrumentation_scope (self ) -> InstrumentationScope :
460+ def instrumentation_scope (self ) -> Optional [ InstrumentationScope ] :
461461 return self ._instrumentation_scope
462462
463- def to_json (self , indent = 4 ):
463+ def to_json (self , indent : int = 4 ):
464464 parent_id = None
465465 if self .parent is not None :
466- if isinstance (self .parent , Span ):
467- ctx = self .parent .context
468- parent_id = f"0x{ trace_api .format_span_id (ctx .span_id )} "
469- elif isinstance (self .parent , SpanContext ):
470- parent_id = (
471- f"0x{ trace_api .format_span_id (self .parent .span_id )} "
472- )
466+ parent_id = f"0x{ trace_api .format_span_id (self .parent .span_id )} "
473467
474468 start_time = None
475469 if self ._start_time :
@@ -479,77 +473,72 @@ def to_json(self, indent=4):
479473 if self ._end_time :
480474 end_time = util .ns_to_iso_str (self ._end_time )
481475
482- if self ._status is not None :
483- status = OrderedDict ()
484- status ["status_code" ] = str (self ._status .status_code .name )
485- if self ._status .description :
486- status ["description" ] = self ._status .description
487-
488- f_span = OrderedDict ()
489-
490- f_span ["name" ] = self ._name
491- f_span ["context" ] = self ._format_context (self ._context )
492- f_span ["kind" ] = str (self .kind )
493- f_span ["parent_id" ] = parent_id
494- f_span ["start_time" ] = start_time
495- f_span ["end_time" ] = end_time
496- if self ._status is not None :
497- f_span ["status" ] = status
498- f_span ["attributes" ] = self ._format_attributes (self ._attributes )
499- f_span ["events" ] = self ._format_events (self ._events )
500- f_span ["links" ] = self ._format_links (self ._links )
501- f_span ["resource" ] = json .loads (self .resource .to_json ())
476+ status = {
477+ "status_code" : str (self ._status .status_code .name ),
478+ }
479+ if self ._status .description :
480+ status ["description" ] = self ._status .description
481+
482+ f_span = {
483+ "name" : self ._name ,
484+ "context" : self ._format_context (self ._context )
485+ if self ._context
486+ else None ,
487+ "kind" : str (self .kind ),
488+ "parent_id" : parent_id ,
489+ "start_time" : start_time ,
490+ "end_time" : end_time ,
491+ "status" : status ,
492+ "attributes" : self ._format_attributes (self ._attributes ),
493+ "events" : self ._format_events (self ._events ),
494+ "links" : self ._format_links (self ._links ),
495+ "resource" : json .loads (self .resource .to_json ()),
496+ }
502497
503498 return json .dumps (f_span , indent = indent )
504499
505500 @staticmethod
506- def _format_context (context ) :
507- x_ctx = OrderedDict ()
508- x_ctx [ "trace_id" ] = f"0x{ trace_api .format_trace_id (context .trace_id )} "
509- x_ctx [ "span_id" ] = f"0x{ trace_api .format_span_id (context .span_id )} "
510- x_ctx [ "trace_state" ] = repr (context .trace_state )
511- return x_ctx
501+ def _format_context (context : SpanContext ) -> Dict [ str , str ] :
502+ return {
503+ "trace_id" : f"0x{ trace_api .format_trace_id (context .trace_id )} " ,
504+ "span_id" : f"0x{ trace_api .format_span_id (context .span_id )} " ,
505+ "trace_state" : repr (context .trace_state ),
506+ }
512507
513508 @staticmethod
514- def _format_attributes (attributes ):
515- if isinstance ( attributes , BoundedAttributes ):
516- return attributes . _dict # pylint: disable=protected-access
517- if isinstance (attributes , MappingProxyType ):
518- return attributes . copy ( )
509+ def _format_attributes (
510+ attributes : types . Attributes ,
511+ ) -> Optional [ Dict [ str , Any ]]:
512+ if attributes is not None and not isinstance (attributes , dict ):
513+ return dict ( attributes )
519514 return attributes
520515
521516 @staticmethod
522- def _format_events (events ):
523- f_events = []
524- for event in events :
525- f_event = OrderedDict ()
526- f_event ["name" ] = event .name
527- f_event ["timestamp" ] = util .ns_to_iso_str (event .timestamp )
528- f_event [
529- "attributes"
530- ] = Span ._format_attributes ( # pylint: disable=protected-access
531- event .attributes
532- )
533- f_events .append (f_event )
534- return f_events
517+ def _format_events (events : Sequence [Event ]) -> List [Dict [str , Any ]]:
518+ return [
519+ {
520+ "name" : event .name ,
521+ "timestamp" : util .ns_to_iso_str (event .timestamp ),
522+ "attributes" : Span ._format_attributes ( # pylint: disable=protected-access
523+ event .attributes
524+ ),
525+ }
526+ for event in events
527+ ]
535528
536529 @staticmethod
537- def _format_links (links ):
538- f_links = []
539- for link in links :
540- f_link = OrderedDict ()
541- f_link [
542- "context"
543- ] = Span ._format_context ( # pylint: disable=protected-access
544- link .context
545- )
546- f_link [
547- "attributes"
548- ] = Span ._format_attributes ( # pylint: disable=protected-access
549- link .attributes
550- )
551- f_links .append (f_link )
552- return f_links
530+ def _format_links (links : Sequence [trace_api .Link ]) -> List [Dict [str , Any ]]:
531+ return [
532+ {
533+ "context" : Span ._format_context ( # pylint: disable=protected-access
534+ link .context
535+ ),
536+ "attributes" : Span ._format_attributes ( # pylint: disable=protected-access
537+ link .attributes
538+ ),
539+ }
540+ for link in links
541+ ]
553542
554543
555544class SpanLimits :
0 commit comments