def test_create_zipkin_attr_runs_custom_is_tracing_if_present(dummy_request): is_tracing = mock.Mock(return_value=True) dummy_request.registry.settings = { 'zipkin.is_tracing': is_tracing, } request_helper.create_zipkin_attr(dummy_request) is_tracing.assert_called_once_with(dummy_request)
def tween(request): # Creates zipkin attributes, attaches a zipkin_trace_id attr to the # request, and pushes the attrs onto threadlocal stack. zipkin_attrs = create_zipkin_attr(request) push_zipkin_attrs(zipkin_attrs) try: # If this request isn't sampled, don't go through the work # of initializing the rest of the zipkin attributes if not zipkin_attrs.is_sampled: return handler(request) # If the request IS sampled, we create thrift objects and # enter zipkin logging context thrift_endpoint = create_endpoint(request) log_handler = ZipkinLoggerHandler(zipkin_attrs) with ZipkinLoggingContext(zipkin_attrs, thrift_endpoint, log_handler, request) as context: response = handler(request) context.response_status_code = response.status_code context.binary_annotations_dict = get_binary_annotations( request, response) return response finally: # Regardless of what happens in the request we want to pop attrs pop_zipkin_attrs()
def tween(request): # Creates zipkin_attrs and attaches a zipkin_trace_id attr to the request zipkin_attrs = create_zipkin_attr(request) if 'zipkin.transport_handler' in request.registry.settings: transport_handler = request.registry.settings[ 'zipkin.transport_handler'] else: raise ZipkinError( "`zipkin.transport_handler` is a required config property, which" " is missing. It is a callback method which takes a message as a" " param and logs it via scribe/kafka." ) service_name = request.registry.settings.get('service_name', 'unknown') span_name = '{0} {1}'.format(request.method, request.path) with zipkin_span( service_name=service_name, span_name=span_name, zipkin_attrs=zipkin_attrs, transport_handler=transport_handler, port=request.server_port, ) as zipkin_context: response = handler(request) zipkin_context.update_binary_annotations_for_root_span( get_binary_annotations(request, response), ) return response
def tween(request): zipkin_attrs = create_zipkin_attr(request) endpoint_attrs = create_endpoint(request) log_handler = ZipkinLoggerHandler(zipkin_attrs) with ZipkinLoggingContext(zipkin_attrs, endpoint_attrs, log_handler, request) as context: response = handler(request) context.response_status_code = response.status_code context.binary_annotations_dict = get_binary_annotations( request, response) return response
def test_create_zipkin_attr_emit_zipkin_headers_default_true(dummy_request): """ We must ensure zipkin.always_emit_zipkin_headers is True by default for backward compatibility. """ dummy_request.registry.settings = {'zipkin.is_tracing': lambda _: False} attr = request_helper.create_zipkin_attr(dummy_request) assert dummy_request.set_property.call_count == 1 assert attr.trace_id != '' assert attr.span_id != '' assert attr.is_sampled is False
def test_create_sampled_zipkin_attr_creates_ZipkinAttr_object(mock, request): mock.return_value = 'bla' request.zipkin_trace_id = '12' request.headers = { 'X-B3-TraceId': '12', 'X-B3-SpanId': '23', 'X-B3-ParentSpanId': '34', 'X-B3-Flags': '45', } zipkin_attr = request_helper.ZipkinAttrs( trace_id='12', span_id='23', parent_span_id='34', flags='45', is_sampled='bla') assert zipkin_attr == request_helper.create_zipkin_attr(request)
def tween(request): zipkin_attrs = create_zipkin_attr(request) # If this request isn't sampled, don't go through the work # of initializing the rest of the zipkin attributes if not zipkin_attrs.is_sampled: return handler(request) # If the request IS sampled, we create thrift objects, store # thread-local variables, etc, to enter zipkin logging context thrift_endpoint = create_endpoint(request) log_handler = ZipkinLoggerHandler(zipkin_attrs) with ZipkinLoggingContext(zipkin_attrs, thrift_endpoint, log_handler, request) as context: response = handler(request) context.response_status_code = response.status_code context.binary_annotations_dict = get_binary_annotations(request, response) return response
def tween(request): zipkin_attrs = create_zipkin_attr(request) # If this request isn't sampled, don't go through the work # of initializing the rest of the zipkin attributes if not zipkin_attrs.is_sampled: return handler(request) # If the request IS sampled, we create thrift objects, store # thread-local variables, etc, to enter zipkin logging context thrift_endpoint = create_endpoint(request) log_handler = ZipkinLoggerHandler(zipkin_attrs) with ZipkinLoggingContext(zipkin_attrs, thrift_endpoint, log_handler, request) as context: response = handler(request) context.response_status_code = response.status_code context.binary_annotations_dict = get_binary_annotations( request, response) return response
def tween(request): settings = request.registry.settings # Creates zipkin_attrs and attaches a zipkin_trace_id attr to the request if 'zipkin.create_zipkin_attr' in settings: zipkin_attrs = settings['zipkin.create_zipkin_attr'](request) else: zipkin_attrs = create_zipkin_attr(request) if 'zipkin.transport_handler' in settings: transport_handler = settings['zipkin.transport_handler'] stream_name = settings.get('zipkin.stream_name', 'zipkin') transport_handler = functools.partial(transport_handler, stream_name) else: raise ZipkinError( "`zipkin.transport_handler` is a required config property, which" " is missing. It is a callback method which takes a log stream" " and a message as params and logs the message via scribe/kafka." ) service_name = request.registry.settings.get('service_name', 'unknown') span_name = '{0} {1}'.format(request.method, request.path) with zipkin_span( service_name=service_name, span_name=span_name, zipkin_attrs=zipkin_attrs, transport_handler=transport_handler, port=request.server_port, add_logging_annotation=settings.get( 'zipkin.add_logging_annotation', False, ), ) as zipkin_context: response = handler(request) zipkin_context.update_binary_annotations_for_root_span( get_binary_annotations(request, response), ) return response
def test_create_zipkin_attr_add_headers( is_sampled, emit_headers, dummy_request ): """ We should be setting the headers and zipkin_trace_id if the request is sampled or if zipkin.always_emit_zipkin_headers is True. """ dummy_request.registry.settings = { 'zipkin.is_tracing': lambda _: is_sampled, 'zipkin.always_emit_zipkin_headers': emit_headers, } attr = request_helper.create_zipkin_attr(dummy_request) if is_sampled or emit_headers: assert dummy_request.set_property.call_count == 1 assert attr.trace_id != '' assert attr.span_id != '' else: assert dummy_request.set_property.call_count == 0 assert attr.trace_id == '' assert attr.span_id == '' assert attr.is_sampled is is_sampled
def _get_settings_from_request(request): """Extracts Zipkin attributes and configuration from request attributes. See the `zipkin_span` context in py-zipkin for more detaied information on all the settings. Here are the supported Pyramid registry settings: zipkin.create_zipkin_attr: allows the service to override the creation of Zipkin attributes. For example, if you want to deterministically calculate trace ID from some service-specific attributes. zipkin.transport_handler: how py-zipkin will log the spans it generates. zipkin.stream_name: an additional parameter to be used as the first arg to the transport_handler function. A good example is a Kafka topic. zipkin.add_logging_annotation: if true, the outermost span in this service will have an annotation set when py-zipkin begins its logging. zipkin.report_root_timestamp: if true, the outermost span in this service will set its timestamp and duration attributes. Use this only if this service is not going to have a corresponding client span. See https://github.com/Yelp/pyramid_zipkin/issues/68 zipkin.firehose_handler: [EXPERIMENTAL] this enables "firehose tracing", which will log 100% of the spans to this handler, regardless of sampling decision. This is experimental and may change or be removed at any time without warning. """ settings = request.registry.settings # Creates zipkin_attrs and attaches a zipkin_trace_id attr to the request if 'zipkin.create_zipkin_attr' in settings: zipkin_attrs = settings['zipkin.create_zipkin_attr'](request) else: zipkin_attrs = create_zipkin_attr(request) if 'zipkin.transport_handler' in settings: transport_handler = settings['zipkin.transport_handler'] stream_name = settings.get('zipkin.stream_name', 'zipkin') transport_handler = functools.partial(transport_handler, stream_name) else: raise ZipkinError( "`zipkin.transport_handler` is a required config property, which" " is missing. It is a callback method which takes a log stream" " and a message as params and logs the message via scribe/kafka." ) context_stack = _getattr_path(request, settings.get('zipkin.request_context')) if context_stack is None: context_stack = py_zipkin.stack.ThreadLocalStack() service_name = settings.get('service_name', 'unknown') span_name = '{0} {1}'.format(request.method, request.path) add_logging_annotation = settings.get( 'zipkin.add_logging_annotation', False, ) # If the incoming request doesn't have Zipkin headers, this request is # assumed to be the root span of a trace. There's also a configuration # override to allow services to write their own logic for reporting # timestamp/duration. if 'zipkin.report_root_timestamp' in settings: report_root_timestamp = settings['zipkin.report_root_timestamp'] else: report_root_timestamp = 'X-B3-TraceId' not in request.headers zipkin_host = settings.get('zipkin.host') zipkin_port = settings.get('zipkin.port', request.server_port) firehose_handler = settings.get('zipkin.firehose_handler') max_span_batch_size = settings.get('zipkin.max_span_batch_size') return _ZipkinSettings( zipkin_attrs, transport_handler, service_name, span_name, add_logging_annotation, report_root_timestamp, zipkin_host, zipkin_port, context_stack, firehose_handler, max_span_batch_size, )
def _get_settings_from_request(request): """Extracts Zipkin attributes and configuration from request attributes. See the `zipkin_span` context in py-zipkin for more detaied information on all the settings. Here are the supported Pyramid registry settings: zipkin.create_zipkin_attr: allows the service to override the creation of Zipkin attributes. For example, if you want to deterministically calculate trace ID from some service-specific attributes. zipkin.transport_handler: how py-zipkin will log the spans it generates. zipkin.stream_name: an additional parameter to be used as the first arg to the transport_handler function. A good example is a Kafka topic. zipkin.add_logging_annotation: if true, the outermost span in this service will have an annotation set when py-zipkin begins its logging. zipkin.report_root_timestamp: if true, the outermost span in this service will set its timestamp and duration attributes. Use this only if this service is not going to have a corresponding client span. See https://github.com/Yelp/pyramid_zipkin/issues/68 zipkin.firehose_handler: [EXPERIMENTAL] this enables "firehose tracing", which will log 100% of the spans to this handler, regardless of sampling decision. This is experimental and may change or be removed at any time without warning. zipkin.use_pattern_as_span_name: if true, we'll use the pyramid route pattern as span name. If false (default) we'll keep using the raw url path. """ settings = request.registry.settings # Creates zipkin_attrs and attaches a zipkin_trace_id attr to the request if 'zipkin.create_zipkin_attr' in settings: zipkin_attrs = settings['zipkin.create_zipkin_attr'](request) else: zipkin_attrs = create_zipkin_attr(request) if 'zipkin.transport_handler' in settings: transport_handler = settings['zipkin.transport_handler'] if not isinstance(transport_handler, BaseTransportHandler): warnings.warn( 'Using a function as transport_handler is deprecated. ' 'Please extend py_zipkin.transport.BaseTransportHandler', DeprecationWarning, ) stream_name = settings.get('zipkin.stream_name', 'zipkin') transport_handler = functools.partial(transport_handler, stream_name) else: raise ZipkinError( "`zipkin.transport_handler` is a required config property, which" " is missing. Have a look at py_zipkin's docs for how to implement" " it: https://github.com/Yelp/py_zipkin#transport") context_stack = _getattr_path(request, settings.get('zipkin.request_context')) service_name = settings.get('service_name', 'unknown') span_name = '{0} {1}'.format(request.method, request.path) add_logging_annotation = settings.get( 'zipkin.add_logging_annotation', False, ) # If the incoming request doesn't have Zipkin headers, this request is # assumed to be the root span of a trace. There's also a configuration # override to allow services to write their own logic for reporting # timestamp/duration. if 'zipkin.report_root_timestamp' in settings: report_root_timestamp = settings['zipkin.report_root_timestamp'] else: report_root_timestamp = 'X-B3-TraceId' not in request.headers zipkin_host = settings.get('zipkin.host') zipkin_port = settings.get('zipkin.port', request.server_port) firehose_handler = settings.get('zipkin.firehose_handler') post_handler_hook = settings.get('zipkin.post_handler_hook') max_span_batch_size = settings.get('zipkin.max_span_batch_size') use_pattern_as_span_name = bool( settings.get('zipkin.use_pattern_as_span_name', False), ) encoding = settings.get('zipkin.encoding', Encoding.V1_THRIFT) return _ZipkinSettings( zipkin_attrs, transport_handler, service_name, span_name, add_logging_annotation, report_root_timestamp, zipkin_host, zipkin_port, context_stack, firehose_handler, post_handler_hook, max_span_batch_size, use_pattern_as_span_name, encoding=encoding, )
def _get_settings_from_request(request): """Extracts Zipkin attributes and configuration from request attributes. See the `zipkin_span` context in py-zipkin for more detaied information on all the settings. Here are the supported Pyramid registry settings: zipkin.create_zipkin_attr: allows the service to override the creation of Zipkin attributes. For example, if you want to deterministically calculate trace ID from some service-specific attributes. zipkin.transport_handler: how py-zipkin will log the spans it generates. zipkin.stream_name: an additional parameter to be used as the first arg to the transport_handler function. A good example is a Kafka topic. zipkin.add_logging_annotation: if true, the outermost span in this service will have an annotation set when py-zipkin begins its logging. zipkin.report_root_timestamp: if true, the outermost span in this service will set its timestamp and duration attributes. Use this only if this service is not going to have a corresponding client span. See https://github.com/Yelp/pyramid_zipkin/issues/68 zipkin.firehose_handler: [EXPERIMENTAL] this enables "firehose tracing", which will log 100% of the spans to this handler, regardless of sampling decision. This is experimental and may change or be removed at any time without warning. """ settings = request.registry.settings # Creates zipkin_attrs and attaches a zipkin_trace_id attr to the request if 'zipkin.create_zipkin_attr' in settings: zipkin_attrs = settings['zipkin.create_zipkin_attr'](request) else: zipkin_attrs = create_zipkin_attr(request) if 'zipkin.transport_handler' in settings: transport_handler = settings['zipkin.transport_handler'] stream_name = settings.get('zipkin.stream_name', 'zipkin') transport_handler = functools.partial(transport_handler, stream_name) else: raise ZipkinError( "`zipkin.transport_handler` is a required config property, which" " is missing. It is a callback method which takes a log stream" " and a message as params and logs the message via scribe/kafka.") context_stack = _getattr_path(request, settings.get('zipkin.request_context')) if context_stack is None: context_stack = py_zipkin.stack.ThreadLocalStack() service_name = settings.get('service_name', 'unknown') span_name = '{0} {1}'.format(request.method, request.path) add_logging_annotation = settings.get( 'zipkin.add_logging_annotation', False, ) # If the incoming request doesn't have Zipkin headers, this request is # assumed to be the root span of a trace. There's also a configuration # override to allow services to write their own logic for reporting # timestamp/duration. if 'zipkin.report_root_timestamp' in settings: report_root_timestamp = settings['zipkin.report_root_timestamp'] else: report_root_timestamp = 'X-B3-TraceId' not in request.headers zipkin_host = settings.get('zipkin.host') zipkin_port = settings.get('zipkin.port', request.server_port) firehose_handler = settings.get('zipkin.firehose_handler') max_span_batch_size = settings.get('zipkin.max_span_batch_size') return _ZipkinSettings( zipkin_attrs, transport_handler, service_name, span_name, add_logging_annotation, report_root_timestamp, zipkin_host, zipkin_port, context_stack, firehose_handler, max_span_batch_size, )