def test_zipkin_span_trace_with_0_sample_rate( logging_context_cls_mock, logger_handler_cls_mock, create_endpoint_mock, create_attrs_for_span_mock, push_zipkin_attrs_mock, pop_zipkin_attrs_mock, ): create_attrs_for_span_mock.return_value = ZipkinAttrs( trace_id=generate_random_64bit_string(), span_id=generate_random_64bit_string(), parent_span_id=None, flags='0', is_sampled=False, ) with zipkin.zipkin_span( service_name='some_service_name', span_name='span_name', transport_handler=mock.Mock(), sample_rate=0.0, ) as zipkin_context: assert zipkin_context.port == 0 pass create_attrs_for_span_mock.assert_called_once_with( sample_rate=0.0, use_128bit_trace_id=False, ) push_zipkin_attrs_mock.assert_called_once_with( create_attrs_for_span_mock.return_value) assert create_endpoint_mock.call_count == 0 assert logger_handler_cls_mock.call_count == 0 assert logging_context_cls_mock.call_count == 0 pop_zipkin_attrs_mock.assert_called_once_with()
def create_attrs_for_span(sample_rate=100.0, trace_id=None, span_id=None): """Creates a set of zipkin attributes for a span. :param sample_rate: Float between 0.0 and 100.0 to determine sampling rate :type sample_rate: float :param trace_id: Optional 16-character hex string representing a trace_id. If this is None, a random trace_id will be generated. :type trace_id: str :param span_id: Optional 16-character hex string representing a span_id. If this is None, a random span_id will be generated. :type span_id: str """ # Calculate if this trace is sampled based on the sample rate if trace_id is None: trace_id = generate_random_64bit_string() if span_id is None: span_id = generate_random_64bit_string() if sample_rate == 0.0: is_sampled = False else: is_sampled = (random.random() * 100) < sample_rate return ZipkinAttrs( trace_id=trace_id, span_id=span_id, parent_span_id=None, flags='0', is_sampled=is_sampled, )
def test_get_current_context_root_sample_rate_override_not_sampled( self, mock_create_attr, ): # Root span, with custom zipkin_attrs, not sampled and sample_rate zipkin_attrs = ZipkinAttrs( trace_id=generate_random_64bit_string(), span_id=generate_random_64bit_string(), parent_span_id=generate_random_64bit_string(), flags=None, is_sampled=False, ) context = zipkin.zipkin_span( service_name='test_service', span_name='test_span', transport_handler=MockTransportHandler(), zipkin_attrs=zipkin_attrs, sample_rate=100.0, ) report_root, _ = context._get_current_context() assert mock_create_attr.call_args == mock.call( sample_rate=100.0, trace_id=zipkin_attrs.trace_id, ) # It wasn't sampled before and now it is, so this is the trace root assert report_root is True
def test_get_current_context_root_sample_rate_override_sampled( self, mock_create_attr, ): # Root span, with custom zipkin_attrs, sampled # Just return the custom zipkin_attrs. zipkin_attrs = ZipkinAttrs( trace_id=generate_random_64bit_string(), span_id=generate_random_64bit_string(), parent_span_id=generate_random_64bit_string(), flags=None, is_sampled=True, ) context = zipkin.zipkin_span( service_name='test_service', span_name='test_span', transport_handler=MockTransportHandler(), zipkin_attrs=zipkin_attrs, sample_rate=100.0, ) report_root, current_attrs = context._get_current_context() assert mock_create_attr.call_count == 0 assert current_attrs == zipkin_attrs # The override was set and was already sampled, so this is probably # not the trace root. assert report_root is False
def test_get_current_context_non_root_existing( self, mock_create_attr, ): # Non root, zipkin_attrs in context stack. # Return existing zipkin_attrs with the current one as parent zipkin_attrs = ZipkinAttrs( trace_id=generate_random_64bit_string(), span_id=generate_random_64bit_string(), parent_span_id=generate_random_64bit_string(), flags=None, is_sampled=True, ) tracer = MockTracer() context = tracer.zipkin_span( service_name='test_service', span_name='test_span', ) tracer._context_stack.push(zipkin_attrs) _, current_attrs = context._get_current_context() assert mock_create_attr.call_count == 0 assert current_attrs == ZipkinAttrs( trace_id=zipkin_attrs.trace_id, span_id=mock.ANY, parent_span_id=zipkin_attrs.span_id, flags=zipkin_attrs.flags, is_sampled=zipkin_attrs.is_sampled, )
def trace(span_name, tracer, span_id=None, service_name=None): span_id = span_id or generate_random_64bit_string() service_name = service_name or settings.ZIPKIN_SERVICE_NAME if len(span_id) > 16: logger.warning('Span id %s for %s should be max 16 chars.' % (span_id, span_name)) trace_id = (tracer.get('trace_id') or generate_random_64bit_string()) parent_span_id = (tracer.get('span_id') or generate_random_64bit_string()) flags = tracer.get('flags') or '' is_sampled = (True if tracer.get('is_tracing') else False) transport_handler = import_string( getattr(settings, 'ZIPKIN_TRANSPORT_HANDLER', 'django_py_zipkin.transport.zipkin_transport')) span = zipkin_span(service_name=service_name, span_name=span_name, transport_handler=transport_handler, zipkin_attrs=ZipkinAttrs(trace_id=trace_id, span_id=span_id, parent_span_id=parent_span_id, flags=flags, is_sampled=is_sampled)) with span as zipkin_context: dict_context = {} yield dict_context zipkin_context.update_binary_annotations(dict_context)
def make_new_attrs(sample_rate=1.0): return ZipkinAttrs( generate_random_64bit_string(), generate_random_64bit_string(), None, '0', sample_rate and random.random() < sample_rate or False, )
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 _make_new_attrs(sample_rate=1.0): from py_zipkin.zipkin import ZipkinAttrs # pylint: disable=E0401 from py_zipkin.util import generate_random_64bit_string # pylint: disable=E0401 return ZipkinAttrs( generate_random_64bit_string(), generate_random_64bit_string(), None, '0', sample_rate and random.random() < sample_rate or False, )
def _read_zipkin_attrs(worker_ctx): if TRACE_ID_HEADER not in worker_ctx.data: trace_id = generate_random_64bit_string() logger.info('No {} header in context, created trace ID: {}'.format(TRACE_ID_HEADER, trace_id)) else: trace_id = worker_ctx.data[TRACE_ID_HEADER] return zipkin.ZipkinAttrs(trace_id=trace_id, span_id=generate_random_64bit_string(), parent_span_id=worker_ctx.data.get(PARENT_SPAN_ID_HEADER), flags=worker_ctx.data.get(FLAGS_HEADER), is_sampled=worker_ctx.data.get(SAMPLED_HEADER) == '1')
def test_create_span_with_bad_kind(): with pytest.raises(ZipkinError) as e: Span( trace_id=generate_random_64bit_string(), name="test span", parent_id=generate_random_64bit_string(), span_id=generate_random_64bit_string(), kind="client", timestamp=26.0, duration=4.0, ) assert "Invalid kind value client. Must be of type Kind." in str(e.value)
def generate_list_of_spans(encoding): 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() transport_handler = MockTransportHandler() # 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]) with zipkin.zipkin_span( service_name='test_service_name', span_name='test_span_name', transport_handler=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', ) return transport_handler.get_payloads()[0], zipkin_attrs, inner_span_id, ts
def test_create_span_with_bad_remote_endpoint(): with pytest.raises(ZipkinError) as e: Span( trace_id=generate_random_64bit_string(), name='test span', parent_id=generate_random_64bit_string(), span_id=generate_random_64bit_string(), kind=Kind.CLIENT, timestamp=26.0, duration=4.0, remote_endpoint='my_service', ) assert 'Invalid remote_endpoint value. Must be of type Endpoint.' in str(e)
def test__convert_unsigned_long_to_lower_hex(self): decoder = _V1ThriftDecoder() span_id = generate_random_64bit_string() span = thrift.create_span( span_id, None, generate_random_64bit_string(), 'test_span', [], [], None, None, ) assert decoder._convert_unsigned_long_to_lower_hex(span.id) == span_id
def test_v1_span(self, kind, annotations): endpoint = create_endpoint(port=8080, service_name="foo", host="80") span = Span( trace_id=generate_random_64bit_string(), name="test span", parent_id=generate_random_64bit_string(), span_id=generate_random_64bit_string(), kind=kind, timestamp=26.0, duration=4.0, local_endpoint=endpoint, ) v1_span = span.build_v1_span() assert v1_span.annotations == annotations
def test_create_span_with_bad_local_endpoint(): with pytest.raises(ZipkinError) as e: Span( trace_id=generate_random_64bit_string(), name="test span", parent_id=generate_random_64bit_string(), span_id=generate_random_64bit_string(), kind=Kind.CLIENT, timestamp=26.0, duration=4.0, local_endpoint="my_service", ) assert "Invalid local_endpoint value. Must be of type Endpoint." in str( e.value)
def construct_zipkin_attrs(data): parsed = json.loads(data) return ZipkinAttrs(trace_id=parsed.get('trace_id'), parent_span_id=parsed.get('parent_span_id'), span_id=generate_random_64bit_string(), is_sampled=parsed.get('is_sampled'), flags='0')
def add_zipkin_to_request(self, request): if not (self.enable_tracing and self.is_tracing(request)): setattr(request, 'zipkin_is_tracing', False) setattr(request, 'zipkin_trace_id', None) setattr(request, 'zipkin_span_id', None) setattr(request, 'zipkin_parent_span_id', None) setattr(request, 'zipkin_flags', None) setattr(request, 'zipkin_tracer', { 'is_tracing': request.zipkin_is_tracing, }) return span_id = request.META.get('HTTP_X_B3_SPANID', generate_random_64bit_string()) parent_span_id = request.META.get('HTTP_X_B3_PARENTSPANID', None) flags = request.META.get('HTTP_X_B3_FLAGS', '0') setattr(request, 'zipkin_is_tracing', True) setattr(request, 'zipkin_trace_id', get_trace_id(request)) setattr(request, 'zipkin_span_id', span_id) setattr(request, 'zipkin_parent_span_id', parent_span_id) setattr(request, 'zipkin_flags', flags) setattr( request, 'zipkin_tracer', { 'is_tracing': request.zipkin_is_tracing, 'trace_id': request.zipkin_trace_id, 'span_id': request.zipkin_span_id, 'parent_span_id': request.zipkin_parent_span_id, 'flags': request.zipkin_flags })
def create_zipkin_attr(request): """Create ZipkinAttrs object from a request with sampled flag as True. Attaches lazy attribute `zipkin_trace_id` with request which is then used throughout the tween. Consumes custom is_tracing function to determine if the request is traced if one is set in the pyramid registry. :param request: pyramid request object :rtype: :class:`pyramid_zipkin.request_helper.ZipkinAttrs` """ request.set_property(get_trace_id, 'zipkin_trace_id', reify=True) trace_id = request.zipkin_trace_id settings = request.registry.settings if 'zipkin.is_tracing' in settings: is_sampled = settings['zipkin.is_tracing'](request) else: is_sampled = is_tracing(request) span_id = request.headers.get('X-B3-SpanId', generate_random_64bit_string()) parent_span_id = request.headers.get('X-B3-ParentSpanId', None) flags = request.headers.get('X-B3-Flags', '0') return ZipkinAttrs( trace_id=trace_id, span_id=span_id, parent_span_id=parent_span_id, flags=flags, is_sampled=is_sampled, )
def test_generate_random_64bit_string(rand): rand.return_value = b'17133d482ba4f605' random_string = util.generate_random_64bit_string() assert random_string == '17133d482ba4f605' # This acts as a contract test of sorts. This should return a str # in both py2 and py3. IOW, no unicode objects. assert isinstance(random_string, str)
def generate_single_thrift_span(): trace_id = generate_random_128bit_string() span_id = generate_random_64bit_string() timestamp_s = round(time.time(), 3) duration_s = 2.0 host = thrift.create_endpoint(port=8000, service_name='host') host.ipv4 = 2130706433 span = thrift.create_span( span_id=span_id, parent_span_id=None, trace_id=trace_id, span_name='foo', annotations=[ thrift.create_annotation(1472470996199000, "cs", host), ], binary_annotations=[ thrift.create_binary_annotation( "key", "value", zipkin_core.AnnotationType.STRING, host, ), ], timestamp_s=timestamp_s, duration_s=duration_s, ) return thrift.span_to_bytes(span)
def enrich_with_zipkin_data(data): zipkin_attr = get_zipkin_attrs() data[0]['trace_id'] = zipkin_attr.trace_id data[0]['parent_span_id'] = zipkin_attr.span_id data[0]['span_id'] = generate_random_64bit_string() data[0]['is_sampled'] = True if zipkin_attr.is_sampled else False return data
def generate_zipkin_headers(zipkin_context): return { "X-B3-TraceId": zipkin_context.zipkin_attrs.trace_id, "X-B3-ParentSpanId": zipkin_context.zipkin_attrs.span_id, "X-B3-SpanId": generate_random_64bit_string(), "X-B3-Sampled": '1' }
def create_zipkin_attr(request): """Create ZipkinAttrs object from a request with sampled flag as True. Attaches lazy attribute `zipkin_trace_id` with request which is then used throughout the tween. Consumes custom is_tracing function to determine if the request is traced if one is set in the pyramid registry. :param request: pyramid request object :rtype: :class:`pyramid_zipkin.request_helper.ZipkinAttrs` """ request.set_property(get_trace_id, 'zipkin_trace_id', reify=True) trace_id = request.zipkin_trace_id settings = request.registry.settings if 'zipkin.is_tracing' in settings: is_sampled = settings['zipkin.is_tracing'](request) else: is_sampled = is_tracing(request) span_id = request.headers.get( 'X-B3-SpanId', generate_random_64bit_string()) parent_span_id = request.headers.get('X-B3-ParentSpanId', None) flags = request.headers.get('X-B3-Flags', '0') return ZipkinAttrs( trace_id=trace_id, span_id=span_id, parent_span_id=parent_span_id, flags=flags, is_sampled=is_sampled, )
def create_http_headers_for_new_span(context_stack=None, tracer=None): """ Generate the headers for a new zipkin span. .. note:: If the method is not called from within a zipkin_trace context, empty dict will be returned back. :returns: dict containing (X-B3-TraceId, X-B3-SpanId, X-B3-ParentSpanId, X-B3-Flags and X-B3-Sampled) keys OR an empty dict. """ if tracer: zipkin_attrs = tracer.get_zipkin_attrs() elif context_stack: zipkin_attrs = context_stack.get() else: zipkin_attrs = get_default_tracer().get_zipkin_attrs() if not zipkin_attrs: return {} return { 'X-B3-TraceId': zipkin_attrs.trace_id, 'X-B3-SpanId': generate_random_64bit_string(), 'X-B3-ParentSpanId': zipkin_attrs.span_id, 'X-B3-Flags': '0', 'X-B3-Sampled': '1' if zipkin_attrs.is_sampled else '0', }
def make_child_attrs(attrs): return ZipkinAttrs( attrs.trace_id, generate_random_64bit_string(), attrs.span_id, attrs.flags, attrs.is_sampled, )
def start_workunit(self, workunit): """Implementation of Reporter callback.""" if workunit.has_label(WorkUnitLabel.GOAL): service_name = "pants goal" elif workunit.has_label(WorkUnitLabel.TASK): service_name = "pants task" else: service_name = "pants workunit" # Check if it is the first workunit first_span = not self._workunits_to_spans if first_span: # If trace_id and parent_id are given as flags create zipkin_attrs if self.trace_id is not None and self.parent_id is not None: zipkin_attrs = ZipkinAttrs( # trace_id and parent_id are passed to Pants by another process that collects # Zipkin trace trace_id=self.trace_id, span_id=generate_random_64bit_string(), parent_span_id=self.parent_id, flags='0', # flags: stores flags header. Currently unused is_sampled=True, ) else: zipkin_attrs = create_attrs_for_span( # trace_id is the same as run_uuid that is created in run_tracker and is the part of # pants_run id trace_id=self.trace_id, sample_rate=self. sample_rate, # Value between 0.0 and 100.0 ) self.trace_id = zipkin_attrs.trace_id # TODO delete this line when parent_id will be passed in v2 engine: # - with ExecutionRequest when Nodes from v2 engine are called by a workunit; # - when a v2 engine Node is called by another v2 engine Node. self.parent_id = zipkin_attrs.span_id span = zipkin_span( service_name=service_name, span_name=workunit.name, transport_handler=self.handler, encoding=Encoding.V1_THRIFT, zipkin_attrs=zipkin_attrs, span_storage=self.span_storage, ) else: span = zipkin_span( service_name=service_name, span_name=workunit.name, span_storage=self.span_storage, ) self._workunits_to_spans[workunit] = span span.start() # Goals and tasks save their start time at the beginning of their run. # This start time is passed to workunit, because the workunit may be created much later. span.start_timestamp = workunit.start_time if first_span and span.zipkin_attrs.is_sampled: span.logging_context.start_timestamp = workunit.start_time
def start_workunit(self, workunit): """Implementation of Reporter callback.""" if workunit.has_label(WorkUnitLabel.GOAL): service_name = "pants goal" elif workunit.has_label(WorkUnitLabel.TASK): service_name = "pants task" else: service_name = "pants workunit" # Check if it is the first workunit first_span = not self._workunits_to_spans if first_span: # If trace_id and parent_id are given as flags create zipkin_attrs if self.trace_id is not None and self.parent_id is not None: zipkin_attrs = ZipkinAttrs( # trace_id and parent_id are passed to Pants by another process that collects # Zipkin trace trace_id=self.trace_id, span_id=generate_random_64bit_string(), parent_span_id=self.parent_id, flags='0', # flags: stores flags header. Currently unused is_sampled=True, ) else: zipkin_attrs = create_attrs_for_span( # trace_id is the same as run_uuid that is created in run_tracker and is the part of # pants_run id trace_id=self.trace_id, sample_rate=self.sample_rate, # Value between 0.0 and 100.0 ) self.trace_id = zipkin_attrs.trace_id # TODO delete this line when parent_id will be passed in v2 engine: # - with ExecutionRequest when Nodes from v2 engine are called by a workunit; # - when a v2 engine Node is called by another v2 engine Node. self.parent_id = zipkin_attrs.span_id span = zipkin_span( service_name=service_name, span_name=workunit.name, transport_handler=self.handler, encoding=Encoding.V1_THRIFT, zipkin_attrs=zipkin_attrs, span_storage=self.span_storage, ) else: span = zipkin_span( service_name=service_name, span_name=workunit.name, span_storage=self.span_storage, ) self._workunits_to_spans[workunit] = span span.start() # Goals and tasks save their start time at the beginning of their run. # This start time is passed to workunit, because the workunit may be created much later. span.start_timestamp = workunit.start_time if first_span and span.zipkin_attrs.is_sampled: span.logging_context.start_timestamp = workunit.start_time
def extract_zipkin_attrs(headers): logger.debug(f"headers:{headers}") return ZipkinAttrs( headers['X-B3-TraceId'], generate_random_64bit_string(), headers['X-B3-SpanId'], headers.get('X-B3-Flags', ''), headers['X-B3-Sampled'], )
def _read_zipkin_attrs(worker_ctx): if TRACE_ID_HEADER not in worker_ctx.data: return None return zipkin.ZipkinAttrs( trace_id=worker_ctx.data[TRACE_ID_HEADER], span_id=generate_random_64bit_string(), parent_span_id=worker_ctx.data[PARENT_SPAN_ID_HEADER], flags=worker_ctx.data[FLAGS_HEADER], is_sampled=worker_ctx.data[SAMPLED_HEADER] == '1')
def _make_child_attrs(attrs): from py_zipkin.zipkin import ZipkinAttrs # pylint: disable=E0401 from py_zipkin.util import generate_random_64bit_string # pylint: disable=E0401 return ZipkinAttrs( attrs.trace_id, generate_random_64bit_string(), attrs.span_id, attrs.flags, attrs.is_sampled, )
def __get_span_attrs(self, use_128bit_trace_id=False): parent_span_id = self.__get_parent_span_id() trace_id = self.__get_trace_id() if trace_id is None: if use_128bit_trace_id: trace_id = generate_random_128bit_string() else: trace_id = generate_random_64bit_string() is_sampled = self.__is_sampled() span_id = generate_random_64bit_string() return ZipkinAttrs( trace_id=trace_id, span_id=span_id, parent_span_id=parent_span_id, flags=self.__get_flags(), is_sampled=is_sampled, )
def get_trace_id(request): """Gets the trace id based on a request. If not present with the request, create a custom (depending on config: `zipkin.trace_id_generator`) or a completely random trace id. :param: current active pyramid request :returns: a 64-bit hex string """ if 'X-B3-TraceId' in request.headers: trace_id = request.headers['X-B3-TraceId'] elif 'zipkin.trace_id_generator' in request.registry.settings: trace_id = request.registry.settings[ 'zipkin.trace_id_generator'](request) else: trace_id = generate_random_64bit_string() return trace_id
def get_trace_id(request): """Gets the trace id based on a request. If not present with the request, create a custom (depending on config: `zipkin.trace_id_generator`) or a completely random trace id. :param: current active pyramid request :returns: a 64-bit hex string """ if 'X-B3-TraceId' in request.headers: trace_id = _convert_signed_hex(request.headers['X-B3-TraceId']) # Tolerates 128 bit X-B3-TraceId by reading the right-most 16 hex # characters (as opposed to overflowing a U64 and starting a new trace). trace_id = trace_id[-16:] elif 'zipkin.trace_id_generator' in request.registry.settings: trace_id = _convert_signed_hex(request.registry.settings[ 'zipkin.trace_id_generator'](request)) else: trace_id = generate_random_64bit_string() return trace_id
def create_zipkin_attr(request): """Create ZipkinAttrs object from a request with sampled flag as True. Attaches lazy attribute `zipkin_trace_id` with request which is then used throughout the tween. Consumes custom is_tracing function to determine if the request is traced if one is set in the pyramid registry. :param request: pyramid request object :rtype: :class:`pyramid_zipkin.request_helper.ZipkinAttrs` """ settings = request.registry.settings if 'zipkin.is_tracing' in settings: is_sampled = settings['zipkin.is_tracing'](request) else: is_sampled = is_tracing(request) # If zipkin.always_emit_zipkin_headers is set to false, don't propagate # zipkin headers if we're not tracing. # This saves about 0.3ms since request.set_property is quite slow if is_sampled or settings.get('zipkin.always_emit_zipkin_headers', True): request.set_property(get_trace_id, 'zipkin_trace_id', reify=True) trace_id = request.zipkin_trace_id span_id = request.headers.get( 'X-B3-SpanId', generate_random_64bit_string()) parent_span_id = request.headers.get('X-B3-ParentSpanId', None) flags = request.headers.get('X-B3-Flags', '0') return ZipkinAttrs( trace_id=trace_id, span_id=span_id, parent_span_id=parent_span_id, flags=flags, is_sampled=is_sampled, ) return ZipkinAttrs('', '', '', '0', False)
def create_zipkin_attr(request): """Create ZipkinAttrs object from a request with sampled flag as True. Attaches lazy attribute `zipkin_trace_id` with request which is then used throughout the tween. :param request: pyramid request object :rtype: :class:`pyramid_zipkin.request_helper.ZipkinAttrs` """ request.set_property(get_trace_id, 'zipkin_trace_id', reify=True) trace_id = request.zipkin_trace_id is_sampled = is_tracing(request) span_id = request.headers.get( 'X-B3-SpanId', generate_random_64bit_string()) parent_span_id = request.headers.get('X-B3-ParentSpanId', None) flags = request.headers.get('X-B3-Flags', '0') return ZipkinAttrs( trace_id=trace_id, span_id=span_id, parent_span_id=parent_span_id, flags=flags, is_sampled=is_sampled, )