def test_http_user_agent_attribute(self): self.environ["HTTP_USER_AGENT"] = "test-useragent" expected = {"http.user_agent": "test-useragent"} self.assertGreaterEqual( otel_wsgi.collect_request_attributes(self.environ).items(), expected.items(), )
def _before_request(): if _excluded_urls.url_disabled(flask.request.url): return environ = flask.request.environ span_name = flask.request.endpoint or otel_wsgi.get_default_span_name( environ) token = context.attach( propagators.extract(otel_wsgi.get_header_from_environ, environ)) tracer = trace.get_tracer(__name__, __version__) attributes = otel_wsgi.collect_request_attributes(environ) if flask.request.url_rule: # For 404 that result from no route found, etc, we # don't have a url_rule. attributes["http.route"] = flask.request.url_rule.rule span = tracer.start_span( span_name, kind=trace.SpanKind.SERVER, attributes=attributes, start_time=environ.get(_ENVIRON_STARTTIME_KEY), ) activation = tracer.use_span(span, end_on_exit=True) activation.__enter__() environ[_ENVIRON_ACTIVATION_KEY] = activation environ[_ENVIRON_SPAN_KEY] = span environ[_ENVIRON_TOKEN] = token
def _before_request(): if _excluded_urls.url_disabled(flask.request.url): return flask_request_environ = flask.request.environ span_name = name_callback() token = context.attach( extract(flask_request_environ, getter=otel_wsgi.wsgi_getter)) tracer = trace.get_tracer(__name__, __version__) span = tracer.start_span( span_name, kind=trace.SpanKind.SERVER, start_time=flask_request_environ.get(_ENVIRON_STARTTIME_KEY), ) if span.is_recording(): attributes = otel_wsgi.collect_request_attributes( flask_request_environ) if flask.request.url_rule: # For 404 that result from no route found, etc, we # don't have a url_rule. attributes["http.route"] = flask.request.url_rule.rule for key, value in attributes.items(): span.set_attribute(key, value) activation = trace.use_span(span, end_on_exit=True) activation.__enter__() # pylint: disable=E1101 flask_request_environ[_ENVIRON_ACTIVATION_KEY] = activation flask_request_environ[_ENVIRON_SPAN_KEY] = span flask_request_environ[_ENVIRON_TOKEN] = token
def process_view(self, request, view_func, view_args, view_kwargs): # pylint: disable=unused-argument # request.META is a dictionary containing all available HTTP headers # Read more about request.META here: # https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest.META # environ = { # key.lower().replace('_', '-').replace("http-", "", 1): value # for key, value in request.META.items() # } if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): return environ = request.META token = attach(extract(get_header_from_environ, environ)) tracer = get_tracer(__name__, __version__) attributes = collect_request_attributes(environ) span = tracer.start_span( view_func.__name__, kind=SpanKind.SERVER, attributes=attributes, start_time=environ.get( "opentelemetry-instrumentor-django.starttime_key"), ) activation = tracer.use_span(span, end_on_exit=True) activation.__enter__() request.META[self._environ_activation_key] = activation request.META[self._environ_span_key] = span request.META[self._environ_token] = token
def test_request_attributes_pathless(self): self.environ["RAW_URI"] = "" expected = {SpanAttributes.HTTP_TARGET: ""} self.assertGreaterEqual( otel_wsgi.collect_request_attributes(self.environ).items(), expected.items(), )
def test_request_attributes_pathless(self): self.environ["RAW_URI"] = "" expected = {"http.target": ""} self.assertGreaterEqual( otel_wsgi.collect_request_attributes(self.environ).items(), expected.items(), )
def process_request(self, request): # request.META is a dictionary containing all available HTTP headers # Read more about request.META here: # https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest.META if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): return environ = request.META token = attach(extract(get_header_from_environ, environ)) tracer = get_tracer(__name__, __version__) attributes = collect_request_attributes(environ) for attr in self._traced_request_attrs: value = getattr(request, attr, None) if value is not None: attributes[attr] = str(value) span = tracer.start_span( self._get_span_name(request), kind=SpanKind.SERVER, attributes=attributes, start_time=environ.get( "opentelemetry-instrumentor-django.starttime_key"), ) activation = tracer.use_span(span, end_on_exit=True) activation.__enter__() request.META[self._environ_activation_key] = activation request.META[self._environ_span_key] = span request.META[self._environ_token] = token
def server_request(): with tracer.start_as_current_span( "server_request", context=propagators.extract(DictGetter(), request.headers), kind=trace.SpanKind.SERVER, attributes=collect_request_attributes(request.environ)): print(request.args.get("param")) return "served"
def server_request(): with tracer.start_as_current_span( "server_request", parent=propagators.extract(lambda dict_, key: dict_.get(key, []), request.headers)["current-span"], kind=trace.SpanKind.SERVER, attributes=collect_request_attributes(request.environ), ): print(request.args.get("param")) return "served"
def test_credential_removal(self): self.environ["HTTP_HOST"] = "username:[email protected]" self.environ["PATH_INFO"] = "/status/200" expected = { SpanAttributes.HTTP_URL: "http://httpbin.com/status/200", SpanAttributes.NET_HOST_PORT: 80, } self.assertGreaterEqual( otel_wsgi.collect_request_attributes(self.environ).items(), expected.items(), )
def _wrapped_app(wrapped_app_environ, start_response): # We want to measure the time for route matching, etc. # In theory, we could start the span here and use # update_name later but that API is "highly discouraged" so # we better avoid it. wrapped_app_environ[_ENVIRON_STARTTIME_KEY] = _time_ns() start = default_timer() attributes = otel_wsgi.collect_request_attributes(wrapped_app_environ) active_requests_count_attrs = ( otel_wsgi._parse_active_request_count_attrs(attributes)) duration_attrs = otel_wsgi._parse_duration_attrs(attributes) active_requests_counter.add(1, active_requests_count_attrs) def _start_response(status, response_headers, *args, **kwargs): if flask.request and ( excluded_urls is None or not excluded_urls.url_disabled(flask.request.url)): span = flask.request.environ.get(_ENVIRON_SPAN_KEY) propagator = get_global_response_propagator() if propagator: propagator.inject( response_headers, setter=otel_wsgi.default_response_propagation_setter, ) if span: otel_wsgi.add_response_attributes(span, status, response_headers) status_code = otel_wsgi._parse_status_code(status) if status_code is not None: duration_attrs[ SpanAttributes.HTTP_STATUS_CODE] = status_code if (span.is_recording() and span.kind == trace.SpanKind.SERVER): custom_attributes = otel_wsgi.collect_custom_response_headers_attributes( response_headers) if len(custom_attributes) > 0: span.set_attributes(custom_attributes) else: _logger.warning( "Flask environ's OpenTelemetry span " "missing at _start_response(%s)", status, ) if response_hook is not None: response_hook(span, status, response_headers) return start_response(status, response_headers, *args, **kwargs) result = wsgi_app(wrapped_app_environ, _start_response) duration = max(round((default_timer() - start) * 1000), 0) duration_histogram.record(duration, duration_attrs) active_requests_counter.add(-1, active_requests_count_attrs) return result
def _before_traversal(event): request = event.request request_environ = request.environ span_name = otel_wsgi.get_default_span_name(request_environ) enabled = request_environ.get(_ENVIRON_ENABLED_KEY) if enabled is None: _logger.warning( "Opentelemetry pyramid tween 'opentelemetry.instrumentation.pyramid.trace_tween_factory'" "was not called. Make sure that the tween is included in 'pyramid.tweens' if" "the tween list was created manually") return if not enabled: # Tracing not enabled, return return start_time = request_environ.get(_ENVIRON_STARTTIME_KEY) tracer = trace.get_tracer(__name__, __version__) if request.matched_route: span_name = request.matched_route.pattern else: span_name = otel_wsgi.get_default_span_name(request_environ) span, token = _start_internal_or_server_span( tracer=tracer, span_name=span_name, start_time=start_time, context_carrier=request_environ, context_getter=otel_wsgi.wsgi_getter, ) if span.is_recording(): attributes = otel_wsgi.collect_request_attributes(request_environ) if request.matched_route: attributes[ SpanAttributes.HTTP_ROUTE] = request.matched_route.pattern for key, value in attributes.items(): span.set_attribute(key, value) if span.kind == trace.SpanKind.SERVER: custom_attributes = ( otel_wsgi.collect_custom_request_headers_attributes( request_environ)) if len(custom_attributes) > 0: span.set_attributes(custom_attributes) activation = trace.use_span(span, end_on_exit=True) activation.__enter__() # pylint: disable=E1101 request_environ[_ENVIRON_ACTIVATION_KEY] = activation request_environ[_ENVIRON_SPAN_KEY] = span if token: request_environ[_ENVIRON_TOKEN] = token
def test_request_attributes_with_conflicting_nonstandard_port(self): self.environ[ "HTTP_HOST"] += ":8080" # Note that we do not correct SERVER_PORT expected = { SpanAttributes.HTTP_HOST: "127.0.0.1:8080", SpanAttributes.HTTP_URL: "http://127.0.0.1:8080/", SpanAttributes.NET_HOST_PORT: 80, } self.assertGreaterEqual( otel_wsgi.collect_request_attributes(self.environ).items(), expected.items(), )
def test_request_attributes_with_full_request_uri(self): self.environ["HTTP_HOST"] = "127.0.0.1:8080" self.environ["REQUEST_METHOD"] = "CONNECT" self.environ[ "REQUEST_URI"] = "127.0.0.1:8080" # Might happen in a CONNECT request expected = { SpanAttributes.HTTP_HOST: "127.0.0.1:8080", SpanAttributes.HTTP_TARGET: "127.0.0.1:8080", } self.assertGreaterEqual( otel_wsgi.collect_request_attributes(self.environ).items(), expected.items(), )
def __call__(self, env, start_response): # pylint: disable=E1101 if self._otel_excluded_urls.url_disabled(env.get("PATH_INFO", "/")): return super().__call__(env, start_response) start_time = _time_ns() span, token = _start_internal_or_server_span( tracer=self._otel_tracer, span_name=otel_wsgi.get_default_span_name(env), start_time=start_time, context_carrier=env, context_getter=otel_wsgi.wsgi_getter, ) if span.is_recording(): attributes = otel_wsgi.collect_request_attributes(env) for key, value in attributes.items(): span.set_attribute(key, value) if span.is_recording() and span.kind == trace.SpanKind.SERVER: custom_attributes = ( otel_wsgi.collect_custom_request_headers_attributes(env) ) if len(custom_attributes) > 0: span.set_attributes(custom_attributes) activation = trace.use_span(span, end_on_exit=True) activation.__enter__() env[_ENVIRON_SPAN_KEY] = span env[_ENVIRON_ACTIVATION_KEY] = activation def _start_response(status, response_headers, *args, **kwargs): response = start_response( status, response_headers, *args, **kwargs ) activation.__exit__(None, None, None) if token is not None: context.detach(token) return response try: return super().__call__(env, _start_response) except Exception as exc: activation.__exit__( type(exc), exc, getattr(exc, "__traceback__", None), ) if token is not None: context.detach(token) raise
def test_request_attributes(self): self.environ["QUERY_STRING"] = "foo=bar" attrs = otel_wsgi.collect_request_attributes(self.environ) self.assertDictEqual( attrs, { "http.method": "GET", "http.host": "127.0.0.1", "http.url": "http://127.0.0.1/?foo=bar", "net.host.port": 80, "http.scheme": "http", "http.server_name": "127.0.0.1", "http.flavor": "1.0", }, )
def test_request_attributes(self): self.environ["QUERY_STRING"] = "foo=bar" attrs = otel_wsgi.collect_request_attributes(self.environ) self.assertDictEqual( attrs, { SpanAttributes.HTTP_METHOD: "GET", SpanAttributes.HTTP_HOST: "127.0.0.1", SpanAttributes.HTTP_URL: "http://127.0.0.1/?foo=bar", SpanAttributes.NET_HOST_PORT: 80, SpanAttributes.HTTP_SCHEME: "http", SpanAttributes.HTTP_SERVER_NAME: "127.0.0.1", SpanAttributes.HTTP_FLAVOR: "1.0", }, )
def _before_traversal(event): request = event.request request_environ = request.environ span_name = otel_wsgi.get_default_span_name(request_environ) enabled = request_environ.get(_ENVIRON_ENABLED_KEY) if enabled is None: _logger.warning( "Opentelemetry pyramid tween 'opentelemetry.instrumentation.pyramid.trace_tween_factory'" "was not called. Make sure that the tween is included in 'pyramid.tweens' if" "the tween list was created manually") return if not enabled: # Tracing not enabled, return return start_time = request_environ.get(_ENVIRON_STARTTIME_KEY) token = context.attach( propagators.extract(otel_wsgi.carrier_getter, request_environ)) tracer = trace.get_tracer(__name__, __version__) if request.matched_route: span_name = request.matched_route.pattern else: span_name = otel_wsgi.get_default_span_name(request_environ) span = tracer.start_span( span_name, kind=trace.SpanKind.SERVER, start_time=start_time, ) if span.is_recording(): attributes = otel_wsgi.collect_request_attributes(request_environ) if request.matched_route: attributes["http.route"] = request.matched_route.pattern for key, value in attributes.items(): span.set_attribute(key, value) activation = tracer.use_span(span, end_on_exit=True) activation.__enter__() request_environ[_ENVIRON_ACTIVATION_KEY] = activation request_environ[_ENVIRON_SPAN_KEY] = span request_environ[_ENVIRON_TOKEN] = token
def process_request(self, request): # request.META is a dictionary containing all available HTTP headers # Read more about request.META here: # https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest.META if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): return # pylint:disable=W0212 request._otel_start_time = time() request_meta = request.META token = attach(extract(request_meta, getter=wsgi_getter)) tracer = get_tracer(__name__, __version__) span = tracer.start_span( self._get_span_name(request), kind=SpanKind.SERVER, start_time=request_meta.get( "opentelemetry-instrumentor-django.starttime_key" ), ) attributes = collect_request_attributes(request_meta) if span.is_recording(): attributes = extract_attributes_from_object( request, self._traced_request_attrs, attributes ) for key, value in attributes.items(): span.set_attribute(key, value) activation = use_span(span, end_on_exit=True) activation.__enter__() # pylint: disable=E1101 request.META[self._environ_activation_key] = activation request.META[self._environ_span_key] = span request.META[self._environ_token] = token if _DjangoMiddleware._otel_request_hook: _DjangoMiddleware._otel_request_hook( # pylint: disable=not-callable span, request )
def validate_url(self, expected_url, raw=False, has_host=True): parts = urlsplit(expected_url) expected = { "http.scheme": parts.scheme, "host.port": parts.port or (80 if parts.scheme == "http" else 443), "http.server_name": parts.hostname, # Not true in the general case, but for all tests. } if raw: expected["http.target"] = expected_url.split(parts.netloc, 1)[1] else: expected["http.url"] = expected_url if has_host: expected["http.host"] = parts.hostname attrs = otel_wsgi.collect_request_attributes(self.environ) self.assertGreaterEqual( attrs.items(), expected.items(), expected_url + " expected." )
def _before_request(): if excluded_urls and excluded_urls.url_disabled(flask.request.url): return flask_request_environ = flask.request.environ span_name = get_default_span_name() token = ctx = span_kind = None if trace.get_current_span() is trace.INVALID_SPAN: ctx = extract(flask_request_environ, getter=otel_wsgi.wsgi_getter) token = context.attach(ctx) span_kind = trace.SpanKind.SERVER else: ctx = context.get_current() span_kind = trace.SpanKind.INTERNAL span = tracer.start_span( span_name, ctx, kind=span_kind, start_time=flask_request_environ.get(_ENVIRON_STARTTIME_KEY), ) if request_hook: request_hook(span, flask_request_environ) if span.is_recording(): attributes = otel_wsgi.collect_request_attributes( flask_request_environ) if flask.request.url_rule: # For 404 that result from no route found, etc, we # don't have a url_rule. attributes[ SpanAttributes.HTTP_ROUTE] = flask.request.url_rule.rule for key, value in attributes.items(): span.set_attribute(key, value) activation = trace.use_span(span, end_on_exit=True) activation.__enter__() # pylint: disable=E1101 flask_request_environ[_ENVIRON_ACTIVATION_KEY] = activation flask_request_environ[_ENVIRON_SPAN_KEY] = span flask_request_environ[_ENVIRON_TOKEN] = token
def __call__(self, env, start_response): # pylint: disable=E1101 if _excluded_urls.url_disabled(env.get("PATH_INFO", "/")): return super().__call__(env, start_response) start_time = _time_ns() token = context.attach(extract(env, getter=otel_wsgi.wsgi_getter)) span = self._tracer.start_span( otel_wsgi.get_default_span_name(env), kind=trace.SpanKind.SERVER, start_time=start_time, ) if span.is_recording(): attributes = otel_wsgi.collect_request_attributes(env) for key, value in attributes.items(): span.set_attribute(key, value) activation = trace.use_span(span, end_on_exit=True) activation.__enter__() env[_ENVIRON_SPAN_KEY] = span env[_ENVIRON_ACTIVATION_KEY] = activation def _start_response(status, response_headers, *args, **kwargs): otel_wsgi.add_response_attributes(span, status, response_headers) response = start_response(status, response_headers, *args, **kwargs) activation.__exit__(None, None, None) context.detach(token) return response try: return super().__call__(env, _start_response) except Exception as exc: activation.__exit__( type(exc), exc, getattr(exc, "__traceback__", None), ) context.detach(token) raise
def validate_url(self, expected_url, raw=False, has_host=True): parts = urlsplit(expected_url) expected = { SpanAttributes.HTTP_SCHEME: parts.scheme, SpanAttributes.NET_HOST_PORT: parts.port or (80 if parts.scheme == "http" else 443), SpanAttributes.HTTP_SERVER_NAME: parts.hostname, # Not true in the general case, but for all tests. } if raw: expected[SpanAttributes.HTTP_TARGET] = expected_url.split( parts.netloc, 1 )[1] else: expected[SpanAttributes.HTTP_URL] = expected_url if has_host: expected[SpanAttributes.HTTP_HOST] = parts.hostname attrs = otel_wsgi.collect_request_attributes(self.environ) self.assertGreaterEqual( attrs.items(), expected.items(), expected_url + " expected." )
def _before_request(): if excluded_urls and excluded_urls.url_disabled(flask.request.url): return flask_request_environ = flask.request.environ span_name = get_default_span_name() span, token = _start_internal_or_server_span( tracer=tracer, span_name=span_name, start_time=flask_request_environ.get(_ENVIRON_STARTTIME_KEY), context_carrier=flask_request_environ, context_getter=otel_wsgi.wsgi_getter, ) if request_hook: request_hook(span, flask_request_environ) if span.is_recording(): attributes = otel_wsgi.collect_request_attributes( flask_request_environ) if flask.request.url_rule: # For 404 that result from no route found, etc, we # don't have a url_rule. attributes[ SpanAttributes.HTTP_ROUTE] = flask.request.url_rule.rule for key, value in attributes.items(): span.set_attribute(key, value) if span.is_recording() and span.kind == trace.SpanKind.SERVER: custom_attributes = ( otel_wsgi.collect_custom_request_headers_attributes( flask_request_environ)) if len(custom_attributes) > 0: span.set_attributes(custom_attributes) activation = trace.use_span(span, end_on_exit=True) activation.__enter__() # pylint: disable=E1101 flask_request_environ[_ENVIRON_ACTIVATION_KEY] = activation flask_request_environ[_ENVIRON_SPAN_KEY] = span flask_request_environ[_ENVIRON_TOKEN] = token
def __call__(self, env, start_response): if _excluded_urls.url_disabled(env.get("PATH_INFO", "/")): return super().__call__(env, start_response) start_time = time_ns() token = context.attach( propagators.extract(otel_wsgi.get_header_from_environ, env)) attributes = otel_wsgi.collect_request_attributes(env) span = self._tracer.start_span( otel_wsgi.get_default_span_name(env), kind=trace.SpanKind.SERVER, attributes=attributes, start_time=start_time, ) activation = self._tracer.use_span(span, end_on_exit=True) activation.__enter__() env[_ENVIRON_SPAN_KEY] = span env[_ENVIRON_ACTIVATION_KEY] = activation def _start_response(status, response_headers, *args, **kwargs): otel_wsgi.add_response_attributes(span, status, response_headers) response = start_response(status, response_headers, *args, **kwargs) activation.__exit__(None, None, None) context.detach(token) return response try: return super().__call__(env, _start_response) except Exception as exc: activation.__exit__( type(exc), exc, getattr(exc, "__traceback__", None), ) context.detach(token) raise
def _before_request(): if _excluded_urls.url_disabled(flask.request.url): return environ = flask.request.environ span_name = None try: span_name = flask.request.url_rule.rule except AttributeError: pass if span_name is None: span_name = otel_wsgi.get_default_span_name(environ) token = context.attach( propagators.extract(otel_wsgi.carrier_getter, environ) ) tracer = trace.get_tracer(__name__, __version__) span = tracer.start_span( span_name, kind=trace.SpanKind.SERVER, start_time=environ.get(_ENVIRON_STARTTIME_KEY), ) if span.is_recording(): attributes = otel_wsgi.collect_request_attributes(environ) if flask.request.url_rule: # For 404 that result from no route found, etc, we # don't have a url_rule. attributes["http.route"] = flask.request.url_rule.rule for key, value in attributes.items(): span.set_attribute(key, value) activation = tracer.use_span(span, end_on_exit=True) activation.__enter__() environ[_ENVIRON_ACTIVATION_KEY] = activation environ[_ENVIRON_SPAN_KEY] = span environ[_ENVIRON_TOKEN] = token