コード例 #1
0
 def test_no_whitelist(self, span, integration_config):
     """
     :type span: Span
     :type integration_config: IntegrationConfig
     """
     store_response_headers({
         'Content-Type': 'some;value',
     }, span, integration_config)
     assert span.get_tag('http.response.headers.content-type') is None
コード例 #2
0
 def test_numbers_in_headers_names_are_allowed(self, span, integration_config):
     """
     :type span: Span
     :type integration_config: IntegrationConfig
     """
     integration_config.http.trace_headers('Content-Type123')
     store_response_headers({
         'Content-Type123': 'some;value',
     }, span, integration_config)
     assert span.get_tag('http.response.headers.content-type123') == 'some;value'
コード例 #3
0
 def test_whitelist_case_insensitive(self, span, integration_config):
     """
     :type span: Span
     :type integration_config: IntegrationConfig
     """
     integration_config.http.trace_headers('CoNtEnT-tYpE')
     store_response_headers({
         'cOnTeNt-TyPe': 'some;value',
     }, span, integration_config)
     assert span.get_tag('http.response.headers.content-type') == 'some;value'
コード例 #4
0
 def test_whitelist_exact(self, span, integration_config):
     """
     :type span: Span
     :type integration_config: IntegrationConfig
     """
     integration_config.http.trace_headers('content-type')
     store_response_headers({
         'Content-Type': 'some;value',
     }, span, integration_config)
     assert span.get_tag('http.response.headers.content-type') == 'some;value'
コード例 #5
0
 def test_value_not_trim_leading_trailing_spaced(self, span, integration_config):
     """
     :type span: Span
     :type integration_config: IntegrationConfig
     """
     integration_config.http.trace_headers('Content-Type')
     store_response_headers({
         'Content-Type': '   some;value   ',
     }, span, integration_config)
     assert span.get_tag('http.response.headers.content-type') == '   some;value   '
コード例 #6
0
 def test_allowed_chars_not_replaced_in_tag_name(self, span, integration_config):
     """
     :type span: Span
     :type integration_config: IntegrationConfig
     """
     # See: https://docs.datadoghq.com/tagging/#defining-tags
     integration_config.http.trace_headers('C0n_t:e/nt-Type')
     store_response_headers({
         'C0n_t:e/nt-Type': 'some;value',
     }, span, integration_config)
     assert span.get_tag('http.response.headers.c0n_t:e/nt-type') == 'some;value'
コード例 #7
0
 def test_period_is_replaced_by_underscore(self, span, integration_config):
     """
     :type span: Span
     :type integration_config: IntegrationConfig
     """
     # Deviation from https://docs.datadoghq.com/tagging/#defining-tags in order to allow
     # consistent representation of headers having the period in the name.
     integration_config.http.trace_headers('api.token')
     store_response_headers({
         'api.token': 'some;value',
     }, span, integration_config)
     assert span.get_tag('http.response.headers.api_token') == 'some;value'
コード例 #8
0
 def test_store_multiple_response_headers_as_dict(self, span, integration_config):
     """
     :type span: Span
     :type integration_config: IntegrationConfig
     """
     integration_config.http.trace_headers(['Content-Type', 'Max-Age'])
     store_response_headers({
         'Content-Type': 'some;value;content-type',
         'Max-Age': 'some;value;max_age',
         'Other': 'some;value;other',
     }, span, integration_config)
     assert span.get_tag('http.response.headers.content-type') == 'some;value;content-type'
     assert span.get_tag('http.response.headers.max-age') == 'some;value;max_age'
     assert None is span.get_tag('http.response.headers.other')
