def from_headers(self, headers): """Generate a SpanContext object from B3 propagation headers. :type headers: dict :param headers: HTTP request headers. :rtype: :class:`~opencensus.trace.span_context.SpanContext` :returns: SpanContext generated from B3 propagation headers. """ if headers is None: return SpanContext(from_header=False) trace_id, span_id, sampled = None, None, None state = headers.get(_STATE_HEADER_KEY) if state: fields = state.split('-', 4) if len(fields) == 1: sampled = fields[0] elif len(fields) == 2: trace_id, span_id = fields elif len(fields) == 3: trace_id, span_id, sampled = fields elif len(fields) == 4: trace_id, span_id, sampled, _parent_span_id = fields else: return SpanContext(from_header=False) else: trace_id = headers.get(_TRACE_ID_KEY) span_id = headers.get(_SPAN_ID_KEY) sampled = headers.get(_SAMPLED_KEY) if sampled is not None: # The specification encodes an enabled tracing decision as "1". # In the wild pre-standard implementations might still send "true". # "d" is set in the single header case when debugging is enabled. sampled = sampled.lower() in ('1', 'd', 'true') else: # If there's no incoming sampling decision, it was deferred to us. # Even though we set it to False here, we might still sample # depending on the tracer configuration. sampled = False trace_options = TraceOptions() trace_options.set_enabled(sampled) # TraceId and SpanId headers both have to exist if not trace_id or not span_id: return SpanContext(trace_options=trace_options) # Convert 64-bit trace ids to 128-bit if len(trace_id) == 16: trace_id = '0' * 16 + trace_id span_context = SpanContext(trace_id=trace_id, span_id=span_id, trace_options=trace_options, from_header=True) return span_context
def nope(*args, **kwargs): trace_options = TraceOptions() trace_options.set_enabled(False) return SpanContext(trace_options=trace_options)