def __init__(self, *args, **kwargs): otel_opts = kwargs.pop("_otel_opts", {}) # inject trace middleware middlewares = kwargs.pop("middleware", []) tracer_provider = otel_opts.pop("tracer_provider", None) if not isinstance(middlewares, (list, tuple)): middlewares = [middlewares] self._otel_tracer = trace.get_tracer( __name__, __version__, tracer_provider ) trace_middleware = _TraceMiddleware( self._otel_tracer, otel_opts.pop( "traced_request_attributes", get_traced_request_attrs("FALCON") ), otel_opts.pop("request_hook", None), otel_opts.pop("response_hook", None), ) middlewares.insert(0, trace_middleware) kwargs["middleware"] = middlewares self._otel_excluded_urls = get_excluded_urls("FALCON") super().__init__(*args, **kwargs)
def setUp(self): TornadoInstrumentor().instrument( server_request_hook=getattr(self, "server_request_hook", None), client_request_hook=getattr(self, "client_request_hook", None), client_response_hook=getattr(self, "client_response_hook", None), ) super().setUp() # pylint: disable=protected-access self.env_patch = patch.dict( "os.environ", { "OTEL_PYTHON_TORNADO_EXCLUDED_URLS": "healthz,ping", "OTEL_PYTHON_TORNADO_TRACED_REQUEST_ATTRS": "uri,full_url,query", }, ) self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.tornado._excluded_urls", get_excluded_urls("TORNADO"), ) self.traced_patch = patch( "opentelemetry.instrumentation.tornado._traced_request_attrs", get_traced_request_attrs("TORNADO"), ) self.exclude_patch.start() self.traced_patch.start()
def setUp(self): super().setUp() FalconInstrumentor().instrument( request_hook=getattr(self, "request_hook", None), response_hook=getattr(self, "response_hook", None), ) self.app = make_app() # pylint: disable=protected-access self.env_patch = patch.dict( "os.environ", { "OTEL_PYTHON_FALCON_EXCLUDED_URLS": "ping", "OTEL_PYTHON_FALCON_TRACED_REQUEST_ATTRS": "query_string", }, ) self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.falcon._excluded_urls", get_excluded_urls("FALCON"), ) middleware = self.app._middleware[0][ # pylint:disable=W0212 0 ].__self__ self.traced_patch = patch.object( middleware, "_traced_request_attrs", get_traced_request_attrs("FALCON"), ) self.exclude_patch.start() self.traced_patch.start()
def setUp(self): super().setUp() setup_test_environment() _django_instrumentor.instrument() self.env_patch = patch.dict( "os.environ", { "OTEL_PYTHON_DJANGO_EXCLUDED_URLS": "http://testserver/excluded_arg/123,excluded_noarg", "OTEL_PYTHON_DJANGO_TRACED_REQUEST_ATTRS": "path_info,content_type,non_existing_variable", }, ) self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.django.middleware._DjangoMiddleware._excluded_urls", get_excluded_urls("DJANGO"), ) self.traced_patch = patch( "opentelemetry.instrumentation.django.middleware._DjangoMiddleware._traced_request_attrs", get_traced_request_attrs("DJANGO"), ) self.exclude_patch.start() self.traced_patch.start()
) from opentelemetry.propagate import extract from opentelemetry.trace.status import Status from opentelemetry.util._time import _time_ns from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs _logger = getLogger(__name__) _ENVIRON_STARTTIME_KEY = "opentelemetry-falcon.starttime_key" _ENVIRON_SPAN_KEY = "opentelemetry-falcon.span_key" _ENVIRON_ACTIVATION_KEY = "opentelemetry-falcon.activation_key" _ENVIRON_TOKEN = "opentelemetry-falcon.token" _ENVIRON_EXC = "opentelemetry-falcon.exc" _excluded_urls = get_excluded_urls("FALCON") _traced_request_attrs = get_traced_request_attrs("FALCON") _response_propagation_setter = FuncSetter(falcon.api.Response.append_header) class FalconInstrumentor(BaseInstrumentor): # pylint: disable=protected-access,attribute-defined-outside-init """An instrumentor for falcon.API See `BaseInstrumentor` """ def _instrument(self, **kwargs): self._original_falcon_api = falcon.API falcon.API = partial(_InstrumentedFalconAPI, **kwargs) def _uninstrument(self, **kwargs): falcon.API = self._original_falcon_api
class _DjangoMiddleware(MiddlewareMixin): """Django Middleware for OpenTelemetry""" _environ_activation_key = ( "opentelemetry-instrumentor-django.activation_key") _environ_token = "opentelemetry-instrumentor-django.token" _environ_span_key = "opentelemetry-instrumentor-django.span_key" _environ_exception_key = "opentelemetry-instrumentor-django.exception_key" _traced_request_attrs = get_traced_request_attrs("DJANGO") _excluded_urls = get_excluded_urls("DJANGO") @staticmethod def _get_span_name(request): try: if getattr(request, "resolver_match"): match = request.resolver_match else: match = resolve(request.path) if hasattr(match, "route"): return match.route # Instead of using `view_name`, better to use `_func_name` as some applications can use similar # view names in different modules if hasattr(match, "_func_name"): return match._func_name # pylint: disable=protected-access # Fallback for safety as `_func_name` private field return match.view_name except Resolver404: return "HTTP {}".format(request.method) 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(carrier_getter, request_meta)) 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 = 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 # pylint: disable=unused-argument def process_view(self, request, view_func, *args, **kwargs): # Process view is executed before the view function, here we get the # route template from request.resolver_match. It is not set yet in process_request if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): return if (self._environ_activation_key in request.META.keys() and self._environ_span_key in request.META.keys()): span = request.META[self._environ_span_key] if span.is_recording(): match = getattr(request, "resolver_match") if match: route = getattr(match, "route") if route: span.set_attribute("http.route", route) def process_exception(self, request, exception): if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): return if self._environ_activation_key in request.META.keys(): request.META[self._environ_exception_key] = exception def process_response(self, request, response): if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): return response if (self._environ_activation_key in request.META.keys() and self._environ_span_key in request.META.keys()): add_response_attributes( request.META[self._environ_span_key], "{} {}".format(response.status_code, response.reason_phrase), response, ) request.META.pop(self._environ_span_key) exception = request.META.pop(self._environ_exception_key, None) if exception: request.META[self._environ_activation_key].__exit__( type(exception), exception, getattr(exception, "__traceback__", None), ) else: request.META[self._environ_activation_key].__exit__( None, None, None) request.META.pop(self._environ_activation_key) if self._environ_token in request.META.keys(): detach(request.environ.get(self._environ_token)) request.META.pop(self._environ_token) return response
) from opentelemetry.propagate import extract from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace.status import Status, StatusCode from opentelemetry.util._time import _time_ns from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs from .client import fetch_async # pylint: disable=E0401 _logger = getLogger(__name__) _TraceContext = namedtuple("TraceContext", ["activation", "span", "token"]) _HANDLER_CONTEXT_KEY = "_otel_trace_context_key" _OTEL_PATCHED_KEY = "_otel_patched_key" _excluded_urls = get_excluded_urls("TORNADO") _traced_request_attrs = get_traced_request_attrs("TORNADO") response_propagation_setter = FuncSetter(tornado.web.RequestHandler.add_header) class TornadoInstrumentor(BaseInstrumentor): patched_handlers = [] original_handler_new = None def instrumentation_dependencies(self) -> Collection[str]: return _instruments def _instrument(self, **kwargs): """ _instrument patches tornado.web.RequestHandler and tornado.httpclient.AsyncHTTPClient classes to automatically instrument requests both received and sent by Tornado.
class _DjangoMiddleware(MiddlewareMixin): """Django Middleware for OpenTelemetry""" _environ_activation_key = ( "opentelemetry-instrumentor-django.activation_key" ) _environ_token = "opentelemetry-instrumentor-django.token" _environ_span_key = "opentelemetry-instrumentor-django.span_key" _environ_exception_key = "opentelemetry-instrumentor-django.exception_key" _traced_request_attrs = get_traced_request_attrs("DJANGO") _excluded_urls = get_excluded_urls("DJANGO") _tracer = None _otel_request_hook: Callable[[Span, HttpRequest], None] = None _otel_response_hook: Callable[ [Span, HttpRequest, HttpResponse], None ] = None @staticmethod def _get_span_name(request): try: if getattr(request, "resolver_match"): match = request.resolver_match else: match = resolve(request.path) if hasattr(match, "route"): return match.route # Instead of using `view_name`, better to use `_func_name` as some applications can use similar # view names in different modules if hasattr(match, "_func_name"): return match._func_name # pylint: disable=protected-access # Fallback for safety as `_func_name` private field return match.view_name except Resolver404: return f"HTTP {request.method}" 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 is_asgi_request = _is_asgi_request(request) if not _is_asgi_supported and is_asgi_request: return # pylint:disable=W0212 request._otel_start_time = time() request_meta = request.META if is_asgi_request: carrier = request.scope carrier_getter = asgi_getter collect_request_attributes = asgi_collect_request_attributes else: carrier = request_meta carrier_getter = wsgi_getter collect_request_attributes = wsgi_collect_request_attributes token = context = None span_kind = SpanKind.INTERNAL if get_current_span() is INVALID_SPAN: context = extract(carrier, getter=carrier_getter) token = attach(context) span_kind = SpanKind.SERVER span = self._tracer.start_span( self._get_span_name(request), context, kind=span_kind, start_time=request_meta.get( "opentelemetry-instrumentor-django.starttime_key" ), ) attributes = collect_request_attributes(carrier) if span.is_recording(): attributes = extract_attributes_from_object( request, self._traced_request_attrs, attributes ) if is_asgi_request: # ASGI requests include extra attributes in request.scope.headers. attributes = extract_attributes_from_object( types.SimpleNamespace( **{ name.decode("latin1"): value.decode("latin1") for name, value in request.scope.get("headers", []) } ), 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 if token: request.META[self._environ_token] = token if _DjangoMiddleware._otel_request_hook: _DjangoMiddleware._otel_request_hook( # pylint: disable=not-callable span, request ) # pylint: disable=unused-argument def process_view(self, request, view_func, *args, **kwargs): # Process view is executed before the view function, here we get the # route template from request.resolver_match. It is not set yet in process_request if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): return if ( self._environ_activation_key in request.META.keys() and self._environ_span_key in request.META.keys() ): span = request.META[self._environ_span_key] if span.is_recording(): match = getattr(request, "resolver_match", None) if match: route = getattr(match, "route", None) if route: span.set_attribute(SpanAttributes.HTTP_ROUTE, route) def process_exception(self, request, exception): if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): return if self._environ_activation_key in request.META.keys(): request.META[self._environ_exception_key] = exception def process_response(self, request, response): if self._excluded_urls.url_disabled(request.build_absolute_uri("?")): return response is_asgi_request = _is_asgi_request(request) if not _is_asgi_supported and is_asgi_request: return response activation = request.META.pop(self._environ_activation_key, None) span = request.META.pop(self._environ_span_key, None) if activation and span: if is_asgi_request: set_status_code(span, response.status_code) else: add_response_attributes( span, f"{response.status_code} {response.reason_phrase}", response, ) propagator = get_global_response_propagator() if propagator: propagator.inject(response) # record any exceptions raised while processing the request exception = request.META.pop(self._environ_exception_key, None) if _DjangoMiddleware._otel_response_hook: _DjangoMiddleware._otel_response_hook( # pylint: disable=not-callable span, request, response ) if exception: activation.__exit__( type(exception), exception, getattr(exception, "__traceback__", None), ) else: activation.__exit__(None, None, None) if request.META.get(self._environ_token, None) is not None: detach(request.META.get(self._environ_token)) request.META.pop(self._environ_token) return response