def setup_once(): # type: () -> None try: SanicIntegration.version = tuple(map(int, SANIC_VERSION.split("."))) except (TypeError, ValueError): raise DidNotEnable("Unparsable Sanic version: {}".format(SANIC_VERSION)) if SanicIntegration.version < (0, 8): raise DidNotEnable("Sanic 0.8 or newer required.") if not HAS_REAL_CONTEXTVARS: # We better have contextvars or we're going to leak state between # requests. raise DidNotEnable( "The sanic integration for Sentry requires Python 3.7+ " " or the aiocontextvars package." + CONTEXTVARS_ERROR_MESSAGE ) if SANIC_VERSION.startswith("0.8."): # Sanic 0.8 and older creates a logger named "root" and puts a # stringified version of every exception in there (without exc_info), # which our error deduplication can't detect. # # We explicitly check the version here because it is a very # invasive step to ignore this logger and not necessary in newer # versions at all. # # https://github.com/huge-success/sanic/issues/1332 ignore_logger("root") if SanicIntegration.version < (21, 9): _setup_legacy_sanic() return _setup_sanic()
def setup_once(): # type: () -> None if not HAS_REAL_CONTEXTVARS: # We better have contextvars or we're going to leak state between # requests. raise RuntimeError( "The sanic integration for Sentry requires Python 3.7+ " " or aiocontextvars package") if VERSION.startswith("0.8."): # Sanic 0.8 and older creates a logger named "root" and puts a # stringified version of every exception in there (without exc_info), # which our error deduplication can't detect. # # We explicitly check the version here because it is a very # invasive step to ignore this logger and not necessary in newer # versions at all. # # https://github.com/huge-success/sanic/issues/1332 ignore_logger("root") old_handle_request = Sanic.handle_request async def sentry_handle_request(self, request, *args, **kwargs): # type: (Any, Request, *Any, **Any) -> Any hub = Hub.current if hub.get_integration(SanicIntegration) is None: return old_handle_request(self, request, *args, **kwargs) weak_request = weakref.ref(request) with Hub(hub) as hub: with hub.configure_scope() as scope: scope.clear_breadcrumbs() scope.add_event_processor( _make_request_processor(weak_request)) response = old_handle_request(self, request, *args, **kwargs) if isawaitable(response): response = await response return response Sanic.handle_request = sentry_handle_request old_router_get = Router.get def sentry_router_get(self, request): # type: (Any, Request) -> Any rv = old_router_get(self, request) hub = Hub.current if hub.get_integration(SanicIntegration) is not None: with capture_internal_exceptions(): with hub.configure_scope() as scope: scope.transaction = rv[0].__name__ return rv Router.get = sentry_router_get old_error_handler_lookup = ErrorHandler.lookup def sentry_error_handler_lookup(self, exception): # type: (Any, Exception) -> Optional[Callable] _capture_exception(exception) old_error_handler = old_error_handler_lookup(self, exception) if old_error_handler is None: return None if Hub.current.get_integration(SanicIntegration) is None: return old_error_handler async def sentry_wrapped_error_handler(request, exception): # type: (Request, Exception) -> Any try: response = old_error_handler(request, exception) if isawaitable(response): response = await response return response except Exception: # Report errors that occur in Sanic error handler. These # exceptions will not even show up in Sanic's # `sanic.exceptions` logger. exc_info = sys.exc_info() _capture_exception(exc_info) reraise(*exc_info) return sentry_wrapped_error_handler ErrorHandler.lookup = sentry_error_handler_lookup
def setup_once(): # type: () -> None try: version = tuple(map(int, SANIC_VERSION.split("."))) except (TypeError, ValueError): raise DidNotEnable( "Unparsable Sanic version: {}".format(SANIC_VERSION)) if version < (0, 8): raise DidNotEnable("Sanic 0.8 or newer required.") if not HAS_REAL_CONTEXTVARS: # We better have contextvars or we're going to leak state between # requests. raise DidNotEnable( "The sanic integration for Sentry requires Python 3.7+ " " or the aiocontextvars package." + CONTEXTVARS_ERROR_MESSAGE) if SANIC_VERSION.startswith("0.8."): # Sanic 0.8 and older creates a logger named "root" and puts a # stringified version of every exception in there (without exc_info), # which our error deduplication can't detect. # # We explicitly check the version here because it is a very # invasive step to ignore this logger and not necessary in newer # versions at all. # # https://github.com/huge-success/sanic/issues/1332 ignore_logger("root") old_handle_request = Sanic.handle_request async def sentry_handle_request(self, request, *args, **kwargs): # type: (Any, Request, *Any, **Any) -> Any hub = Hub.current if hub.get_integration(SanicIntegration) is None: return old_handle_request(self, request, *args, **kwargs) weak_request = weakref.ref(request) with Hub(hub) as hub: with hub.configure_scope() as scope: scope.clear_breadcrumbs() scope.add_event_processor( _make_request_processor(weak_request)) response = old_handle_request(self, request, *args, **kwargs) if isawaitable(response): response = await response return response Sanic.handle_request = sentry_handle_request old_router_get = Router.get def sentry_router_get(self, *args): # type: (Any, Union[Any, Request]) -> Any rv = old_router_get(self, *args) hub = Hub.current if hub.get_integration(SanicIntegration) is not None: with capture_internal_exceptions(): with hub.configure_scope() as scope: if version >= (21, 3): # Sanic versions above and including 21.3 append the app name to the # route name, and so we need to remove it from Route name so the # transaction name is consistent across all versions sanic_app_name = self.ctx.app.name sanic_route = rv[0].name if sanic_route.startswith("%s." % sanic_app_name): # We add a 1 to the len of the sanic_app_name because there is a dot # that joins app name and the route name # Format: app_name.route_name sanic_route = sanic_route[len(sanic_app_name) + 1:] scope.transaction = sanic_route else: scope.transaction = rv[0].__name__ return rv Router.get = sentry_router_get old_error_handler_lookup = ErrorHandler.lookup def sentry_error_handler_lookup(self, exception): # type: (Any, Exception) -> Optional[object] _capture_exception(exception) old_error_handler = old_error_handler_lookup(self, exception) if old_error_handler is None: return None if Hub.current.get_integration(SanicIntegration) is None: return old_error_handler async def sentry_wrapped_error_handler(request, exception): # type: (Request, Exception) -> Any try: response = old_error_handler(request, exception) if isawaitable(response): response = await response return response except Exception: # Report errors that occur in Sanic error handler. These # exceptions will not even show up in Sanic's # `sanic.exceptions` logger. exc_info = sys.exc_info() _capture_exception(exc_info) reraise(*exc_info) return sentry_wrapped_error_handler ErrorHandler.lookup = sentry_error_handler_lookup