def process_view(self, request: Request, view_func, view_args, view_kwargs) -> Response: if not hasattr(request, "_metric_tags"): request._metric_tags = {} if request.method not in self.allowed_methods: return view = view_func if not inspect.isfunction(view_func): view = view.__class__ try: path = f"{view.__module__}.{view.__name__}" except AttributeError: return if not path.startswith(self.allowed_paths): return request._view_path = path request._start_time = time.time()
def dispatch(self, request: Request, *args, **kwargs) -> Response: """ Identical to rest framework's dispatch except we add the ability to convert arguments (for common URL params). """ with sentry_sdk.start_span(op="base.dispatch.setup", description=type(self).__name__): self.args = args self.kwargs = kwargs request = self.initialize_request(request, *args, **kwargs) self.load_json_body(request) self.request = request self.headers = self.default_response_headers # deprecate? # Tags that will ultimately flow into the metrics backend at the end of # the request (happens via middleware/stats.py). request._metric_tags = {} start_time = time.time() origin = request.META.get("HTTP_ORIGIN", "null") # A "null" value should be treated as no Origin for us. # See RFC6454 for more information on this behavior. if origin == "null": origin = None try: with sentry_sdk.start_span(op="base.dispatch.request", description=type(self).__name__): if origin: if request.auth: allowed_origins = request.auth.get_allowed_origins() else: allowed_origins = None if not is_valid_origin(origin, allowed=allowed_origins): response = Response(f"Invalid origin: {origin}", status=400) self.response = self.finalize_response(request, response, *args, **kwargs) return self.response self.initial(request, *args, **kwargs) # Get the appropriate handler method if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) (args, kwargs) = self.convert_args(request, *args, **kwargs) self.args = args self.kwargs = kwargs else: handler = self.http_method_not_allowed if getattr(request, "access", None) is None: # setup default access request.access = access.from_request(request) with sentry_sdk.start_span( op="base.dispatch.execute", description=f"{type(self).__name__}.{handler.__name__}", ): response = handler(request, *args, **kwargs) except Exception as exc: response = self.handle_exception(request, exc) if origin: self.add_cors_headers(request, response) self.response = self.finalize_response(request, response, *args, **kwargs) if settings.SENTRY_API_RESPONSE_DELAY: duration = time.time() - start_time if duration < (settings.SENTRY_API_RESPONSE_DELAY / 1000.0): with sentry_sdk.start_span( op="base.dispatch.sleep", description=type(self).__name__, ) as span: span.set_data("SENTRY_API_RESPONSE_DELAY", settings.SENTRY_API_RESPONSE_DELAY) time.sleep(settings.SENTRY_API_RESPONSE_DELAY / 1000.0 - duration) return self.response