Log Django exceptions to Slack
Create a slack webhook
- Create a new channel for logging all your Django exceptions.
- Log into slack.com and create s hook in Incoming Webhooks App
- 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 beFalse
DEBUG_PROPAGATE_EXCEPTIONS
settings variable should beFalse
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.