Всякий раз, когда возникают исключения, они регистрируются в консоли (и в Sentry, если он используется).
Многие из этих исключений предназначены только для показа пользователю. Например, django-graphql-jwt
вызывает исключение PermissionDenied
для login_required
декоратора .
Проблема в том, что это загрязняет вывод консоли во время тестирования / разработки ирегистрирует допустимые ошибки в Sentry во время производства. Для исключений, таких как приведенный выше пример, он предназначен только для показа пользователю, не зарегистрировано.
В качестве обходного пути я попытался написать промежуточное программное обеспечение, которое перехватывает любые выданные исключения:
class ExceptionFilterMiddleware:
IGNORED_EXCEPTIONS = (
# Local exceptions
ValidationException,
# Third-party exceptions
JSONWebTokenExpired,
PermissionDenied,
)
def on_error(self, error):
if not isinstance(error, self.IGNORED_EXCEPTIONS):
return error
def resolve(self, next, *args, **kwargs):
return next(*args, **kwargs).catch(self.on_error)
Но если исключение поймано или не возвращено, оно больше не заполняет поле errors
в выводе запроса / мутации. Поэтому все ошибки регистрируются, нет способа условно регистрировать исключения.
Это означает, что единственным решением является создание фильтра журналирования, подобного следующему:
def skip_valid_exceptions(record):
"""
Skip exceptions for errors only intended to be displayed to the API user.
"""
skip: bool = False
if record.exc_info:
exc_type, exc_value = record.exc_info[:2]
skip = isinstance(exc_value, valid_exceptions)
return not skip
Но это не работаетлибо потому, что record.exc_info
равно None
всякий раз, когда возникает ошибка с графеном, поэтому невозможно отфильтровать исключения по их типу.
Есть ли решение для этого? Похоже, это будет распространенной проблемой, но у меня возникли проблемы с поиском какого-либо решения.
В качестве альтернативы я мог бы просто не использовать исключения для отображения ошибок пользователю API, но это означало бы добавление ошибок в запросполе data.errors
результата вместо errors
. Это стандарт и требует адаптации внешней логики (такой как обработка ошибок Apollo), что не идеально. Это также означает, что никакие функциональные возможности не могут быть использованы из сторонних библиотек (таких как django-graphql-jwt), которые генерируют исключения.