diff --git a/instana/http_propagator.py b/instana/http_propagator.py index 48f20ce3..15a6a77a 100644 --- a/instana/http_propagator.py +++ b/instana/http_propagator.py @@ -3,27 +3,43 @@ from basictracer.context import SpanContext from instana import util, log -prefix_tracer_state = 'X-Instana-' -field_name_trace_id = prefix_tracer_state + 'T' -field_name_span_id = prefix_tracer_state + 'S' -field_count = 2 + +# The carrier can be a dict or a list. +# Using the trace header as an example, it can be in the following forms +# for extraction: +# X-Instana-T +# HTTP_X_INSTANA_T +# +# The second form above is found in places like Django middleware for +# incoming requests. +# +# For injection, we only support the standard format: +# X-Instana-T class HTTPPropagator(): """A Propagator for Format.HTTP_HEADERS. """ + HEADER_KEY_T = 'X-Instana-T' + HEADER_KEY_S = 'X-Instana-S' + HEADER_KEY_L = 'X-Instana-L' + ALT_HEADER_KEY_T = 'HTTP_X_INSTANA_T' + ALT_HEADER_KEY_S = 'HTTP_X_INSTANA_S' + ALT_HEADER_KEY_L = 'HTTP_X_INSTANA_L' + def inject(self, span_context, carrier): try: trace_id = util.id_to_header(span_context.trace_id) span_id = util.id_to_header(span_context.span_id) + if type(carrier) is dict or hasattr(carrier, "__dict__"): - carrier[field_name_trace_id] = trace_id - carrier[field_name_span_id] = span_id + carrier[self.HEADER_KEY_T] = trace_id + carrier[self.HEADER_KEY_S] = span_id + carrier[self.HEADER_KEY_L] = "1" elif type(carrier) is list: - trace_header = (field_name_trace_id, trace_id) - carrier.append(trace_header) - span_header = (field_name_span_id, span_id) - carrier.append(span_header) + carrier.append((self.HEADER_KEY_T, trace_id)) + carrier.append((self.HEADER_KEY_S, span_id)) + carrier.append((self.HEADER_KEY_L, "1")) else: raise Exception("Unsupported carrier type", type(carrier)) @@ -39,9 +55,15 @@ def extract(self, carrier): # noqa else: raise ot.SpanContextCorruptedException() - if field_name_trace_id in dc and field_name_span_id in dc: - trace_id = util.header_to_id(dc[field_name_trace_id]) - span_id = util.header_to_id(dc[field_name_span_id]) + # Look for standard X-Instana-T/S format + if self.HEADER_KEY_T in dc and self.header_key_s in dc: + trace_id = util.header_to_id(dc[self.HEADER_KEY_T]) + span_id = util.header_to_id(dc[self.HEADER_KEY_S]) + + # Alternatively check for alternate HTTP_X_INSTANA_T/S style + elif self.ALT_HEADER_KEY_T in dc and self.ALT_HEADER_KEY_S in dc: + trace_id = util.header_to_id(dc[self.ALT_HEADER_KEY_T]) + span_id = util.header_to_id(dc[self.ALT_HEADER_KEY_S]) return SpanContext(span_id=span_id, trace_id=trace_id, diff --git a/tests/test_ot_propagators.py b/tests/test_ot_propagators.py new file mode 100644 index 00000000..e3996fa9 --- /dev/null +++ b/tests/test_ot_propagators.py @@ -0,0 +1,33 @@ +import instana.http_propagator as ihp +import opentracing as ot +from instana import tracer, options, util +from nose.tools import assert_equals +import inspect + + +def test_basics(): + inspect.isclass(ihp.HTTPPropagator) + + inject_func = getattr(ihp.HTTPPropagator, "inject", None) + assert inject_func + assert callable(inject_func) + + extract_func = getattr(ihp.HTTPPropagator, "extract", None) + assert extract_func + assert callable(extract_func) + + +def test_inject(): + opts = options.Options() + ot.global_tracer = tracer.InstanaTracer(opts) + + carrier = {} + span = ot.global_tracer.start_span("nosetests") + ot.global_tracer.inject(span.context, ot.Format.HTTP_HEADERS, carrier) + + assert 'X-Instana-T' in carrier + assert_equals(carrier['X-Instana-T'], util.id_to_header(span.context.trace_id)) + assert 'X-Instana-S' in carrier + assert_equals(carrier['X-Instana-S'], util.id_to_header(span.context.span_id)) + assert 'X-Instana-L' in carrier + assert_equals(carrier['X-Instana-L'], "1")