The middleware adds an ID to your logs that is unique to each incoming request. Correlation IDs (also knows as request IDs) make it easy to correlate logs from a single HTTP request, and makes debugging simple.
Django GUID also includes ways of extending correlation IDs to Celery workers and Sentry issues.
For the purposes of this package, a GUID (globally unique identifier) is equivalent to a UUID (universally unique identifier).
Let's assume we have three outgoing requests happening at the same time across our application instances:
INFO project.views Fetching resource
INFO project.views Fetching resource
INFO project.views Fetching resource
INFO project.services Finished successfully
INFO project.services Finished successfully
ERROR project.services Something went wrong!
Without a correlation-id we have no way of knowing which logs belong to which request.
Using a log filter, we can do a little better:
INFO [773fa6885e03493498077a273d1b7f2d] project.views Fetching resource
INFO [0d1c3919e46e4cd2b2f4ac9a187a8ea1] project.views Fetching resource
INFO [99d44111e9174c5a9494275aa7f28858] project.views Fetching resource
INFO [99d44111e9174c5a9494275aa7f28858] project.services Finished successfully
INFO [773fa6885e03493498077a273d1b7f2d] project.services Finished successfully
ERROR [0d1c3919e46e4cd2b2f4ac9a187a8ea1] project.services Something went wrong!
With the filter, we now know which logs belong to which request and can start debugging.
pip install django-guidPackage settings are added in your settings.py:
DJANGO_GUID = {
'GUID_HEADER_NAME': 'X-Request-ID',
'VALIDATE_GUID': True,
'RETURN_HEADER': True,
'EXPOSE_HEADER': True,
'INTEGRATIONS': [],
'IGNORE_URLS': [],
'UUID_LENGTH': 32,
}Optional Parameters
-
GUID_HEADER_NAMEThe name of the GUID to look for in a header in an incoming request. Remember that it's case insensitive.
Default:
Correlation-ID -
VALIDATE_GUIDWhether the
GUID_HEADER_NAMEshould be validated or not. If the GUID sent to through the header is not a valid GUID (uuid.uuid4).Default:
True -
RETURN_HEADERWhether to return the GUID (Correlation-ID) as a header in the response or not. It will have the same name as the
GUID_HEADER_NAMEsetting.Default:
True -
EXPOSE_HEADERWhether to return
Access-Control-Expose-Headersfor the GUID header ifRETURN_HEADERisTrue, has no effect ifRETURN_HEADERisFalse. This is allows the JavaScript Fetch API to access the header when CORS is enabled.Default:
True -
INTEGRATIONSWhether to enable any custom or available integrations with
django_guid. As an example, usingSentryIntegration()as an integration would set Sentry'stransaction_idto match the GUID used by the middleware.Default:
[] -
IGNORE_URLSURL endpoints where the middleware will be disabled. You can put your health check endpoints here.
Default:
[] -
UUID_LENGTHLets you optionally trim the length of the package generated UUIDs.
Default:
32
Once settings have set up, add the following to your projects' settings.py:
Add django_guid to your INSTALLED_APPS:
INSTALLED_APPS = [
'django_guid',
]Add the django_guid.middleware.guid_middleware to your MIDDLEWARE:
MIDDLEWARE = [
'django_guid.middleware.guid_middleware',
...
]It is recommended that you add the middleware at the top, so that the remaining middleware loggers include the requests GUID.
Add django_guid.log_filters.CorrelationId as a filter in your LOGGING configuration:
LOGGING = {
...
'filters': {
'correlation_id': {
'()': 'django_guid.log_filters.CorrelationId'
}
}
}Put that filter in your handler:
LOGGING = {
...
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'medium',
'filters': ['correlation_id'],
}
}
}And make sure to add the new correlation_id filter to one or all of your formatters:
LOGGING = {
...
'formatters': {
'medium': {
'format': '%(levelname)s %(asctime)s [%(correlation_id)s] %(name)s %(message)s'
}
}
}If these settings were confusing, you might find the repo examples helpful.
If you wish to see the Django GUID middleware outputs, you may configure a logger for the module. Simply add django_guid to your loggers in the project, like in the example below:
LOGGING = {
...
'loggers': {
'django_guid': {
'handlers': ['console', 'logstash'],
'level': 'WARNING',
'propagate': False,
}
}
}This could be useful for debugging problems with request ID propagation. If a received request header containing a request ID is misconfigured, we will not raise exceptions, but will generate warning logs.