发送生产错误而不是电子邮件

Eld*_*mir 5 django reporting middleware slack-api

我想让我的Django应用程序发送调试信息而不是通过电子邮件,这是默认设置.

  • 禁用电子邮件很简单.只是不要在ADMINS设置中添加任何电子邮件
  • 将信息发送到松弛状态很容易.只需添加一个传入的webhook

现在,我应该在哪里创建发送消息的逻辑?中间件似乎是个不错的主意.我会做点什么的

class ExceptionMiddleware:
    def process_exception(self, request, exception):
        pretty_debugging_message = ...
        requests.post("https://my-slack-url/", {...})
Run Code Online (Sandbox Code Playgroud)

中间件只会返回,None以免干扰系统的其余部分; 毕竟,电子邮件已被禁用.

所以我的问题是:如何获得django收集的所有调试信息?我可以做点什么

import sys, traceback
pretty_debugging_message = '\n'.join(
    traceback.format_exception(*sys.exc_info())
)
Run Code Online (Sandbox Code Playgroud)

但这仅提供追溯.那么所有的本地人,会议,客户IP等呢?

通过https://docs.djangoproject.com/en/1.8/howto/error-reporting/阅读,我认为所有这些信息都是在处理中间件之后才收集的,也就是说,一旦尝试了所有内容,如果没有处理错误,那么Django会运行其ErrorReporter并记录信息.我可以以某种方式干预这个过程并让它发送信息松弛吗?会更好吗?

更新

我的解决方案

class SlackHandler(AdminEmailHandler):
    def emit(self, record):
        try:
            request = record.request
            subject = '%s (%s IP): %s' % (
                record.levelname,
                ('internal' if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS
                 else 'EXTERNAL'),
                record.getMessage()
            )
            filter = get_exception_reporter_filter(request)
            request_repr = '\n{0}'.format(filter.get_request_repr(request))
        except Exception:
            subject = '%s: %s' % (
                record.levelname,
                record.getMessage()
            )
            request = None
            request_repr = "unavailable"
        subject = self.format_subject(subject)

        if record.exc_info:
            exc_info = record.exc_info
        else:
            exc_info = (None, record.getMessage(), None)

        message = "%s\n\nRequest repr(): %s" % (self.format(record), request_repr)
        reporter = ExceptionReporter(request, is_email=True, *exc_info)
        html_message = reporter.get_traceback_html() if self.include_html else None

        requests.post(settings.SLACK_WEBHOOK_URL, json={
            "fallback": message,
            "pretext": "An error occured",
            "color": "#ef2a2a",
            "fields": [
                {
                    "title": "Error",
                    "value": message,
                    "short": False
                }
            ]
        })
Run Code Online (Sandbox Code Playgroud)

在settings.py中:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'slack': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'myapp.myapp.SlackHandler'
        }
        # 'mail_admins': {
        #     'level': 'ERROR',
        #     'filters': ['require_debug_false'],
        #     'class': 'django.utils.log.AdminEmailHandler'
        # }
    },
    'loggers': {
        'django.request': {
            'handlers': ['slack'],
            'level': 'ERROR',
            'propagate': True,
        },
    }
}
Run Code Online (Sandbox Code Playgroud)

aum*_*umo 8

我建议你创建一个自定义日志记录处理程序.您可以查看AdminEmailHandler实现并制作您自己的,或者更简单的,如果它符合您的需要,将其子类化并仅覆盖该send_mail方法.

import requests

from django.utils.log import AdminEmailHandler


class SlackHandler(AdminEmailHandler):
    def send_mail(self, subject, message, *args, **kwargs):
        html_message = kwargs.get('html_message')
        requests.post("https://my-slack-url/", {...})
Run Code Online (Sandbox Code Playgroud)

然后,您需要配置LOGGING设置以使用新的处理程序而不是AdminEmailHandler.这是Django的默认日志配置.

例:

'handlers': {
    'slack': {
        'level': 'ERROR',
        'filters': ['require_debug_false'],
        'class': 'import.path.to.SlackHandler'
    }
},
# ...
'loggers': {
    'django.request': {
        'handlers': ['slack'],
        'level': 'ERROR',
        'propagate': False,
    },
    # ...
}
Run Code Online (Sandbox Code Playgroud)

  • 我做到了。从不调用 send_email 方法。相反,我已经覆盖了emit 方法。现在它可以工作了:)感谢您的帮助 (2认同)