コード例 #9
0
    def process_response(self, req, resp, resource, req_succeeded=None):
        # req_succeded is not a kwarg in the API, but we need that to support
        # Falcon 1.0 that doesn't provide this argument
        span = self.tracer.current_span()
        if not span:
            return  # unexpected

        status = httpx.normalize_status_code(resp.status)

        # Note: any response header set after this line will not be stored in the span
        store_response_headers(resp._headers, span, config.falcon)

        # FIXME[matt] falcon does not map errors or unmatched routes
        # to proper status codes, so we we have to try to infer them
        # here. See https://github.com/falconry/falcon/issues/606
        if resource is None:
            status = '404'
            span.resource = '%s 404' % req.method
            span.set_tag(httpx.STATUS_CODE, status)
            span.finish()
            return

        err_type = sys.exc_info()[0]
        if err_type is not None:
            if req_succeeded is None:
                # backward-compatibility with Falcon 1.0; any version
                # greater than 1.0 has req_succeded in [True, False]
                # TODO[manu]: drop the support at some point
                status = _detect_and_set_status_error(err_type, span)
            elif req_succeeded is False:
                # Falcon 1.1+ provides that argument that is set to False
                # if get an Exception (404 is still an exception)
                status = _detect_and_set_status_error(err_type, span)

        span.set_tag(httpx.STATUS_CODE, status)

        # Emit span hook for this response
        # DEV: Emit before closing so they can overwrite `span.resource` if they want
        config.falcon.hooks._emit('request', span, req, resp)

        # Close the span
        span.finish()
コード例 #10
0
 def test_it_does_not_break_if_headers_are_not_a_dict(self, span, integration_config):
     store_request_headers(list(), span, integration_config)
     store_response_headers(list(), span, integration_config)
コード例 #11
0
 def test_it_does_not_break_if_no_headers(self, span, integration_config):
     store_request_headers(None, span, integration_config)
     store_response_headers(None, span, integration_config)
コード例 #12
0
def _wrap_send(func, instance, args, kwargs):
    """Trace the `Session.send` instance method"""
    # TODO[manu]: we already offer a way to provide the Global Tracer
    # and is oteltrace.tracer; it's used only inside our tests and can
    # be easily changed by providing a TracingTestCase that sets common
    # tracing functionalities.
    tracer = getattr(instance, 'opentelemetry_tracer', oteltrace.tracer)

    # skip if tracing is not enabled
    if not tracer.enabled:
        return func(*args, **kwargs)

    request = kwargs.get('request') or args[0]
    if not request:
        return func(*args, **kwargs)

    # sanitize url of query
    parsed_uri = parse.urlparse(request.url)
    hostname = parsed_uri.hostname
    if parsed_uri.port:
        hostname = '{}:{}'.format(hostname, parsed_uri.port)
    sanitized_url = parse.urlunparse((
        parsed_uri.scheme,
        parsed_uri.netloc,
        parsed_uri.path,
        parsed_uri.params,
        None,  # drop parsed_uri.query
        parsed_uri.fragment))

    with tracer.trace('requests.request', span_type=http.TYPE) as span:
        # update the span service name before doing any action
        span.service = _extract_service_name(instance, span, hostname=hostname)

        # Configure trace search sample rate
        # DEV: analytics enabled on per-session basis
        cfg = config.get_from(instance)
        analytics_enabled = cfg.get('analytics_enabled')
        if analytics_enabled:
            span.set_tag(ANALYTICS_SAMPLE_RATE_KEY,
                         cfg.get('analytics_sample_rate', True))

        # propagate distributed tracing headers
        if cfg.get('distributed_tracing'):
            propagator = HTTPPropagator()
            propagator.inject(span.context, request.headers)

        # Storing request headers in the span
        store_request_headers(request.headers, span, config.requests)

        response = None
        try:
            response = func(*args, **kwargs)

            # Storing response headers in the span. Note that response.headers is not a dict, but an iterable
            # requests custom structure, that we convert to a dict
            if hasattr(response, 'headers'):
                store_response_headers(dict(response.headers), span,
                                       config.requests)
            return response
        finally:
            try:
                span.set_tag(http.METHOD, request.method.upper())
                span.set_tag(http.URL, sanitized_url)
                if config.requests.trace_query_string:
                    span.set_tag(http.QUERY_STRING, parsed_uri.query)
                if response is not None:
                    span.set_tag(http.STATUS_CODE, response.status_code)
                    # `span.error` must be an integer
                    span.error = int(500 <= response.status_code)
                    # Storing response headers in the span.
                    # Note that response.headers is not a dict, but an iterable
                    # requests custom structure, that we convert to a dict
                    response_headers = dict(getattr(response, 'headers', {}))
                    store_response_headers(response_headers, span,
                                           config.requests)
            except Exception:
                log.debug('requests: error adding tags', exc_info=True)