Set Up Sentry Error Monitoring for Django
Local logs are not enough once a Django app is in production. Exceptions can happen after deploys, during background jobs, or only under real user traffic patterns.
Problem statement
Local logs are not enough once a Django app is in production. Exceptions can happen after deploys, during background jobs, or only under real user traffic patterns. If you rely only on Gunicorn logs, reverse proxy logs, or manual SSH checks, production failures are easy to miss or slow to triage.
A practical Sentry setup for Django gives you centralized exception tracking, issue grouping, release visibility, and alerting. It does not replace server logs, but it helps you capture production errors quickly and tie them to the correct environment and release.
This guide shows how to configure Sentry for Django in a production-safe way: install the SDK, initialize it from environment variables, verify it after deploy, reduce noise, and keep rollback simple.
Quick answer
To set up Sentry error monitoring for Django safely in production:
- Create a Sentry project and copy the DSN.
- Install and pin
sentry-sdk. - Initialize Sentry in Django settings with
DjangoIntegration. - Pass
SENTRY_DSN,SENTRY_ENVIRONMENT, andSENTRY_RELEASEthrough environment variables. - Deploy and trigger a controlled test exception.
- Verify the event appears in the correct environment and release.
- If the rollout causes problems, clear
SENTRY_DSNand restart or redeploy.
Step-by-step solution
1) Create and prepare the Sentry project
Create a project in Sentry for your Django application. A standard Python or Django project is fine.
Before changing production settings, decide:
- which Sentry project will receive production events
- whether staging will use the same project with a separate environment, or a separate project
- what release identifier you will send, such as a git SHA or deploy version
At minimum, collect these values:
SENTRY_DSNSENTRY_ENVIRONMENTSENTRY_RELEASE
A simple release strategy is to use the current git commit:
git rev-parse --short HEAD
Example values:
SENTRY_DSN="https://example@o0.ingest.sentry.io/0"
SENTRY_ENVIRONMENT="production"
SENTRY_RELEASE="myapp@a1b2c3d"
Verification check: confirm you copied the DSN for the correct project before updating production config.
2) Install the Sentry SDK
Install the official SDK in your Django environment:
pip install sentry-sdk
Pin the dependency so deploys stay reproducible:
pip freeze > requirements.txt
If you manage dependencies with a lockfile or pyproject.toml, update that file instead.
Verification check: confirm sentry-sdk is included in the image, artifact, or virtual environment you actually deploy.
Rollback note: if dependency resolution causes build failures, revert the dependency change and deploy without Sentry first.
3) Configure Sentry in Django settings
Add Sentry initialization to the Django settings module used in production. Do not hardcode the DSN in source control.
import os
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
SENTRY_DSN = os.environ.get("SENTRY_DSN")
SENTRY_ENVIRONMENT = os.environ.get("SENTRY_ENVIRONMENT", "production")
SENTRY_RELEASE = os.environ.get("SENTRY_RELEASE")
if SENTRY_DSN:
sentry_sdk.init(
dsn=SENTRY_DSN,
integrations=[DjangoIntegration()],
environment=SENTRY_ENVIRONMENT,
release=SENTRY_RELEASE,
send_default_pii=False,
traces_sample_rate=0.0,
)
This enables exception tracking but leaves performance tracing disabled by default. That is a good baseline for production error monitoring because it keeps rollout simpler and avoids unexpected event volume.
If you need to filter noisy exceptions, add a before_send hook:
def before_send(event, hint):
exc_info = hint.get("exc_info")
if exc_info is not None:
exc_type, exc_value, tb = exc_info
if exc_type.__name__ == "DisallowedHost":
return None
return event
if SENTRY_DSN:
sentry_sdk.init(
dsn=SENTRY_DSN,
integrations=[DjangoIntegration()],
environment=SENTRY_ENVIRONMENT,
release=SENTRY_RELEASE,
send_default_pii=False,
traces_sample_rate=0.0,
before_send=before_send,
)
That example drops DisallowedHost, which often creates noise from random host header probes. Only filter DisallowedHost after confirming ALLOWED_HOSTS is correctly configured; filtering should reduce hostile-traffic noise, not hide a real deployment misconfiguration.
Verification check: start Django locally or in staging with the same settings path and confirm startup succeeds.
Rollback note: if app startup fails after this change, first clear SENTRY_DSN or unset it in the runtime environment and restart or redeploy. Prefer config rollback over editing application code during an incident.
4) Pass environment variables during deployment
Non-Docker example with systemd
Store runtime variables in an env file:
SENTRY_DSN=https://example@o0.ingest.sentry.io/0
SENTRY_ENVIRONMENT=production
SENTRY_RELEASE=myapp@a1b2c3d
Reference it from your service:
[Service]
EnvironmentFile=/etc/myapp/myapp.env
After updating the file:
sudo systemctl restart myapp
sudo systemctl status myapp
Run sudo systemctl daemon-reload only if you changed the unit file itself, not when you only updated the EnvironmentFile contents.
Do not put secrets directly into a committed unit file if your deployment process can avoid it.
Docker Compose example
services:
web:
environment:
SENTRY_DSN: ${SENTRY_DSN}
SENTRY_ENVIRONMENT: production
SENTRY_RELEASE: ${GIT_SHA}
Load SENTRY_DSN from your deployment environment or secret store, not from a checked-in file containing production secrets.
CI/CD injection
In CI/CD, set:
SENTRY_DSNas a secretSENTRY_ENVIRONMENTper environmentSENTRY_RELEASEfrom git SHA, tag, or build ID
This keeps the same code across staging and production while changing only environment-specific values.
Verification check: after deploy, verify the running service definition, rendered container configuration, or application behavior shows the expected values are in use.
5) Verify Sentry is working after deploy
Do not assume the integration works just because the app starts.
One practical check is a temporary test view:
from django.http import HttpResponse
def sentry_test_error(request):
raise RuntimeError("Sentry test error from production verification")
Add a temporary URL:
from django.urls import path
from .views import sentry_test_error
urlpatterns = [
path("sentry-test-error/", sentry_test_error),
]
Deploy, then request the endpoint once from a controlled source only. Do not leave the route exposed longer than necessary. If possible, trigger it from an internal IP, VPN, or another restricted path and remove it immediately after verification.
You should get a 500 response. Check Sentry for a new event in the expected project and environment.
Validation points:
- event appears in the correct Sentry project
- environment is labeled correctly
- release is attached if configured
- normal application requests still work
- application startup and worker startup were unaffected
After validation, remove the test route and redeploy.
If adding a temporary failing route is not acceptable in your environment, use a controlled one-time verification path in code that calls Sentry directly during a maintenance window, then remove it after the event is confirmed.
Rollback note: if verification reveals startup issues or excessive noise, clear SENTRY_DSN and restart the app while you investigate.
6) Configure alerting and ownership
Basic alerting is enough at first. Configure alerts for:
- new issues
- regressions
- high-frequency errors
Send alerts to the team channel that actually handles deploys and incidents. Email-only routing often gets ignored in small teams.
During initial rollout, keep alerts conservative. A noisy first week usually means:
- expected exceptions need filtering
- staging and production are mixed together
- probing traffic is generating avoidable errors
7) Cover worker and background-job processes
If you run Celery or other worker processes, do not stop at the web service. Workers need the same Sentry environment variables and the same initialization code path, or task failures may never appear in the expected project and release.
In practice, that means:
- worker processes should run with the same
SENTRY_DSN - worker processes should use the same
SENTRY_ENVIRONMENT - worker processes should receive the same
SENTRY_RELEASE - the Django settings module used by workers must also initialize Sentry
For example, if your web service and Celery worker both load the same Django settings module, the settings-based sentry_sdk.init(...) block above will apply to both, as long as the worker process gets the same environment variables.
Verification check: after deploy, run or trigger a controlled failing background job and confirm the event appears in Sentry with the correct environment and release.
8) Operational notes for production Django deployments
Sentry is useful for exceptions, stack traces, release correlation, and issue grouping. It does not replace:
- web server access logs
- reverse proxy logs
- structured application logs
- database logs
- infrastructure metrics
After deploys and migrations, watch both Sentry and your normal logs. Some failures appear as repeated exceptions in Sentry, while others show up first as startup failures, migration locks, timeout behavior, or upstream 502/504 errors in your proxy.
When to turn this into reusable automation
Once you repeat this setup across multiple Django services, the manual steps become good candidates for a template or deploy script. The settings block, env variable layout, release naming, and post-deploy verification are usually the first parts worth standardizing. Keep the manual path clear first so the automation reflects a known-good deployment.
Explanation
This Django Sentry integration works because the Sentry SDK hooks into Django’s exception handling and reports unhandled errors with request context, environment labels, and release metadata.
A few production-safe defaults matter:
if SENTRY_DSN:keeps Sentry optional and makes rollback easysend_default_pii=Falseavoids collecting user-identifying data unless you intentionally enable ittraces_sample_rate=0.0disables performance monitoring until you choose and tune it- environment variables keep secrets and environment-specific values out of source control
Use separate environments consistently. If staging sends events as production, issue triage becomes confusing quickly. If your app has high traffic or frequent bot noise, add filtering before enabling more features.
Edge cases / notes
- Multiple settings modules: add the Sentry block to the production settings path actually used by
DJANGO_SETTINGS_MODULE. - Staging vs production: separate projects can reduce confusion, but one project with distinct environment labels also works if your team is disciplined.
- Privacy and client IPs: review proxy and header handling before enabling PII collection. Do not turn on
send_default_pii=Truecasually. - High-volume error storms: filtering expected exceptions is usually better than broad sampling for basic error monitoring.
- Self-hosted Sentry: valid operationally, but you must maintain upgrades, storage, and reliability yourself.
- Gunicorn/Uvicorn timeouts and proxy errors: Sentry may show application exceptions, but upstream timeout behavior still needs app server and reverse proxy logs for full diagnosis.
- Migrations and startup failures: if the app fails before handling requests, you may see little or nothing in Sentry. Always keep direct access to service logs.
- Rollback priority: in an incident, disable Sentry by clearing
SENTRY_DSNin the runtime environment and restarting or redeploying. That is safer than making emergency code edits.
Internal links
For related deployment work, see:
- Django Deployment Checklist for Production
- Set Django Environment Variables in Production
- Deploy Django with Gunicorn and Nginx on Ubuntu
- How to Debug Django 500 Errors in Production
FAQ
Should I enable Sentry in development?
Usually no, or at least not by default in the same project as production. Local development already gives you direct tracebacks and logs. Staging is usually the better place to validate the production Sentry workflow.
Does Sentry replace Django logs?
No. Sentry is for exception tracking and issue management. You still need application logs, process logs, and reverse proxy logs for operational debugging.
How do I keep DSN and environment values secure?
Store them in environment variables, secret managers, CI/CD secrets, or protected env files. Do not hardcode them in settings.py or commit production secret files to version control.
Can I use Sentry with Celery and background jobs?
Yes, but test worker processes explicitly. Make sure worker services receive the same Sentry environment variables and load the same initialization path as the web application.
What should I do if Sentry generates too many events?
First, identify the noisy exception classes or endpoints and filter expected errors. Also verify that staging and production are separated correctly and that hostile probing traffic is not creating avoidable issue volume. If necessary, disable Sentry quickly by clearing SENTRY_DSN while you adjust the configuration.