Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 35 additions & 13 deletions instana/http_propagator.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand All @@ -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,
Expand Down
33 changes: 33 additions & 0 deletions tests/test_ot_propagators.py
Original file line number Diff line number Diff line change
@@ -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")