Module app.errors
View Source
import bugsnag
from aiohttp.client_exceptions import ClientPayloadError
from sanic.exceptions import MethodNotSupported, NotFound
from sanic.handlers import ErrorHandler
from . import settings
IGNORED_EXCEPTIONS = (NotFound, MethodNotSupported, ClientPayloadError)
bugsnag.configure(
api_key=settings.BUGSNAG_API_KEY,
project_root="/app",
release_stage=settings.RELEASE_STAGE,
)
class BugsnagErrorHandler(ErrorHandler): # pragma: no cover
def default(self, request, exception):
if self._should_report(exception):
bugsnag.notify(exception, meta_data={"request": request.url})
return super().default(request, exception)
def _should_report(self, exception) -> bool:
if not settings.BUGSNAG_API_KEY:
return False
if isinstance(exception, IGNORED_EXCEPTIONS):
return False
return True
Variables
IGNORED_EXCEPTIONS
Classes
BugsnagErrorHandler
class BugsnagErrorHandler(
)
Provide :class:sanic.app.Sanic application with a mechanism to handle
and process any and all uncaught exceptions in a way the application
developer will set fit.
This error handling framework is built into the core that can be extended by the developers to perform a wide range of tasks from recording the error stats to reporting them to an external service that can be used for realtime alerting system.
View Source
class BugsnagErrorHandler(ErrorHandler): # pragma: no cover
def default(self, request, exception):
if self._should_report(exception):
bugsnag.notify(exception, meta_data={"request": request.url})
return super().default(request, exception)
def _should_report(self, exception) -> bool:
if not settings.BUGSNAG_API_KEY:
return False
if isinstance(exception, IGNORED_EXCEPTIONS):
return False
return True
Ancestors (in MRO)
- sanic.handlers.ErrorHandler
Class variables
cached_handlers
handlers
Methods
add
def add(
self,
exception,
handler
)
Add a new exception handler to an already existing handler object.
:param exception: Type of exception that need to be handled :param handler: Reference to the method that will handle the exception
:type exception: :class:sanic.exceptions.SanicException or
:class:Exception
:type handler: function
:return: None
View Source
def add(self, exception, handler):
"""
Add a new exception handler to an already existing handler object.
:param exception: Type of exception that need to be handled
:param handler: Reference to the method that will handle the exception
:type exception: :class:`sanic.exceptions.SanicException` or
:class:`Exception`
:type handler: ``function``
:return: None
"""
self.handlers.append((exception, handler))
default
def default(
self,
request,
exception
)
Provide a default behavior for the objects of :class:ErrorHandler.
If a developer chooses to extent the :class:ErrorHandler they can
provide a custom implementation for this method to behave in a way
they see fit.
:param request: Incoming request :param exception: Exception object
:type request: :class:sanic.request.Request
:type exception: :class:sanic.exceptions.SanicException or
:class:Exception
:return:
View Source
def default(self, request, exception):
if self._should_report(exception):
bugsnag.notify(exception, meta_data={"request": request.url})
return super().default(request, exception)
log
def log(
self,
message,
level='error'
)
Deprecated, do not use.
View Source
def log(self, message, level="error"):
"""
Deprecated, do not use.
"""
lookup
def lookup(
self,
exception
)
Lookup the existing instance of :class:ErrorHandler and fetch the
registered handler for a specific type of exception.
This method leverages a dict lookup to speedup the retrieval process.
:param exception: Type of exception
:type exception: :class:sanic.exceptions.SanicException or
:class:Exception
:return: Registered function if found None otherwise
View Source
def lookup(self, exception):
"""
Lookup the existing instance of :class:`ErrorHandler` and fetch the
registered handler for a specific type of exception.
This method leverages a dict lookup to speedup the retrieval process.
:param exception: Type of exception
:type exception: :class:`sanic.exceptions.SanicException` or
:class:`Exception`
:return: Registered function if found ``None`` otherwise
"""
handler = self.cached_handlers.get(type(exception), self._missing)
if handler is self._missing:
for exception_class, handler in self.handlers:
if isinstance(exception, exception_class):
self.cached_handlers[type(exception)] = handler
return handler
self.cached_handlers[type(exception)] = None
handler = None
return handler
response
def response(
self,
request,
exception
)
Fetches and executes an exception handler and returns a response object
:param request: Instance of :class:sanic.request.Request
:param exception: Exception to handle
:type request: :class:sanic.request.Request
:type exception: :class:sanic.exceptions.SanicException or
:class:Exception
:return: Wrap the return value obtained from :func:default
or registered handler for that type of exception.
View Source
def response(self, request, exception):
"""Fetches and executes an exception handler and returns a response
object
:param request: Instance of :class:`sanic.request.Request`
:param exception: Exception to handle
:type request: :class:`sanic.request.Request`
:type exception: :class:`sanic.exceptions.SanicException` or
:class:`Exception`
:return: Wrap the return value obtained from :func:`default`
or registered handler for that type of exception.
"""
handler = self.lookup(exception)
response = None
try:
if handler:
response = handler(request, exception)
if response is None:
response = self.default(request, exception)
except Exception:
self.log(format_exc())
try:
url = repr(request.url)
except AttributeError:
url = "unknown"
response_message = (
"Exception raised in exception handler " '"%s" for uri: %s'
)
logger.exception(response_message, handler.__name__, url)
if self.debug:
return text(response_message % (handler.__name__, url), 500)
else:
return text("An error occurred while handling an error", 500)
return response