首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何有条件地记录石墨烯-django中的异常?

如何有条件地记录石墨烯-django中的异常?
EN

Stack Overflow用户
提问于 2019-09-30 17:54:16
回答 1查看 1.6K关注 0票数 9

无论何时引发异常,它们都会记录在控制台中(如果使用了Sentry,还会记录在Sentry中)。

这些异常中的许多只打算显示给用户。例如django-graphql-jwt引发PermissionDenied异常对于login_required装饰者。

问题是,这会在测试/开发期间污染控制台输出,并在生产期间将有效错误记录到Sentry。对于像上面的例子这样的例外,它只打算显示给用户,注释已记录。

作为一种变通方法,我尝试编写中间件来捕获抛出的任何异常:

代码语言:javascript
复制
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查询/突变输出中的字段。因此,所有的错误都会被记录下来,没有办法有条件地记录异常。

这意味着唯一的解决方案是创建一个日志过滤器,如下所示:

代码语言:javascript
复制
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因此,每当使用Graphene抛出错误时,都不可能根据其类型有条件地过滤掉异常。

有解决方案吗?这似乎是一个常见的问题,但我很难找到任何解决方案。

或者,我可以不使用异常向API用户显示错误,但这意味着将错误放入查询结果的data.errors字段,而不是errors。这是一个标准,需要调整前端逻辑(例如Apollo的错误处理),这并不理想。这也意味着不能从抛出异常的第三方库(如django-graphql-jwt)中使用任何功能。

EN

回答 1

Stack Overflow用户

发布于 2020-11-17 02:49:11

试试这个。首先,确保预期的异常是GraphQLError或者它的后代。

然后创建一个日志过滤器,如下所示:

代码语言:javascript
复制
import logging
from graphql import GraphQLError

class GraphQLLogFilter(logging.Filter):
    """
    Filter GraphQL errors that are intentional.

    Any exceptions of type GraphQLError that are raised on purpose 
    to generate errors for GraphQL responses will be silenced from logs. 
    Other exceptions will be displayed so they can be tracked down.
    """
    def filter(self, record):
        if record.exc_info:
            etype, _, _ = record.exc_info
            if etype == GraphQLError:
                return None
        if record.stack_info and 'GraphQLError' in record.stack_info:
            return None
        if record.msg and 'GraphQLError' in record.msg:
            return None

        return True

在您的设置中使用:

代码语言:javascript
复制
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    # Prevent graphql exception from displaying in console
    'filters': {
        'graphql_log_filter': {
            '()': GraphQLLogFilter,
        }
    },
    'loggers': {
        'graphql.execution.utils': {
            'level': 'WARNING',
            'handlers': ['console'],
            'filters': ['graphql_log_filter'],
        },
    },
}

相关资源:

  • 浅谈石墨烯文库
  • Django日志记录文档
  • 过滤器如何工作
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58165464

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档