Django + Slack integration to track exception logs

Create a slack webhook

  1. Create a new channel for logging all your Django exceptions.
  2. Log into slack.com and create s hook in Incoming Webhooks App
  3. Select your channel and after creation copy the webhook URL which begins with https://hooks.slack.com

Integrate hook into Django

First, install slack-webhook PyPI package:

pip install slack-webhook
🤔 We are using pip command above only to cover users who use it. We recommend using pipenv to have project local dependencies and useful version locking

In Django's settings.py add webhook value:

SLACK_WH ='https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXX'

🤔 For the military-security level we recomend you using django-environ or alternative way to read the variable from environment or secrets vault instead of hardcoding value in the repository.

Go you any views.py file, e.g. mine located in the "core" app and aff next view:

from slack_webhook import Slack  # import Slack module
from django.template import Template, Context # we will return with plaing string-based template
import sys 

def handler500(request):
    page_full_path = request.build_absolute_uri()
    slack = Slack(url=settings.SLACK_WH)
    type_, value, traceback = sys.exc_info()
    try:
        tb_str = traceback.format_exc()
    except Exception as e:
        tb_str = 'Not attached'

    slack.post(text=f"""
    🌋{settings.ENV}: 500: {page_full_path}
    {type_}{value}

    Traceback:
      ```
      {tb_str}
      ```
    😱
    """)
    
    response = Template('Internal Server Error').render(context=Context({}))
    response.status_code = 500
    return response

Later, instead of a string-based template you might want to use HTML template with a neat "We are sorry" image:

response = render(request, "500.html", context={})

In this case, don't forget to create a template in some template dir.

🤔 If you want to custumize your template never try to output any exception information to the page! Users will be very confussed and hackers will use this nice info to compromise your service

Enable webhook

In urls.py add this line:

handler500 = 'core.views.handler500'

Where 'core.views.handler500' is a full path to your handler500 function.

⚠ This will work only with two conditions:

  • DEBUG settings variable should be False
  • DEBUG_PROPAGATE_EXCEPTIONS settings variable should be False

So this thing in most cases should not bother you locally, because commonly locally you have DEBUG = True

Good luck and be notified about all your unexpected exceptions.