def get_recorder(): recorder = Recorder() t = BasicTracer(recorder=recorder) t.register_required_propagators() opentracing.tracer = t return recorder
def test_trace_requests_no_error_tag(monkeypatch): resp = Response() resp.status_code = 400 resp.url = URL trace_requests(set_error_tag=False) monkeypatch.setattr('opentracing_utils.libs._requests.__requests_http_send', assert_send_request_mock(resp)) recorder = Recorder() t = BasicTracer(recorder=recorder) t.register_required_propagators() opentracing.tracer = t top_span = opentracing.tracer.start_span(operation_name='top_span') with top_span: response = requests.get(URL, headers={CUSTOM_HEADER: CUSTOM_HEADER_VALUE}) assert len(recorder.spans) == 2 assert recorder.spans[0].context.trace_id == top_span.context.trace_id assert recorder.spans[0].parent_id == recorder.spans[-1].context.span_id assert response.status_code == resp.status_code assert recorder.spans[0].tags[tags.HTTP_STATUS_CODE] == resp.status_code assert recorder.spans[0].tags[tags.HTTP_URL] == URL assert recorder.spans[0].tags[tags.HTTP_METHOD] == 'GET' assert recorder.spans[0].tags[tags.SPAN_KIND] == tags.SPAN_KIND_RPC_CLIENT assert recorder.spans[0].tags[tags.PEER_HOSTNAME] == 'example.com' assert recorder.spans[0].tags['timeout'] is None assert recorder.spans[0].tags[tags.COMPONENT] == 'requests' assert recorder.spans[0].operation_name == '{}_get'.format(OPERATION_NAME_PREFIX) assert 'error' not in recorder.spans[0].tags
def test_trace_requests_with_ignore_url_pattern_prune_kwargs(monkeypatch): """ In case there is a parent span already, the ignore url pattern must still be respected """ resp = Response() resp.status_code = 200 resp.url = URL trace_requests(ignore_url_patterns=[r".*{}.*".format(URL)]) monkeypatch.setattr('opentracing_utils.libs._requests.__requests_http_send', assert_send_request_mock_no_traces(resp)) @trace() def f1(): pass recorder = Recorder() t = BasicTracer(recorder=recorder) t.register_required_propagators() opentracing.tracer = t top_span = opentracing.tracer.start_span(operation_name='top_span') with top_span: response = requests.get(URL, headers={CUSTOM_HEADER: CUSTOM_HEADER_VALUE}) f1() # Top span, and @trace for f1() create spans. With the ignore pattern # in place, the call to requests.get should not add a span assert len(recorder.spans) == 2 assert recorder.spans[0].context.trace_id == top_span.context.trace_id assert recorder.spans[0].operation_name == 'f1' assert recorder.spans[1].operation_name == 'top_span' assert response.status_code == resp.status_code
def test_trace_requests_no_parent_span(monkeypatch): resp = Response() resp.status_code = 200 resp.url = URL monkeypatch.setattr('opentracing_utils.libs._requests.__requests_http_send', assert_send_request_mock(resp)) recorder = Recorder() t = BasicTracer(recorder=recorder) t.register_required_propagators() opentracing.tracer = t session = requests.Session() session.headers.update({CUSTOM_HEADER: CUSTOM_HEADER_VALUE}) response = session.get(URL) assert len(recorder.spans) == 1 assert recorder.spans[0].tags[tags.HTTP_STATUS_CODE] == resp.status_code assert recorder.spans[0].tags[tags.HTTP_URL] == URL assert recorder.spans[0].tags[tags.HTTP_METHOD] == 'GET' assert recorder.spans[0].tags[tags.SPAN_KIND] == tags.SPAN_KIND_RPC_CLIENT assert recorder.spans[0].tags[tags.PEER_HOSTNAME] == 'example.com' assert recorder.spans[0].tags['timeout'] is None assert recorder.spans[0].tags[tags.COMPONENT] == 'requests' assert recorder.spans[0].operation_name == '{}_get'.format(OPERATION_NAME_PREFIX) assert response.status_code == resp.status_code
def test_trace_requests_extract_span_fail(monkeypatch): resp = Response() resp.status_code = 200 resp.url = URL send_request_mock = MagicMock() send_request_mock.return_value = resp extract_span_mock = MagicMock() extract_span_mock.return_value = None, None monkeypatch.setattr('opentracing_utils.libs._requests.__requests_http_send', send_request_mock) monkeypatch.setattr('opentracing_utils.libs._requests.get_span_from_kwargs', extract_span_mock) logger = MagicMock() monkeypatch.setattr('opentracing_utils.libs._requests.logger', logger) recorder = Recorder() t = BasicTracer(recorder=recorder) t.register_required_propagators() opentracing.tracer = t session = requests.Session() session.headers.update({CUSTOM_HEADER: CUSTOM_HEADER_VALUE}) response = session.get(URL) assert response.status_code == resp.status_code logger.warn.assert_called_once()
def wrapper(*args, **kwargs): tracer = BasicTracer() tracer.register_required_propagators() #span_context = tracer.extract( # format=Format.HTTP_HEADERS, # carrier=request.headers, #) # terrible workaround, because the python opentracing libraries lack a reference implementation # https://github.com/opentracing/opentracing-python # (just no-op). I do not have time to write the reference implementation, so we'll manually extract the # headers here, possibly breaking forward compatibility. fault = request.headers.get("Ot-Baggage-Injectfault") if fault is not None: service, faults = fault.split("_") if service != name: return func(*args, **kwargs) else: print "FAULT is " + fault f, param = faults.split(":") if f == "delay": time.sleep(int(param)) return func(*args, **kwargs) else: return else: return func(*args, **kwargs)
def test_trace_requests_session(monkeypatch): resp = Response() resp.status_code = 200 resp.url = URL monkeypatch.setattr( 'opentracing_utils.libs._requests.__requests_http_send', assert_send_reuqest_mock(resp)) recorder = Recorder() t = BasicTracer(recorder=recorder) t.register_required_propagators() opentracing.tracer = t top_span = opentracing.tracer.start_span(operation_name='top_span') with top_span: session = requests.Session() session.headers.update({CUSTOM_HEADER: CUSTOM_HEADER_VALUE}) response = session.get(URL) assert len(recorder.spans) == 2 assert recorder.spans[0].context.trace_id == top_span.context.trace_id assert recorder.spans[0].parent_id == recorder.spans[-1].context.span_id assert recorder.spans[-1].operation_name == 'top_span' assert response.status_code == resp.status_code assert recorder.spans[0].tags[tags.HTTP_STATUS_CODE] == resp.status_code assert recorder.spans[0].tags[tags.HTTP_URL] == URL assert recorder.spans[0].tags[tags.HTTP_METHOD] == 'GET' assert recorder.spans[0].tags[tags.SPAN_KIND] == tags.SPAN_KIND_RPC_CLIENT assert recorder.spans[0].tags[tags.PEER_HOSTNAME] == 'example.com'
def tracer(asyncio_scope_manager): t = BasicTracer( recorder=InMemoryRecorder(), scope_manager=asyncio_scope_manager, ) t.register_required_propagators() return t
def test_trace_requests_span_extractor(monkeypatch): resp = Response() resp.status_code = 200 resp.url = "http://example.com/" recorder = Recorder() t = BasicTracer(recorder=recorder) t.register_required_propagators() opentracing.tracer = t top_span = opentracing.tracer.start_span(operation_name='top_span') def span_extractor(*args, **kwargs): return top_span trace_requests(span_extractor=span_extractor) monkeypatch.setattr( 'opentracing_utils.libs._requests.__requests_http_send', assert_send_request_mock(resp)) # disable getting the span from stack monkeypatch.setattr('opentracing_utils.span.inspect_span_from_stack', lambda: None) response = requests.get("http://example.com/") top_span.finish() assert len(recorder.spans) == 2 assert recorder.spans[0].context.trace_id == top_span.context.trace_id assert recorder.spans[0].parent_id == recorder.spans[1].context.span_id assert recorder.spans[0].operation_name == 'http_send_get' assert recorder.spans[-1].operation_name == 'top_span' assert response.status_code == resp.status_code
async def before_srver_start(app, loop): queue = asyncio.Queue() app.queue = queue loop.create_task(consume(queue, app.config.ZIPKIN_SERVER)) reporter = AioReporter(queue=queue) tracer = BasicTracer(recorder=reporter) tracer.register_required_propagators() opentracing.tracer = tracer app.db = await ConnectionPool(loop=loop).init(DB_CONFIG)
def tracer(): t = BasicTracer(recorder=InMemoryRecorder()) t.register_required_propagators() old_tracer = opentracing.tracer opentracing.tracer = t try: yield t except: opentracing.tracer = old_tracer
def tracer(): dummy_tracer = BasicTracer(recorder=InMemoryRecorder()) dummy_tracer.register_required_propagators() old_tracer = opentracing.tracer opentracing.tracer = dummy_tracer try: yield dummy_tracer finally: opentracing.tracer = old_tracer
def test_span_missing_all_fields(): tracer = BasicTracer() tracer.register_required_propagators() # Given an empty carrier headers = {} # When .extract is called ctx = tracer.extract(Format.TEXT_MAP, headers) # Then it should return None assert ctx is None
def tracer(): old_tracer = opentracing.tracer t = BasicTracer( recorder=InMemoryRecorder(), scope_manager=TornadoScopeManager(), ) t.register_required_propagators() opentracing.tracer = t try: yield t finally: opentracing.tracer = old_tracer
def test_start_span(): """ Test in process child span creation.""" tracer = BasicTracer() tracer.register_required_propagators() sp = tracer.start_span(operation_name='test') sp.set_baggage_item('foo', 'bar') child = tracer.start_span( operation_name='child', child_of=sp.context) assert child.context.trace_id == sp.context.trace_id assert child.context.sampled == sp.context.sampled assert child.context.baggage == sp.context.baggage assert child.parent_id == sp.context.span_id
def test_span_missing_all_headers(): tracer = BasicTracer() tracer.register_required_propagators() # Given an carrier with no ot-headers headers = { 'Content-Type': 'text/html', 'Authorization': 'Digest 123456', } # When .extract is called ctx = tracer.extract(Format.TEXT_MAP, headers) # Then it should return None assert ctx is None
async def before_srver_start(app, loop): queue = asyncio.Queue() app.queue = queue loop.create_task(consume(queue, app.config['ZIPKIN_SERVER'])) reporter = AioReporter(queue=queue) tracer = BasicTracer(recorder=reporter) tracer.register_required_propagators() opentracing.tracer = tracer app.db = await ConnectionPool(loop=loop).init(app.config['DB_CONFIG']) service_names = app.config['SERVICES'] app.services = defaultdict(list) service = ServiceManager(loop=loop) for name in service_names: s = service.discovery_service(name) app.services[s].extend(s)
async def before_server_start(app, loop): queue = asyncio.Queue() app.queue = queue loop.create_task(consume(queue, app)) loop.create_task(service_watcher(app, loop)) reporter = AioReporter(queue=queue) tracer = BasicTracer(recorder=reporter) tracer.register_required_propagators() opentracing.tracer = tracer app.db = await ConnectionPool(loop=loop).init(app.config['DB_CONFIG']) service = ServiceManager(loop=loop, host=app.config['CONSUL_AGENT_HOST']) services = await service.discovery_services() app.services = defaultdict(list) for name in services[1].keys(): s = await service.discovery_service(name) app.services[name].extend(s)
def ctx(self): ld = TestLocalDiscovery() self.ctx_local.append(ld) discovery = AIOCompositeDiscovery(self.get_local_discovery(), self.dict_discovery) discovery.tracer = BasicTracer(self.recorder) return Context(discovery, self.svc)
async def before_server_start(app, loop): queue = asyncio.Queue() app.queue = queue if consul_enabled: app.service_manager = ServiceManager( consul_host=app.config['CONSUL_AGENT_HOST'], consul_port=app.config['CONSUL_AGENT_PORT'], loop=loop, ) loop.create_task(service_watcher(app, loop)) loop.create_task(consume(queue, app)) reporter = AioReporter(queue=queue) tracer = BasicTracer(recorder=reporter) tracer.register_required_propagators() opentracing.tracer = tracer app.db = await ConnectionPool(loop=loop).init(app.config['DB_CONFIG'])
def init_opentracing_tracer(tracer, **kwargs): if tracer == OPENTRACING_BASIC: from basictracer import BasicTracer # noqa recorder = kwargs.get('recorder') sampler = kwargs.get('sampler') opentracing.tracer = BasicTracer(recorder=recorder, sampler=sampler) elif tracer == OPENTRACING_INSTANA: import instana.options as InstanaOpts import instana.tracer # noqa service = kwargs.pop('service', os.environ.get('OPENTRACING_INSTANA_SERVICE')) log_level = kwargs.pop('log_level', logging.INFO) instana.tracer.init( InstanaOpts.Options(service=service, log_level=log_level, **kwargs)) elif tracer == OPENTRACING_LIGHTSTEP: import lightstep # Get Lightstep specific config vars component_name = kwargs.pop( 'component_name', os.environ.get('OPENTRACING_LIGHTSTEP_COMPONENT_NAME')) access_token = kwargs.pop( 'access_token', os.environ.get('OPENTRACING_LIGHTSTEP_ACCESS_TOKEN')) collector_host = kwargs.pop( 'collector_host', os.environ.get('OPENTRACING_LIGHTSTEP_COLLECTOR_HOST', 'collector.lightstep.com')) collector_port = kwargs.pop( 'collector_port', int(os.environ.get('OPENTRACING_LIGHTSTEP_COLLECTOR_PORT', 443))) verbosity = kwargs.pop( 'verbosity', int(os.environ.get('OPENTRACING_LIGHTSTEP_VERBOSITY', 0))) if not access_token: logger.warn('Initializing LighStep tracer with no access_token!') opentracing.tracer = lightstep.Tracer(component_name=component_name, access_token=access_token, collector_host=collector_host, collector_port=collector_port, verbosity=verbosity, **kwargs) elif tracer == OPENTRACING_JAEGER: from jaeger_client import Config service_name = kwargs.pop( 'service_name', os.environ.get('OPENTRACING_JAEGER_SERVICE_NAME')) config = kwargs.pop('config', {}) jaeger_config = Config(config=config, service_name=service_name) opentracing.tracer = jaeger_config.initialize_tracer() else: opentracing.tracer = opentracing.Tracer()
def test_get_new_span_with_extractor_with_scope(): opentracing.tracer = BasicTracer() parent_span = opentracing.tracer.start_span() extractor = MagicMock() extractor.return_value = parent_span ctx = '123' def f(ctx, extras=True): pass with opentracing.tracer.start_active_span("ignored_parent", finish_on_close=True): span_arg_name, using_scope_manager, span = get_new_span( f, [ctx], {'extras': True}, span_extractor=extractor, inspect_stack=False) assert DEFAULT_SPAN_ARG_NAME == span_arg_name # span_extractor takes precedence. assert span.parent_id == parent_span.context.span_id assert using_scope_manager is False extractor.assert_called_with(ctx, extras=True)
def start_span(self, *args, **kwargs): span = BasicTracer.start_span(self, *args, **kwargs) if span.parent_id is None: span.context.trace_id = '1-%x-%s' % (int( time.time()), binascii.b2a_hex(os.urandom(12)).decode('ascii')) span.context.span_id = binascii.b2a_hex(os.urandom(8)).decode('ascii') return span
def test_trace_generator(): @trace() def f1(): list(l2_gen()) @trace() def f2(): pass @trace(pass_span=True) def l2_gen(**kwargs): s = extract_span_from_kwargs(**kwargs) # noqa f2(span=s) for i in range(10): yield i recorder = Recorder() opentracing.tracer = BasicTracer(recorder=recorder) test_span = opentracing.tracer.start_span(operation_name='test_trace') with test_span: f1() assert len(recorder.spans) == 4 assert recorder.spans[0].context.trace_id == test_span.context.trace_id assert recorder.spans[0].parent_id == recorder.spans[2].context.span_id # Inside generator takes generator as parent! assert recorder.spans[1].context.trace_id == test_span.context.trace_id assert recorder.spans[1].parent_id == recorder.spans[0].context.span_id assert recorder.spans[2].context.trace_id == test_span.context.trace_id assert recorder.spans[2].parent_id == recorder.spans[3].context.span_id
def test_trace_single_with_extractor(return_span): recorder = Recorder() opentracing.tracer = BasicTracer(recorder=recorder) test_span = opentracing.tracer.start_span(operation_name='test_trace') other_span = opentracing.tracer.start_span(operation_name='other_span') extractor = MagicMock() extractor.return_value = test_span if return_span else None @trace(span_extractor=extractor) def f1(): pass with other_span: # other_span could be ignored if extractor returned a span! f1(span=other_span) if return_span: assert recorder.spans[0].context.trace_id == test_span.context.trace_id assert recorder.spans[0].parent_id == test_span.context.span_id else: assert recorder.spans[ 0].context.trace_id == other_span.context.trace_id assert recorder.spans[0].parent_id == other_span.context.span_id
def test_trace_loop(): @trace() def f1(): pass def f0(): f1() recorder = Recorder() opentracing.tracer = BasicTracer(recorder=recorder) for i in range(3): test_span = opentracing.tracer.start_span(operation_name='test_trace') test_span.set_tag('loop', i) with test_span: f0() assert len(recorder.spans) == 6 root_spans = recorder.spans[1::2] for idx, span in enumerate(recorder.spans[::2]): parent_span = root_spans[idx] assert parent_span.tags == {'loop': idx} assert span.context.trace_id == parent_span.context.trace_id assert span.parent_id == parent_span.context.span_id
def test_trace_nested_with_args(): @trace() def parent(arg1, arg2): nested(arg1) @trace() def nested(arg1, **kwargs): assert is_span_in_kwargs(**kwargs) is False @trace(pass_span=True) def expect_span(**kwargs): assert is_span_in_kwargs(**kwargs) is True recorder = Recorder() opentracing.tracer = BasicTracer(recorder=recorder) test_span = opentracing.tracer.start_span(operation_name='test_trace') with test_span: parent(1, 2) expect_span() assert len(recorder.spans) == 4 assert recorder.spans[0].context.trace_id == test_span.context.trace_id assert recorder.spans[0].parent_id == recorder.spans[1].context.span_id assert recorder.spans[1].context.trace_id == test_span.context.trace_id assert recorder.spans[1].parent_id == test_span.context.span_id assert recorder.spans[-1].parent_id is None
def test_propagation(): tracer = BasicTracer() sp = tracer.start_span(operation_name="test") sp.set_baggage_item("foo", "bar") opname = 'op' tests = [(Format.BINARY, bytearray()), (Format.TEXT_MAP, {})] for format, carrier in tests: tracer.inject(sp, format, carrier) child = tracer.join(opname, format, carrier) assert child.raw.context.trace_id == sp.raw.context.trace_id assert child.raw.context.parent_id == sp.raw.context.span_id assert child.raw.context.sampled == sp.raw.context.sampled assert child.raw.baggage == sp.raw.baggage
async def setUp(self): self.recorder = InMemoryRecorder() self.dict_discovery = SimpleDictDiscovery({}) self.discovery = AIOCompositeDiscovery(self.get_local_discovery(), self.dict_discovery) self.discovery.tracer = BasicTracer(self.recorder) self.svc = DummyService() await self.ensure_future(self.svc.on_start())
def test_span_log_kv(): recorder = InMemoryRecorder() tracer = BasicTracer(recorder=recorder) span = tracer.start_span('x') span.log_kv({ 'foo': 'bar', 'baz': 42, }) span.finish() finished_spans = recorder.get_spans() assert len(finished_spans) == 1 assert len(finished_spans[0].logs) == 1 assert len(finished_spans[0].logs[0].key_values) == 2 assert finished_spans[0].logs[0].key_values['foo'] == 'bar' assert finished_spans[0].logs[0].key_values['baz'] == 42
def test_span_log_kv(): recorder = InMemoryRecorder() tracer = BasicTracer(recorder=recorder) span = tracer.start_span('x') span.log_kv({ 'foo': 'bar', 'baz': 42, }) span.finish() finished_spans = recorder.get_spans() assert len(finished_spans) == 1 assert len(finished_spans[0].logs) == 1 assert len(finished_spans[0].logs[0].key_values) == 2 assert finished_spans[0].logs[0].key_values['foo'] == 'bar' assert finished_spans[0].logs[0].key_values['baz'] == 42
def get_tracer(name=None): global tracer if tracer: return tracer recorder = FanRecorder(name or 'no_name', send_to_zipkin=ZIPKIN) tracer = BasicTracer(recorder) return tracer
def test_trace_requests_with_tags(monkeypatch): resp = Response() resp.status_code = 200 resp.url = URL trace_requests(default_tags={'tag1': 'value1'}) monkeypatch.setattr('opentracing_utils.libs._requests.__requests_http_send', assert_send_request_mock(resp)) @trace() def f1(): pass recorder = Recorder() t = BasicTracer(recorder=recorder) t.register_required_propagators() opentracing.tracer = t top_span = opentracing.tracer.start_span(operation_name='top_span') with top_span: response = requests.get(URL, headers={CUSTOM_HEADER: CUSTOM_HEADER_VALUE}) f1() assert len(recorder.spans) == 3 assert recorder.spans[0].context.trace_id == top_span.context.trace_id assert recorder.spans[0].parent_id == recorder.spans[-1].context.span_id assert recorder.spans[-1].operation_name == 'top_span' # ``requests`` default tags do not leak to other unrelated spans! assert recorder.spans[1].tags == {} assert recorder.spans[1].operation_name == 'f1' assert response.status_code == resp.status_code assert recorder.spans[0].tags[tags.HTTP_STATUS_CODE] == resp.status_code assert recorder.spans[0].tags[tags.HTTP_URL] == URL assert recorder.spans[0].tags[tags.HTTP_METHOD] == 'GET' assert recorder.spans[0].tags[tags.SPAN_KIND] == tags.SPAN_KIND_RPC_CLIENT assert recorder.spans[0].tags[tags.PEER_HOSTNAME] == 'example.com' assert recorder.spans[0].tags['timeout'] is None assert recorder.spans[0].tags[tags.COMPONENT] == 'requests' assert recorder.spans[0].operation_name == '{}_get'.format(OPERATION_NAME_PREFIX) assert recorder.spans[0].tags['tag1'] == 'value1'
def test_span_sampling_priority(): recorder = InMemoryRecorder() tracer = BasicTracer(recorder=recorder) span = tracer.start_span('x') assert span.context.sampled is True span.set_tag(tags.SAMPLING_PRIORITY, 0) assert span.context.sampled is False span.finish() assert len(recorder.get_spans()) == 1 def get_sampled_spans(): return [span for span in recorder.get_spans() if span.context.sampled] assert len(get_sampled_spans()) == 0
def test_propagation(): tracer = BasicTracer() tracer.register_required_propagators() sp = tracer.start_span(operation_name='test') sp.context.sampled = False sp.set_baggage_item('foo', 'bar') # Test invalid types with pytest.raises(UnsupportedFormatException): tracer.inject(sp.context, 'invalid', {}) with pytest.raises(UnsupportedFormatException): tracer.extract('invalid', {}) tests = [(Format.BINARY, bytearray()), (Format.TEXT_MAP, {})] for format, carrier in tests: tracer.inject(sp.context, format, carrier) extracted_ctx = tracer.extract(format, carrier) assert extracted_ctx.trace_id == sp.context.trace_id assert extracted_ctx.span_id == sp.context.span_id assert extracted_ctx.sampled == sp.context.sampled assert extracted_ctx.baggage == sp.context.baggage # Test string value of sampled field headers = {} tracer.inject(sp.context, Format.HTTP_HEADERS, headers) headers['ot-tracer-sampled'] = '0' span_ctx0 = tracer.extract(Format.HTTP_HEADERS, headers) assert not span_ctx0.sampled headers['ot-tracer-sampled'] = '1' span_ctx1 = tracer.extract(Format.HTTP_HEADERS, headers) assert span_ctx1.sampled
def tracer(self): t = BasicTracer() t.register_required_propagators() return t
def tracer(): t = BasicTracer(recorder=InMemoryRecorder()) t.register_required_propagators() return t