Django Supportedit

Getting Elastic APM set up for your Django project is easy, and there are various ways you can tweak it to fit to your needs.

Installationedit

Install the Elastic APM agent using pip:

$ pip install elastic-apm

or add it to your project’s requirements.txt file.

Note

If you use Django with uwsgi, make sure to enable threads.

Setupedit

Set up the Elastic APM agent in Django with these two steps:

  1. Add elasticapm.contrib.django to INSTALLED_APPS in your settings:
INSTALLED_APPS = (
   # ...
   'elasticapm.contrib.django',
)
  1. Choose an app name, and set the secret token if needed.
ELASTIC_APM = {
   'APP_NAME': '<APP-NAME>',
   'SECRET_TOKEN': '<SECRET-TOKEN>',
}

or as environment variables:

ELASTIC_APM_APP_NAME=<APP-NAME>
ELASTIC_APM_SECRET_TOKEN=<SECRET-TOKEN>

You now have basic error logging set up, and everything resulting in a 500 HTTP status code will be reported to the APM Server.

Performance Metricsedit

To send performance metrics to Elastic APM, simply add our tracing middleware to your MIDDLEWARES settings:

MIDDLEWARES = (
    'elasticapm.contrib.django.middleware.TracingMiddleware',
    # ...
)
Note

For Django 1.8, you can add the same middleware to MIDDLEWARE_CLASSES.

Make sure that it is the first middleware in the list.

Instrumenting custom Python codeedit

To gain further insights into the performance of your code, please see instrumenting custom code.

Ignoring specific viewsedit

You can use the TRANSACTIONS_IGNORE_PATTERNS configuration option to ignore specific views. The list given should be a list of regular expressions which are matched against the transaction name as seen in the Elastic APM user interface:

ELASTIC_APM['TRANSACTIONS_IGNORE_PATTERNS'] = ['^OPTIONS ', 'views.api.v2']

This example ignores any requests using the OPTIONS method and any requests containing views.api.v2.

Enabling and disabling the agentedit

The easiest way to disable the agent is to set Django’s DEBUG option to True in your development configuration. No errors or metrics will be logged to Elastic APM.

However, if during debugging you would like to force logging of errors to Elastic APM, then you can set DEBUG to True inside of the Elastic APM configuration dictionary, like this:

ELASTIC_APM = {
   # ...
   'DEBUG': True,
}

Loggingedit

For fine-grained control over logging use Python’s built-in logging module. If you are new to how the logging module works together with Django, read more in the Django documentation.

An example of how your LOGGING setting could look:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
    },
    'handlers': {
        'elasticapm': {
            'level': 'WARNING',
            'class': 'elasticapm.contrib.django.handlers.LoggingHandler',
        },
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose'
        }
    },
    'loggers': {
        'django.db.backends': {
            'level': 'ERROR',
            'handlers': ['console'],
            'propagate': False,
        },
        'mysite': {
            'level': 'WARNING',
            'handlers': ['elasticapm'],
            'propagate': False,
        },
        # Log errors from the Elastic APM module to the console (recommended)
        'elasticapm.errors': {
            'level': 'ERROR',
            'handlers': ['console'],
            'propagate': False,
        },
    },
}

With this configuration, logging can be done like this in any module in the myapp django app:

You can now use the logger in any module in the myapp django app, for instance myapp/views.py:

import logging
logger = logging.getLogger('mysite')

try:
    instance = MyModel.objects.get(pk=42)
except MyModel.DoesNotExist:
    logger.error(
        'Could not find instance, doing something else',
        exc_info=True
    )

Note that exc_info=True adds the exception information to the data that gets sent to Elastic APM. Without it, only the message is sent.

Extra dataedit

If you want to send more data than what you get with the agent by default, logging can be done like so:

import logging
logger = logging.getLogger('mysite')

try:
    instance = MyModel.objects.get(pk=42)
except MyModel.DoesNotExist:
    logger.error(
        'There was some crazy error',
        exc_info=True,
        extra={
            'datetime': str(datetime.now()),
        }
    )

Celery Integrationedit

For a general guide on how to set up Django with Celery, head over to Celery’s Django documentation.

Elastic APM will automatically log errors from your celery tasks, and record performance data.

Logging "HTTP 404 Not Found" Errorsedit

By default, Elastic APM does not log HTTP 404 errors. If you wish to log these errors, add 'elasticapm.contrib.django.middleware.Catch404Middleware' to MIDDLEWARES in your settings:

MIDDLEWARES = (
    # ...
    'elasticapm.contrib.django.middleware.Catch404Middleware',
    # ...
)

Note that this middleware respects Django’s IGNORABLE_404_URLS setting.

Disable the agent during testsedit

To prevent the agent from sending any data to the APM Server during tests, set the ELASTIC_APM_DISABLE_SEND environment variable to true, e.g.:

ELASTIC_APM_DISABLE_SEND=true python manage.py test

Troubleshootingedit

Elastic APM comes with a Django command that helps troubleshooting your setup. To check your configuration, run

python manage.py elasticapm check

To send a test exception using the current settings, run

python manage.py elasticapm test

If the command succeeds in sending a test exception, it will print a success message:

python manage.py elasticapm test

Trying to send a test error using these settings:

APP_NAME:           <APP_NAME>
SECRET_TOKEN:       <SECRET_TOKEN>
SERVERS:            http://localhost:8200

Success! We tracked the error successfully! You should be able to see it in a few seconds.

Supported Django and Python versionsedit

The agent supports the following Django versions:

  • 1.8
  • 1.9
  • 1.10
  • 1.11

and the following Python versions:

  • 2.7
  • 3.3
  • 3.4
  • 3.5
  • 3.6