# Django DataDog Logger
[](https://pypi.python.org/pypi/django-datadog-logger)
[](https://github.com/namespace-ee/django-datadog-logger/actions/workflows/pr-checks.yml)
[](https://github.com/namespace-ee/django-datadog-logger/actions/workflows/black.yml)
[](https://django-datadog-logger.readthedocs.io/en/latest/?badge=latest)
Django DataDog Logger integration package.
- Free software: MIT license
- Documentation: <https://django-datadog-logger.readthedocs.io>.
## Quick start
Set up request id tracking (in front) and logging middlewares (at the
end):
``` python
MIDDLEWARE = [
"django_datadog_logger.middleware.request_id.RequestIdMiddleware",
# ...
"django_datadog_logger.middleware.error_log.ErrorLoggingMiddleware",
"django_datadog_logger.middleware.request_log.RequestLoggingMiddleware",
]
```
Configure LOGGERS in your Django settings file:
``` python
API_LOG_ROOT = env.str("API_LOG_ROOT")
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"console": {"format": "{levelname} {message}", "style": "{"},
"json": {"()": "django_datadog_logger.formatters.datadog.DataDogJSONFormatter"},
},
"handlers": {
"console": {"level": "INFO", "class": "logging.StreamHandler", "formatter": "console"},
"application": {
"level": API_LOG_APPLICATION_LEVEL,
"class": "logging.FileHandler",
"filename": os.path.join(API_LOG_ROOT, "api.application.log"),
"formatter": "json",
},
"state": {
"level": API_LOG_STATE_LEVEL,
"class": "logging.FileHandler",
"filename": os.path.join(API_LOG_ROOT, "api.state.log"),
"formatter": "json",
},
"request": {
"level": API_LOG_REQUEST_LEVEL,
"class": "logging.FileHandler",
"filename": os.path.join(API_LOG_ROOT, "api.request.log"),
"formatter": "json",
},
"session": {
"level": API_LOG_SESSION_LEVEL,
"class": "logging.FileHandler",
"filename": os.path.join(API_LOG_ROOT, "api.session.log"),
"formatter": "json",
},
"error": {
"level": API_LOG_ERROR_LEVEL,
"class": "logging.FileHandler",
"filename": os.path.join(API_LOG_ROOT, "api.error.log"),
"formatter": "json",
},
},
"loggers": {
"": {"handlers": ["console", "error"], "level": "DEBUG", "propagate": True},
"ddtrace": {"handlers": ["error"], "level": "ERROR", "propagate": False},
"django.db.backends": {"handlers": ["error"], "level": "ERROR", "propagate": False},
"twilio": {"handlers": ["error"], "level": "ERROR", "propagate": False},
"my_project": {"handlers": ["application"], "level": "INFO", "propagate": False},
"my_project.throttling": {"handlers": ["application"], "level": "DEBUG", "propagate": False},
"my_project.vehicles.viewsets.state": {"handlers": ["state"], "level": "INFO", "propagate": False},
"my_project.accounts.session": {"handlers": ["session"], "level": "DEBUG", "propagate": False},
"my_project.session": {"handlers": ["session"], "level": "DEBUG", "propagate": False},
"django_auth_ldap": {"level": "DEBUG", "handlers": ["session"], "propagate": False},
"django_datadog_logger.middleware.error_log": {"handlers": ["error"], "level": "INFO", "propagate": False},
"django_datadog_logger.middleware.request_log": {"handlers": ["request"], "level": "INFO", "propagate": False},
"django_datadog_logger.rest_framework": {"handlers": ["application"], "level": "INFO", "propagate": False},
},
}
```
If you would like to whitelist your projects for passing extra arguments
to the json log record, please set the following regular expression:
``` python
DJANGO_DATADOG_LOGGER_EXTRA_INCLUDE = r"^(django_datadog_logger|my_project)(|\..+)$"
```
Add Celery logger configuration and request_id tracking decorator to
tasks:
``` python
import logging
from celery import Celery, shared_task
from celery.result import AsyncResult
from celery.signals import after_setup_logger, after_setup_task_logger
from django.conf import settings
from django_datadog_logger.celery import store_celery_request
logger = logging.getLogger(__name__)
@after_setup_logger.connect
def on_after_setup_logger(logger, *args, **kwargs):
from django_datadog_logger.formatters.datadog import DataDogJSONFormatter
if settings.API_LOG_CELERY_JSON:
formatter = DataDogJSONFormatter()
for handler in list(logger.handlers):
handler.setFormatter(formatter)
handler.setLevel(settings.API_LOG_CELERY_LEVEL)
@after_setup_task_logger.connect
def on_after_setup_task_logger(logger, *args, **kwargs):
from django_datadog_logger.formatters.datadog import DataDogJSONFormatter
if settings.API_LOG_CELERY_JSON:
formatter = DataDogJSONFormatter()
for handler in list(logger.handlers):
handler.setFormatter(formatter)
handler.setLevel(settings.API_LOG_CELERY_LEVEL)
app = Celery("my_project")
# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object("django.conf:settings", namespace="CELERY")
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
@shared_task(bind=True)
@store_celery_request
def debug_task(self):
print("Request: {0!r}".format(self.request))
logger.critical("CRITICAL", extra={"level": "CRITICAL"})
logger.error("ERROR", extra={"level": "ERROR"})
logger.warning("WARNING", extra={"level": "WARNING"})
logger.info("INFO", extra={"level": "INFO"})
logger.debug("DEBUG", extra={"level": "DEBUG"})
return 42
```
## ddtrace
The ddtrace library has an option to inject tracing context data into
log records:
<https://ddtrace.readthedocs.io/en/stable/advanced_usage.html#logs-injection>
There is a helper to look for those attributes and add them
automatically to the log entry created by this library.
``` python
# log.py
# Patch logging library to inject dd.* attributes on log records
import ddtrace
ddtrace.patch(logging=True)
# Configure logger with DataDogJSONFormatter
import logging
from django_datadog_logger.formatters.datadog import DataDogJSONFormatter
logger = logging.root
handler = logging.StreamHandler()
handler.formatter = DataDogJSONFormatter()
logger.addHandler(handler)
logger.setLevel(logging.INFO)
# Log a test message
logger.info("test")
```
``` bash
$ DD_SERVICE=django DD_ENV=test DD_VERSION=1234 python log.py
{"message": "test", "logger.name": "root", "logger.thread_name": "MainThread", "logger.method_name": "<module>", "syslog.timestamp": "2021-08-23T18:26:10.391099+00:00", "syslog.severity": "INFO", "dd.version": "1234", "dd.env": "test", "dd.service": "django", "dd.trace_id": "0", "dd.span_id": "0"}
```
If you remove the call to <span
class="title-ref">datadog.patch(logging=True)</span> you end up with:
``` bash
$ python test.py
{"message": "test", "logger.name": "root", "logger.thread_name": "MainThread", "logger.method_name": "<module>", "syslog.timestamp": "2021-08-23T18:27:47.951461+00:00", "syslog.severity": "INFO"}
```
## Credits
This package was created with
[Cookiecutter](https://github.com/audreyr/cookiecutter) and the
[audreyr/cookiecutter-pypackage](https://github.com/audreyr/cookiecutter-pypackage)
project template.
# History
## 0.6.2 (2023-04-27)
- Fixed case where accessing request.auth may raise errors
## 0.6.1 (2023-04-27)
- Removed dependency on Celery package, fixed import error
## 0.6.0 (2023-04-27)
- Removed dependency on Celery package
## 0.5.6 (2023-01-17)
- Datadog formatter: avoid recursion loop when accessing WSGI request
auth attribute
## 0.5.5 (2023-01-16)
- Improved support for request version reporting in <span
class="title-ref">http.request_version</span>
- Add support for <span
class="title-ref">http.url_details.view_name</span>
## 0.5.4 (2023-01-16)
- Added support for HTTP Accept header as <span
class="title-ref">http.accept</span>
## 0.5.3 (2022-12-19)
- Added support for JWT cid claim
## 0.5.2 (2022-11-23)
- Fixed: don't let the logger throw a DisallowedHost error
## 0.5.1 (2022-08-09)
- Fixed: ActionLoginMixin class methods <span
class="title-ref">perform_create</span> and <span
class="title-ref">perform_update</span> call <span
class="title-ref">super()</span>. Remove atomic transaction
## 0.5.0 (2021-10-20)
- Added support for Celery v5+
## 0.4.0 (2021-08-27)
- Enhancement: Updated formatting in README.rst \#5
- Enhancement: Extract and add dd.\* attributes from log record to log
entry dict \#6
- Fixed: KeyError because a dict appears where a list is expected \#7
## 0.3.5 (2021-06-14)
- Prevent recursion when warnings are logged whilst accessing WSGI
request.user
## 0.3.4 (2021-06-14)
- Fixed import error for future package
## 0.3.3 (2020-11-04)
- Added support for incoming HTTP X-Request-ID header values
## 0.3.2 (2020-04-24)
- Respect User.USERNAME_FIELD
## 0.3.1 (2020-04-24)
- Removed API_LOG_REQUEST_DURATION_WARN_SECONDS
## 0.3.0 (2020-04-15)
- Improved Celery task received messages logging.
- Removed RequestIdFilter (not needed anymore).
## 0.2.0 (2020-04-14)
- Added Celery request local.
## 0.1.0 (2020-02-17)
- First release on PyPI.
Raw data
{
"_id": null,
"home_page": "https://github.com/namespace-ee/django-datadog-logger",
"name": "django-datadog-logger",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "django_datadog_logger",
"author": "Lenno Nagel",
"author_email": "lenno@namespace.ee",
"download_url": "https://files.pythonhosted.org/packages/7f/ec/d36154ea51a4a7ad9bcff4a02ccb5f1db47e1ef52d52c870f2c0dfdfa787/django_datadog_logger-0.7.3.tar.gz",
"platform": null,
"description": "# Django DataDog Logger\n\n[](https://pypi.python.org/pypi/django-datadog-logger)\n[](https://github.com/namespace-ee/django-datadog-logger/actions/workflows/pr-checks.yml)\n[](https://github.com/namespace-ee/django-datadog-logger/actions/workflows/black.yml)\n[](https://django-datadog-logger.readthedocs.io/en/latest/?badge=latest)\n\nDjango DataDog Logger integration package.\n\n- Free software: MIT license\n- Documentation: <https://django-datadog-logger.readthedocs.io>.\n\n## Quick start\n\nSet up request id tracking (in front) and logging middlewares (at the\nend):\n\n``` python\nMIDDLEWARE = [\n \"django_datadog_logger.middleware.request_id.RequestIdMiddleware\",\n # ...\n \"django_datadog_logger.middleware.error_log.ErrorLoggingMiddleware\",\n \"django_datadog_logger.middleware.request_log.RequestLoggingMiddleware\",\n]\n```\n\nConfigure LOGGERS in your Django settings file:\n\n``` python\nAPI_LOG_ROOT = env.str(\"API_LOG_ROOT\")\nLOGGING = {\n \"version\": 1,\n \"disable_existing_loggers\": False,\n \"formatters\": {\n \"console\": {\"format\": \"{levelname} {message}\", \"style\": \"{\"},\n \"json\": {\"()\": \"django_datadog_logger.formatters.datadog.DataDogJSONFormatter\"},\n },\n \"handlers\": {\n \"console\": {\"level\": \"INFO\", \"class\": \"logging.StreamHandler\", \"formatter\": \"console\"},\n \"application\": {\n \"level\": API_LOG_APPLICATION_LEVEL,\n \"class\": \"logging.FileHandler\",\n \"filename\": os.path.join(API_LOG_ROOT, \"api.application.log\"),\n \"formatter\": \"json\",\n },\n \"state\": {\n \"level\": API_LOG_STATE_LEVEL,\n \"class\": \"logging.FileHandler\",\n \"filename\": os.path.join(API_LOG_ROOT, \"api.state.log\"),\n \"formatter\": \"json\",\n },\n \"request\": {\n \"level\": API_LOG_REQUEST_LEVEL,\n \"class\": \"logging.FileHandler\",\n \"filename\": os.path.join(API_LOG_ROOT, \"api.request.log\"),\n \"formatter\": \"json\",\n },\n \"session\": {\n \"level\": API_LOG_SESSION_LEVEL,\n \"class\": \"logging.FileHandler\",\n \"filename\": os.path.join(API_LOG_ROOT, \"api.session.log\"),\n \"formatter\": \"json\",\n },\n \"error\": {\n \"level\": API_LOG_ERROR_LEVEL,\n \"class\": \"logging.FileHandler\",\n \"filename\": os.path.join(API_LOG_ROOT, \"api.error.log\"),\n \"formatter\": \"json\",\n },\n },\n \"loggers\": {\n \"\": {\"handlers\": [\"console\", \"error\"], \"level\": \"DEBUG\", \"propagate\": True},\n \"ddtrace\": {\"handlers\": [\"error\"], \"level\": \"ERROR\", \"propagate\": False},\n \"django.db.backends\": {\"handlers\": [\"error\"], \"level\": \"ERROR\", \"propagate\": False},\n \"twilio\": {\"handlers\": [\"error\"], \"level\": \"ERROR\", \"propagate\": False},\n \"my_project\": {\"handlers\": [\"application\"], \"level\": \"INFO\", \"propagate\": False},\n \"my_project.throttling\": {\"handlers\": [\"application\"], \"level\": \"DEBUG\", \"propagate\": False},\n \"my_project.vehicles.viewsets.state\": {\"handlers\": [\"state\"], \"level\": \"INFO\", \"propagate\": False},\n \"my_project.accounts.session\": {\"handlers\": [\"session\"], \"level\": \"DEBUG\", \"propagate\": False},\n \"my_project.session\": {\"handlers\": [\"session\"], \"level\": \"DEBUG\", \"propagate\": False},\n \"django_auth_ldap\": {\"level\": \"DEBUG\", \"handlers\": [\"session\"], \"propagate\": False},\n \"django_datadog_logger.middleware.error_log\": {\"handlers\": [\"error\"], \"level\": \"INFO\", \"propagate\": False},\n \"django_datadog_logger.middleware.request_log\": {\"handlers\": [\"request\"], \"level\": \"INFO\", \"propagate\": False},\n \"django_datadog_logger.rest_framework\": {\"handlers\": [\"application\"], \"level\": \"INFO\", \"propagate\": False},\n },\n}\n```\n\nIf you would like to whitelist your projects for passing extra arguments\nto the json log record, please set the following regular expression:\n\n``` python\nDJANGO_DATADOG_LOGGER_EXTRA_INCLUDE = r\"^(django_datadog_logger|my_project)(|\\..+)$\"\n```\n\nAdd Celery logger configuration and request_id tracking decorator to\ntasks:\n\n``` python\nimport logging\n\nfrom celery import Celery, shared_task\nfrom celery.result import AsyncResult\nfrom celery.signals import after_setup_logger, after_setup_task_logger\nfrom django.conf import settings\nfrom django_datadog_logger.celery import store_celery_request\n\nlogger = logging.getLogger(__name__)\n\n\n@after_setup_logger.connect\ndef on_after_setup_logger(logger, *args, **kwargs):\n from django_datadog_logger.formatters.datadog import DataDogJSONFormatter\n\n if settings.API_LOG_CELERY_JSON:\n formatter = DataDogJSONFormatter()\n for handler in list(logger.handlers):\n handler.setFormatter(formatter)\n handler.setLevel(settings.API_LOG_CELERY_LEVEL)\n\n\n@after_setup_task_logger.connect\ndef on_after_setup_task_logger(logger, *args, **kwargs):\n from django_datadog_logger.formatters.datadog import DataDogJSONFormatter\n\n if settings.API_LOG_CELERY_JSON:\n formatter = DataDogJSONFormatter()\n for handler in list(logger.handlers):\n handler.setFormatter(formatter)\n handler.setLevel(settings.API_LOG_CELERY_LEVEL)\n\n\napp = Celery(\"my_project\")\n\n# Using a string here means the worker will not have to\n# pickle the object when using Windows.\napp.config_from_object(\"django.conf:settings\", namespace=\"CELERY\")\napp.autodiscover_tasks(lambda: settings.INSTALLED_APPS)\n\n\n@shared_task(bind=True)\n@store_celery_request\ndef debug_task(self):\n print(\"Request: {0!r}\".format(self.request))\n logger.critical(\"CRITICAL\", extra={\"level\": \"CRITICAL\"})\n logger.error(\"ERROR\", extra={\"level\": \"ERROR\"})\n logger.warning(\"WARNING\", extra={\"level\": \"WARNING\"})\n logger.info(\"INFO\", extra={\"level\": \"INFO\"})\n logger.debug(\"DEBUG\", extra={\"level\": \"DEBUG\"})\n return 42\n```\n\n## ddtrace\n\nThe ddtrace library has an option to inject tracing context data into\nlog records:\n<https://ddtrace.readthedocs.io/en/stable/advanced_usage.html#logs-injection>\n\nThere is a helper to look for those attributes and add them\nautomatically to the log entry created by this library.\n\n``` python\n# log.py\n\n# Patch logging library to inject dd.* attributes on log records\nimport ddtrace\nddtrace.patch(logging=True)\n\n# Configure logger with DataDogJSONFormatter\nimport logging\nfrom django_datadog_logger.formatters.datadog import DataDogJSONFormatter\n\nlogger = logging.root\n\nhandler = logging.StreamHandler()\nhandler.formatter = DataDogJSONFormatter()\nlogger.addHandler(handler)\nlogger.setLevel(logging.INFO)\n\n\n# Log a test message\nlogger.info(\"test\")\n```\n\n``` bash\n$ DD_SERVICE=django DD_ENV=test DD_VERSION=1234 python log.py\n{\"message\": \"test\", \"logger.name\": \"root\", \"logger.thread_name\": \"MainThread\", \"logger.method_name\": \"<module>\", \"syslog.timestamp\": \"2021-08-23T18:26:10.391099+00:00\", \"syslog.severity\": \"INFO\", \"dd.version\": \"1234\", \"dd.env\": \"test\", \"dd.service\": \"django\", \"dd.trace_id\": \"0\", \"dd.span_id\": \"0\"}\n```\n\nIf you remove the call to <span\nclass=\"title-ref\">datadog.patch(logging=True)</span> you end up with:\n\n``` bash\n$ python test.py\n{\"message\": \"test\", \"logger.name\": \"root\", \"logger.thread_name\": \"MainThread\", \"logger.method_name\": \"<module>\", \"syslog.timestamp\": \"2021-08-23T18:27:47.951461+00:00\", \"syslog.severity\": \"INFO\"}\n```\n\n## Credits\n\nThis package was created with\n[Cookiecutter](https://github.com/audreyr/cookiecutter) and the\n[audreyr/cookiecutter-pypackage](https://github.com/audreyr/cookiecutter-pypackage)\nproject template.\n\n\n# History\n\n## 0.6.2 (2023-04-27)\n\n- Fixed case where accessing request.auth may raise errors\n\n## 0.6.1 (2023-04-27)\n\n- Removed dependency on Celery package, fixed import error\n\n## 0.6.0 (2023-04-27)\n\n- Removed dependency on Celery package\n\n## 0.5.6 (2023-01-17)\n\n- Datadog formatter: avoid recursion loop when accessing WSGI request\n auth attribute\n\n## 0.5.5 (2023-01-16)\n\n- Improved support for request version reporting in <span\n class=\"title-ref\">http.request_version</span>\n- Add support for <span\n class=\"title-ref\">http.url_details.view_name</span>\n\n## 0.5.4 (2023-01-16)\n\n- Added support for HTTP Accept header as <span\n class=\"title-ref\">http.accept</span>\n\n## 0.5.3 (2022-12-19)\n\n- Added support for JWT cid claim\n\n## 0.5.2 (2022-11-23)\n\n- Fixed: don't let the logger throw a DisallowedHost error\n\n## 0.5.1 (2022-08-09)\n\n- Fixed: ActionLoginMixin class methods <span\n class=\"title-ref\">perform_create</span> and <span\n class=\"title-ref\">perform_update</span> call <span\n class=\"title-ref\">super()</span>. Remove atomic transaction\n\n## 0.5.0 (2021-10-20)\n\n- Added support for Celery v5+\n\n## 0.4.0 (2021-08-27)\n\n- Enhancement: Updated formatting in README.rst \\#5\n- Enhancement: Extract and add dd.\\* attributes from log record to log\n entry dict \\#6\n- Fixed: KeyError because a dict appears where a list is expected \\#7\n\n## 0.3.5 (2021-06-14)\n\n- Prevent recursion when warnings are logged whilst accessing WSGI\n request.user\n\n## 0.3.4 (2021-06-14)\n\n- Fixed import error for future package\n\n## 0.3.3 (2020-11-04)\n\n- Added support for incoming HTTP X-Request-ID header values\n\n## 0.3.2 (2020-04-24)\n\n- Respect User.USERNAME_FIELD\n\n## 0.3.1 (2020-04-24)\n\n- Removed API_LOG_REQUEST_DURATION_WARN_SECONDS\n\n## 0.3.0 (2020-04-15)\n\n- Improved Celery task received messages logging.\n- Removed RequestIdFilter (not needed anymore).\n\n## 0.2.0 (2020-04-14)\n\n- Added Celery request local.\n\n## 0.1.0 (2020-02-17)\n\n- First release on PyPI.\n",
"bugtrack_url": null,
"license": "MIT license",
"summary": "Django DataDog Logger integration package.",
"version": "0.7.3",
"project_urls": {
"Homepage": "https://github.com/namespace-ee/django-datadog-logger"
},
"split_keywords": [
"django_datadog_logger"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "541057e7b9f6cc605a7046206e52aadf8e44776f7ac312640a548683fbd91258",
"md5": "09dade56575f26753859d4c77ecad967",
"sha256": "87838cd868f407e050831c536413de6b2ece31433b28c952c0fd90be1d66486a"
},
"downloads": -1,
"filename": "django_datadog_logger-0.7.3-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "09dade56575f26753859d4c77ecad967",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": ">=3.7",
"size": 14004,
"upload_time": "2024-11-21T13:36:10",
"upload_time_iso_8601": "2024-11-21T13:36:10.183340Z",
"url": "https://files.pythonhosted.org/packages/54/10/57e7b9f6cc605a7046206e52aadf8e44776f7ac312640a548683fbd91258/django_datadog_logger-0.7.3-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7fecd36154ea51a4a7ad9bcff4a02ccb5f1db47e1ef52d52c870f2c0dfdfa787",
"md5": "280bc35eef38276b46e345028eefa645",
"sha256": "4361bb068a4b188fa14135398f9b747728464a291757e6adf8c95c9215dcd602"
},
"downloads": -1,
"filename": "django_datadog_logger-0.7.3.tar.gz",
"has_sig": false,
"md5_digest": "280bc35eef38276b46e345028eefa645",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 19894,
"upload_time": "2024-11-21T13:36:11",
"upload_time_iso_8601": "2024-11-21T13:36:11.482845Z",
"url": "https://files.pythonhosted.org/packages/7f/ec/d36154ea51a4a7ad9bcff4a02ccb5f1db47e1ef52d52c870f2c0dfdfa787/django_datadog_logger-0.7.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-21 13:36:11",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "namespace-ee",
"github_project": "django-datadog-logger",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"tox": true,
"lcname": "django-datadog-logger"
}