1818from opentelemetry .exporter .otlp .proto .http .trace_exporter \
1919 import OTLPSpanExporter
2020
21+
2122class TracerMiddleware (BaseTransportMiddleware ):
2223 def __init__ (self , service_name : str ):
2324 self .service_name = service_name
2425 self ._initiate_tracers (service_name )
2526
2627 def _initiate_tracers (self , service_name ):
28+ """Initiates everything needed for tracing"""
29+ # Label this resource as its service:
2730 resource = Resource (attributes = {
2831 SERVICE_NAME : service_name
2932 })
30-
33+ # Export to OpenTelemetry Collector:
3134 processor = BatchSpanProcessor (OTLPSpanExporter ( \
3235 endpoint = "http://localhost:4318/v1/traces" ))
3336 # A provider provides tracers:
3437 provider = TracerProvider (resource = resource )
3538 provider .add_span_processor (processor )
36- # In python trace is global :
39+ # A tracer provides traces :
3740 trace .set_tracer_provider (provider )
3841 self .tracer = trace .get_tracer (__name__ )
3942
40-
41-
4243 def _extract_trace_context (self , message ):
43- """Retrieves span context from message"""
44+ """Retrieves Context object from message"""
4445 try :
46+ # Deserialise serialised context into a Context object:
4547 carrier = message ['trace_context' ]
4648 ctx = TraceContextTextMapPropagator ().extract (carrier = carrier )
47- print (f"Extracting { ctx } " )
4849 return ctx
4950 except KeyError :
50- print ( f"Extracted nothing" )
51+ # If no context, leave empty:
5152 return {}
5253
5354 def _inject_trace_context (self , message ):
54- """Inserts trace context into message"""
55+ """Inserts serialized trace context into message"""
5556 carrier = {}
57+ # If called outside of a span context, just leave carrier empty
58+ # (very safe!)
5659 TraceContextTextMapPropagator ().inject (carrier )
5760 message ['trace_context' ] = carrier
58- print (f"injecting { carrier } " )
59-
6061
6162 def subscribe (self , call_next : Callable , channel , callback , ** kwargs ) -> int :
63+ """The callback includes 'everything' that happens in a service that
64+ we care about, so we wrap it in a span context.
65+ To link the current span context with others from the same request
66+ we inject/extract the serialized trace context in the recipe message"""
6267 @functools .wraps (callback )
6368 def wrapped_callback (header , message ):
6469 ctx = self ._extract_trace_context (message )
@@ -70,5 +75,7 @@ def wrapped_callback(header, message):
7075 return call_next (channel , wrapped_callback , ** kwargs )
7176
7277 def send (self , call_next : Callable , destination , message , ** kwargs ):
78+ # Because send is usually called within a callback, it is inside a span
79+ # context, so we can inject its trace context into the message:
7380 self ._inject_trace_context (message )
7481 call_next (destination , message , ** kwargs )
0 commit comments