5

私の Django アプリがデバッグ情報をメールではなく slack に送信するようにしたいと考えていました。これはデフォルトです。

  • メールを無効にするのは簡単です。ADMINS設定にメールを入れないでください
  • Slack への情報送信は簡単です。着信 Webhook を追加するだけです

では、メッセージを送信するロジックはどこに作成すればよいでしょうか。ミドルウェアはかなり良いアイデアのようです。私は次のようなことをします

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

Noneミドルウェアは、システムの残りの部分に干渉しないように戻るだけです。何しろ、メール送信はすでに無効になっています。

だから私の質問は: django が収集するすべてのデバッグ情報を取得するにはどうすればよいですか? 私は次のようなことができます

import sys, traceback
pretty_debugging_message = '\n'.join(
    traceback.format_exception(*sys.exc_info())
)

ただし、これはトレースバックのみを提供します。すべてのローカル、セッション、クライアント IP などはどうですか?

https://docs.djangoproject.com/en/1.8/howto/error-reporting/を読むと、ミドルウェアが処理されるまで、つまりすべてが試行されるまで、そのすべての情報が収集されないことがわかります。エラーが処理されていない場合、Django はその ErrorReporter を実行し、情報をログに記録します。どうにかしてそのプロセスに介入し、情報を slack に送信させることはできますか? そのほうがいいでしょうか?

アップデート

私の解決策:

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
                }
            ]
        })

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,
        },
    }
}
4

3 に答える 3

0

これは 500 エラーでのみ機能します。

  import requests
  from django.views.debug import ExceptionReporter

  SLACK_TEAM_NAME = "myteam"

  class SlackHandler(AdminEmailHandler):
    def emit(self, record):
        ### Copy the emit from AdminEmailHandler
        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{}'.format(force_text(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)

        ### my stuff here
        html_message = reporter.get_traceback_text()
        token = "XXXXXXXXXXXXXXXX"
        channel = "#XXXXXXXXXXXX"
        html_channel = channel.replace("#","%23")
        url = "https://%s.slack.com/services/hooks/slackbot?token=%s&channel=%s" % (SLACK_TEAM_NAME, token, html_channel)
        #print url
        r = requests.post(url, data=html_message)

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.settings.SlackHandler',
        },
    },
    'loggers': {
        'django.request': {
            'handlers': ['slack'],
            'level': 'ERROR',
            'propagate': False,
        },
    },
}
于 2015-09-07T14:30:35.910 に答える