Как условно регистрировать исключения в графене-джанго? - PullRequest
0 голосов
/ 30 сентября 2019

Всякий раз, когда возникают исключения, они регистрируются в консоли (и в 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), которые генерируют исключения.

...