Django Datadog Logger
Django Datadog Logger is an integration package that provides Django middleware and formatters to send application logs to Datadog. It leverages Python's standard logging module to provide context-rich JSON-formatted logs, including request IDs and error details. The current version is 0.9.0, with a focus on active development and recent support for asynchronous Django (ASGI) environments.
Common errors
-
ModuleNotFoundError: No module named 'django_datadog_logger.middleware.request_id'
cause The `django-datadog-logger` package is either not installed in your environment or the import path specified in your `settings.py` is incorrect.fixRun `pip install django-datadog-logger` to install the package, and double-check the middleware paths in your `settings.py` against the official documentation. -
Logs in Datadog appear as plain text, or specific log attributes (like `request_id`, `status_code`) are not being parsed correctly into structured fields.
cause Your Django `LOGGING` configuration is not using `DatadogJSONFormatter`, or your Datadog Agent is not configured to process JSON-formatted logs from the specified log file/stream.fixEnsure the formatter for your Datadog-bound handlers is set to `'()': 'django_datadog_logger.formatters.datadog.DatadogJSONFormatter'`. If using file-based logging, verify your Datadog Agent's `conf.yaml` includes `source: python` and that `log_processing_rules` are correctly configured for JSON. -
Asynchronous views or ASGI applications are not producing logs with request context (e.g., missing `request_id`) or are encountering unexpected errors related to logging middleware.
cause You are likely running in an ASGI environment with an older version of `django-datadog-logger` that lacks native async middleware support. Prior to `v0.9.0`, middleware might not correctly interact with async request/response cycles.fixUpgrade to `django-datadog-logger==0.9.0` or a newer version. This version adds `async_capable = True` and `__acall__` implementations to the middleware classes to properly handle ASGI requests.
Warnings
- breaking Version 0.9.0 introduced native async middleware support for ASGI deployments. Prior versions may not fully support asynchronous operations with `RequestIdMiddleware`, `ErrorLoggingMiddleware`, and `RequestLoggingMiddleware`, potentially causing issues or lack of context in async views.
- gotcha For optimal parsing and full functionality within Datadog Log Management, it is crucial to use a JSON formatter for your logs. `django-datadog-logger` provides `DatadogJSONFormatter` which should be configured in your `LOGGING` settings. Using plain text formatters will result in unparsed or poorly structured logs in Datadog.
- gotcha The order of middleware in Django's `MIDDLEWARE` setting is important. `RequestIdMiddleware` should typically be placed early in the list (e.g., near the top) to ensure that a request ID is generated and available for all subsequent middleware and application logic that might generate logs.
- gotcha While `django-datadog-logger` enhances logging, for full Application Performance Monitoring (APM) integration and automatic injection of `dd.trace_id` and `dd.span_id` into your logs, you should also install and configure the `ddtrace` library from Datadog.
Install
-
pip install django-datadog-logger
Imports
- RequestIdMiddleware
from django_datadog_logger.middleware.request_id import RequestIdMiddleware
- ErrorLoggingMiddleware
from django_datadog_logger.middleware.error_log import ErrorLoggingMiddleware
- RequestLoggingMiddleware
from django_datadog_logger.middleware.request_log import RequestLoggingMiddleware
- DatadogJSONFormatter
from django_datadog_logger.formatters.datadog import DatadogJSONFormatter
Quickstart
import os
# settings.py
MIDDLEWARE = [
'django_datadog_logger.middleware.request_id.RequestIdMiddleware',
# ... other middlewares ...
'django_datadog_logger.middleware.error_log.ErrorLoggingMiddleware',
'django_datadog_logger.middleware.request_log.RequestLoggingMiddleware',
]
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'datadog_json': {
'()': 'django_datadog_logger.formatters.datadog.DatadogJSONFormatter',
'format': '%(levelname)s %(asctime)s %(name)s %(message)s',
},
},
'handlers': {
'datadog_file': {
'class': 'logging.FileHandler',
'filename': os.path.join(os.environ.get('LOG_DIR', './'), 'datadog.log'),
'formatter': 'datadog_json',
'level': 'INFO',
},
'console': {
'class': 'logging.StreamHandler',
'formatter': 'datadog_json',
'level': 'DEBUG',
}
},
'loggers': {
'': {
'handlers': ['console', 'datadog_file'],
'level': 'INFO',
'propagate': True
},
'django': {
'handlers': ['console', 'datadog_file'],
'level': 'INFO',
'propagate': False,
}
}
}