def test_encoding(encoding, validate_fn): zipkin_attrs = ZipkinAttrs( trace_id=generate_random_64bit_string(), span_id=generate_random_64bit_string(), parent_span_id=generate_random_64bit_string(), is_sampled=True, flags=None, ) inner_span_id = generate_random_64bit_string() mock_transport_handler = MockTransportHandler(10000) # Let's hardcode the timestamp rather than call time.time() every time. # The issue with time.time() is that the convertion to int of the # returned float value * 1000000 is not precise and in the same test # sometimes returns N and sometimes N+1. This ts value doesn't have that # issue afaict, probably since it ends in zeros. ts = 1538544126.115900 with mock.patch("time.time", autospec=True) as mock_time: # zipkin.py start, logging_helper.start, 3 x logging_helper.stop # I don't understand why logging_helper.stop would run 3 times, but # that's what I'm seeing in the test mock_time.side_effect = iter( [ts, ts, ts + 10, ts + 10, ts + 10, ts + 10, ts + 10] ) with zipkin.zipkin_span( service_name="test_service_name", span_name="test_span_name", transport_handler=mock_transport_handler, binary_annotations={"some_key": "some_value"}, encoding=encoding, zipkin_attrs=zipkin_attrs, host="10.0.0.0", port=8080, kind=Kind.CLIENT, ) as span: with mock.patch.object( zipkin, "generate_random_64bit_string", return_value=inner_span_id, ): with zipkin.zipkin_span( service_name="test_service_name", span_name="inner_span", timestamp=ts, duration=5, annotations={"ws": ts}, ): span.add_sa_binary_annotation( 8888, "sa_service", "2001:0db8:85a3:0000:0000:8a2e:0370:7334", ) with zipkin.zipkin_span( service_name="test_service_name", span_name="producer_span", timestamp=ts, duration=10, kind=Kind.PRODUCER, ): pass output = mock_transport_handler.get_payloads()[0] validate_fn(output, zipkin_attrs, inner_span_id, ts)
def _do_test_concurrent_subrequests_in_threads(thread_class): """What if a thread has a span context, then fires off N threads to do N subrequests in parallel? Surely the spans of the subrequests should be siblings whose parentID is equal to the first thread's span context's spanID. Furthermore, a final sub-span created in the first thread should be a child of that thread (no leaking of span stack from the child threads). """ transport = MockTransportHandler() with zipkin_span( service_name="main_thread", span_name="handle_one_big_request", transport_handler=transport, sample_rate=100.0, encoding=Encoding.V2_JSON, use_128bit_trace_id=True, ) as span_ctx: assert True is span_ctx._is_local_root_span assert span_ctx.logging_context expected_trace_id = span_ctx.zipkin_attrs.trace_id expected_parent_id = span_ctx.zipkin_attrs.span_id # Now do three subrequests req_count = 3 threads = [] output_q = queue.Queue() for thread_idx in range(req_count): this_thread = thread_class( target=_do_one_little_request, args=(output_q, "input-%d" % thread_idx) ) threads.append(this_thread) this_thread.start() outputs = set() for thread in threads: thread.join() outputs.add(output_q.get()) assert {"input-0-output", "input-1-output", "input-2-output"} == outputs output = transport.get_payloads() assert len(output) == 1 spans = sorted(json.loads(output[0]), key=itemgetter("timestamp")) assert len(spans) == 4 parent_span = spans[0] subrequest_spans = spans[1:] assert len(subrequest_spans) == 3 assert parent_span["name"] == "handle_one_big_request" for span in subrequest_spans: assert "do-the-thing" == span["name"] assert span["tags"]["input.was"] in ("input-0", "input-1", "input-2") assert expected_trace_id == span["traceId"] # Perhaps most importantly, all the subrequest spans should share the same # parentId, which is the main thread's span's 'id' assert expected_parent_id == span["parentId"]
def test__get_path_content_type(self, encoding, path, content_type): transport = MockTransportHandler() with zipkin_span( service_name="my_service", span_name="home", sample_rate=100, transport_handler=transport, encoding=encoding, ): pass spans = transport.get_payloads()[0] http_transport = SimpleHTTPTransport("localhost", 9411) assert http_transport._get_path_content_type(spans) == (path, content_type)
def test_decorator_works_in_a_new_thread(): """The zipkin_span decorator is instantiated in a thread and then run in another. Let's verify that it works and that it stores the span in the right thread's thread-storage. """ transport = MockTransportHandler() thread = threading.Thread(target=run_inside_another_thread, args=(transport,)) thread.start() thread.join() output = transport.get_payloads() assert len(output) == 1 spans = json.loads(output[0]) assert len(spans) == 2 assert spans[0]["name"] == "service1_do_stuff" assert spans[1]["name"] == "index"
def test_override_span_name(): transport = MockTransportHandler() with zipkin.zipkin_span( service_name='my_service', span_name='span_name', transport_handler=transport, kind=Kind.CLIENT, sample_rate=100.0, encoding=Encoding.V1_JSON, ) as context: context.override_span_name('new_span_name') with zipkin.zipkin_span( service_name='my_service', span_name='nested_span', ) as nested_context: nested_context.override_span_name('new_nested_span') spans = json.loads(transport.get_payloads()[0]) assert len(spans) == 2 assert spans[0]['name'] == 'new_nested_span' assert spans[1]['name'] == 'new_span_name'