def test_baggage_without_trace_id(self): codec = TextCodec(trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') headers = { 'Trace-ID': '0:7f:0:1', # trace_id = 0 is invalid 'trace-attr-Kiff': 'Amy', 'trace-atTR-HERMES': 'LaBarbara' } with mock.patch('jaeger_client.codecs.span_context_from_string') as \ from_str: from_str.return_value = (0, 1, 1, 1) with self.assertRaises(SpanContextCorruptedException): codec.extract(headers)
def _test_baggage_without_trace_id(tracer, trace_id_header, baggage_header_prefix, headers, match): codec = TextCodec( trace_id_header=trace_id_header, baggage_header_prefix=baggage_header_prefix, ) with mock.patch('jaeger_client.codecs.span_context_from_string') as \ from_str: from_str.return_value = (0, 1, 1, 1) # make trace ID == 0 (i.e. invalid) span_context = codec.extract(headers) span = tracer.start_span('test', child_of=span_context) assert span.context.baggage == match # also check baggage through API for k, v in six.iteritems(match): assert span.get_baggage_item(k) == v
def test_context_from_readable_headers(self): codec = TextCodec(trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') ctx = codec.extract(dict()) assert ctx[0] is None, 'No headers' bad_headers = { '_Trace_ID': '100:7f:0:1', '_trace-attr-Kiff': 'Amy' } ctx = codec.extract(bad_headers) assert ctx[0] is None, 'Bad header names' with self.assertRaises(InvalidCarrierException): codec.extract(carrier=[]) # not a dict good_headers_bad_values = { 'Trace-ID': '100:7f:0:1xxx', 'trace-attr-Kiff': 'Amy' } with self.assertRaises(TraceCorruptedException): codec.extract(good_headers_bad_values) headers = { 'Trace-ID': '100:7f:0:1', 'trace-attr-Kiff': 'Amy', 'trace-atTR-HERMES': 'LaBarbara' } trace_id, span_id, parent_id, flags, baggage = codec.extract(headers) assert trace_id == 256 assert span_id == 127 assert parent_id is None assert flags == 1 assert baggage == {'kiff': 'Amy', 'hermes': 'LaBarbara'}
def test_non_ascii_baggage_with_httplib(httpserver): # httpserver is provided by pytest-localserver httpserver.serve_content(content='Hello', code=200, headers=None) tracer = Tracer( service_name='test', reporter=InMemoryReporter(), # don't sample to avoid logging baggage to the span sampler=ConstSampler(False), ) tracer.codecs[Format.TEXT_MAP] = TextCodec(url_encoding=True) baggage = [ (b'key', b'value'), (u'key', b'value'), (b'key', bytes(chr(255))), (u'caf\xe9', 'caf\xc3\xa9'), ('caf\xc3\xa9', 'value'), ] for b in baggage: span = tracer.start_span('test') span.set_baggage_item(b[0], b[1]) headers = {} tracer.inject(span_context=span.context, format=Format.TEXT_MAP, carrier=headers) # make sure httplib doesn't blow up request = urllib2.Request(httpserver.url, None, headers) response = urllib2.urlopen(request) assert response.read() == 'Hello' response.close()
def _test_baggage_without_trace_id(tracer, trace_id_header, baggage_header_prefix, headers, match): codec = TextCodec( trace_id_header=trace_id_header, baggage_header_prefix=baggage_header_prefix, ) with mock.patch('jaeger_client.codecs.span_context_from_string') as \ from_str: from_str.return_value = (0, 1, 1, 1 ) # make trace ID == 0 (i.e. invalid) span_context = codec.extract(headers) span = tracer.start_span('test', child_of=span_context) assert span.context.baggage == match # also check baggage through API for k, v in six.iteritems(match): assert span.get_baggage_item(k) == v
def test_context_from_large_ids(self): codec = TextCodec(trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') headers = { 'Trace-ID': 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFF:1', } context = codec.extract(headers) assert context.trace_id == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF assert context.trace_id == (1 << 128) - 1 assert context.trace_id > 0 assert context.span_id == 0xFFFFFFFFFFFFFFFF assert context.span_id == (1 << 64) - 1 assert context.span_id > 0 assert context.parent_id == 0xFFFFFFFFFFFFFFFF assert context.parent_id == (1 << 64) - 1 assert context.parent_id > 0
def test_baggage_as_unicode_strings_with_httplib(httpserver): if six.PY2: import urllib2 urllib_under_test = urllib2 else: import urllib.request urllib_under_test = urllib.request # httpserver is provided by pytest-localserver httpserver.serve_content(content='Hello', code=200, headers=None) tracer = Tracer( service_name='test', reporter=InMemoryReporter(), # don't sample to avoid logging baggage to the span sampler=ConstSampler(False), ) tracer.codecs[Format.TEXT_MAP] = TextCodec(url_encoding=True) baggage = [(b'key1', b'value'), (u'key2', b'value'), ('key3', u'value'), (b'key4', bytes(chr(255)) if six.PY2 else bytes([255])), (u'key5', u'\U0001F47E')] for b in baggage: span = tracer.start_span('test') span.set_baggage_item(b[0], b[1]) headers = {} tracer.inject(span_context=span.context, format=Format.TEXT_MAP, carrier=headers) # make sure httplib doesn't blow up request = urllib_under_test.Request(httpserver.url, None, headers) response = urllib_under_test.urlopen(request) assert response.read() == b'Hello' response.close()
def test_context_from_large_ids(self): codec = TextCodec(trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') headers = { 'Trace-ID': 'FFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFF:1', } context = codec.extract(headers) assert context.trace_id == 0xFFFFFFFFFFFFFFFF assert context.trace_id == (1 << 64) - 1 assert context.trace_id > 0 assert context.span_id == 0xFFFFFFFFFFFFFFFF assert context.span_id == (1 << 64) - 1 assert context.span_id > 0 assert context.parent_id == 0xFFFFFFFFFFFFFFFF assert context.parent_id == (1 << 64) - 1 assert context.parent_id > 0
def test_context_from_large_ids(self): codec = TextCodec(trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') headers = { 'Trace-ID': 'FFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFF:1', } trace_id, span_id, parent_id, flags, baggage = codec.extract(headers) assert trace_id == 0xFFFFFFFFFFFFFFFFL assert trace_id == (1L << 64) - 1 assert trace_id > 0 assert span_id == 0xFFFFFFFFFFFFFFFFL assert span_id == (1L << 64) - 1 assert span_id > 0 assert parent_id == 0xFFFFFFFFFFFFFFFFL assert parent_id == (1L << 64) - 1 assert parent_id > 0
def test_context_to_readable_headers(self): codec = TextCodec(trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') span = Span(trace_id=256, span_id=127, parent_id=None, flags=1, operation_name='x', tracer=None, start_time=1) carrier = {} codec.inject(span, carrier) assert carrier == {'trace-id': '100:7f:0:1'} span.set_baggage_item('Fry', 'Leela') span.set_baggage_item('Bender', 'Countess de la Roca') carrier = {} codec.inject(span, carrier) assert carrier == { 'trace-id': '100:7f:0:1', 'trace-attr-bender': 'Countess de la Roca', 'trace-attr-fry': 'Leela'}
def test_context_to_readable_headers(self): for url_encoding in [False, True]: codec = TextCodec( url_encoding=url_encoding, trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') ctx = SpanContext( trace_id=256, span_id=127, parent_id=None, flags=1 ) carrier = {} codec.inject(ctx, carrier) assert carrier == {'trace-id': '100:7f:0:1'} ctx._baggage = { 'bender': 'Countess de la Roca', 'fry': u'Leela', b'key1': bytes(chr(75)) if six.PY2 else bytes([75]), u'key2': 'cafe', u'key3': u'\U0001F47E', } carrier = {} codec.inject(ctx, carrier) # NB: the reverse transformation is not exact, e.g. this fails: # assert ctx._baggage == codec.extract(carrier)._baggage # But fully supporting lossless Unicode baggage is not the goal. if url_encoding: assert carrier == { 'trace-id': '100:7f:0:1', 'trace-attr-bender': 'Countess%20de%20la%20Roca', 'trace-attr-fry': 'Leela', 'trace-attr-key1': 'K', 'trace-attr-key2': 'cafe', 'trace-attr-key3': '%F0%9F%91%BE', }, 'with url_encoding = %s' % url_encoding for key, val in six.iteritems(carrier): assert isinstance(key, str) assert isinstance(val, str), '%s' % type(val) else: assert carrier == { 'trace-id': '100:7f:0:1', 'trace-attr-bender': 'Countess de la Roca', 'trace-attr-fry': 'Leela', 'trace-attr-key1': 'K', u'trace-attr-key2': 'cafe', 'trace-attr-key3': u'\U0001F47E', }, 'with url_encoding = %s' % url_encoding
def test_context_to_readable_headers(self): for url_encoding in [False, True]: codec = TextCodec(url_encoding=url_encoding, trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') ctx = SpanContext(trace_id=256, span_id=127, parent_id=None, flags=1) carrier = {} codec.inject(ctx, carrier) assert carrier == {'trace-id': '100:7f:0:1'} ctx._baggage = { 'fry': 'Leela', 'bender': 'Countess de la Roca', } carrier = {} codec.inject(ctx, carrier) if url_encoding: assert carrier == { 'trace-id': '100:7f:0:1', 'trace-attr-bender': 'Countess%20de%20la%20Roca', 'trace-attr-fry': 'Leela' } else: assert carrier == { 'trace-id': '100:7f:0:1', 'trace-attr-bender': 'Countess de la Roca', 'trace-attr-fry': 'Leela' }
def test_context_from_bad_readable_headers(self): codec = TextCodec(trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') ctx = codec.extract(dict()) assert ctx is None, 'No headers' bad_headers = {'_Trace_ID': '100:7f:0:1', '_trace-attr-Kiff': 'Amy'} ctx = codec.extract(bad_headers) assert ctx is None, 'Bad header names' with self.assertRaises(InvalidCarrierException): codec.extract(carrier=[]) # not a dict good_headers_bad_values = { 'Trace-ID': '100:7f:0:1xxx', 'trace-attr-Kiff': 'Amy' } with self.assertRaises(SpanContextCorruptedException): codec.extract(good_headers_bad_values)
def test_context_to_readable_headers(self): for url_encoding in [False, True]: codec = TextCodec(url_encoding=url_encoding, trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') ctx = SpanContext(trace_id=256, span_id=127, parent_id=None, flags=1) carrier = {} codec.inject(ctx, carrier) assert carrier == {'trace-id': '100:7f:0:1'} ctx._baggage = { 'fry': u'Leela', 'bender': 'Countess de la Roca', b'key1': bytes(chr(255)), u'key2-caf\xe9': 'caf\xc3\xa9', u'key3': u'caf\xe9', 'key4-caf\xc3\xa9': 'value', } carrier = {} codec.inject(ctx, carrier) # NB: the reverse transformation is not exact, e.g. this fails: # assert ctx._baggage == codec.extract(carrier)._baggage # But fully supporting lossless Unicode baggage is not the goal. if url_encoding: assert carrier == { 'trace-id': '100:7f:0:1', 'trace-attr-bender': 'Countess%20de%20la%20Roca', 'trace-attr-fry': 'Leela', 'trace-attr-key1': '%FF', 'trace-attr-key2-caf\xc3\xa9': 'caf%C3%A9', 'trace-attr-key3': 'caf%C3%A9', 'trace-attr-key4-caf\xc3\xa9': 'value', }, 'with url_encoding = %s' % url_encoding for key, val in six.iteritems(carrier): assert isinstance(key, str) or isinstance(key, newstr) assert isinstance(val, str) or isinstance( val, newstr), '%s' % type(val) else: assert carrier == { 'trace-id': '100:7f:0:1', 'trace-attr-bender': 'Countess de la Roca', 'trace-attr-fry': 'Leela', 'trace-attr-key1': '\xff', u'trace-attr-key2-caf\xe9': 'caf\xc3\xa9', u'trace-attr-key3': u'caf\xe9', 'trace-attr-key4-caf\xc3\xa9': 'value', }, 'with url_encoding = %s' % url_encoding
def test_non_ascii_baggage_with_httplib(httpserver): # TODO this test requires `futurize`. Unfortunately, that also changes # how the test works under Py2. # Some observation: # - In Py2, the httplib does not like unicode strings, maybe we need to convert everything to bytes. # - Not sure yet what's the story with httplib in Py3, it seems not to like raw bytes. if six.PY3: raise ValueError('this test does not work with Py3') # httpserver is provided by pytest-localserver httpserver.serve_content(content='Hello', code=200, headers=None) tracer = Tracer( service_name='test', reporter=InMemoryReporter(), # don't sample to avoid logging baggage to the span sampler=ConstSampler(False), ) tracer.codecs[Format.TEXT_MAP] = TextCodec(url_encoding=True) baggage = [ (b'key', b'value'), (u'key', b'value'), (b'key', byte255), (u'caf\xe9', 'caf\xc3\xa9'), ('caf\xc3\xa9', 'value'), ] for b in baggage: span = tracer.start_span('test') span.set_baggage_item(b[0], b[1]) headers = {} tracer.inject(span_context=span.context, format=Format.TEXT_MAP, carrier=headers) # make sure httplib doesn't blow up import urllib2 request = urllib2.Request(httpserver.url, None, headers) response = urllib2.urlopen(request) assert response.read() == b'Hello' response.close()
def test_debug_id(): debug_header = 'correlation-id' tracer = Tracer( service_name='test', reporter=InMemoryReporter(), sampler=ConstSampler(True), debug_id_header=debug_header, ) tracer.codecs[Format.TEXT_MAP] = TextCodec( url_encoding=False, debug_id_header=debug_header, ) carrier = {debug_header: 'Coraline'} context = tracer.extract(Format.TEXT_MAP, carrier) assert context.is_debug_id_container_only assert context.debug_id == 'Coraline' span = tracer.start_span('test', child_of=context) assert span.is_debug() assert span.is_sampled() tags = [t for t in span.tags if t.key == debug_header] assert len(tags) == 1 assert tags[0].vStr == 'Coraline'
def test_context_from_bad_readable_headers(self): codec = TextCodec(trace_id_header='Trace_ID', baggage_header_prefix='Trace-Attr-') ctx = codec.extract(dict()) assert ctx is None, 'No headers' bad_headers = { '_Trace_ID': '100:7f:0:1', '_trace-attr-Kiff': 'Amy' } ctx = codec.extract(bad_headers) assert ctx is None, 'Bad header names' with self.assertRaises(InvalidCarrierException): codec.extract(carrier=[]) # not a dict good_headers_bad_values = { 'Trace-ID': '100:7f:0:1xxx', 'trace-attr-Kiff': 'Amy' } with self.assertRaises(SpanContextCorruptedException): codec.extract(good_headers_bad_values)
def test_wrong_carrier(self): codec = TextCodec() with self.assertRaises(InvalidCarrierException): codec.inject(span_context={}, carrier=[]) # array is no good with self.assertRaises(InvalidCarrierException): codec.extract(carrier=[])