Introduction¶
django-rich-logging outputs the current Django request in a live updating table for easy parsing.
Installation¶
poetry add django-rich-logging OR pip install django-rich-logging
Configuration¶
django-rich-logging uses the log records emitted by the django.server logger to do its magic. However, configuring logging in Django (and in Python in general) can sometimes be a little obtuse.
Minimal configuration¶
# settings.py
# other settings here
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"django_rich_logging": {
"class": "django_rich_logging.logging.DjangoRequestHandler",
},
},
"loggers": {
"django.server": {"handlers": ["django_rich_logging"]},
"django.request": {"level": "CRITICAL"},
},
}
# other settings here
DjangoRequestHandlerhandles log messages from thedjango.serverloggerthe level must be
INFOor below to get all requests (which it is by default)there must be a handler which uses
django_rich_logging.logging.DjangoRequestHandler
django.requestshould be set toCRITICALotherwise you will see 4xx and 5xx status codes getting logged twice
Only logging when debug¶
Most of the time, you will only want this type of logging when in local development (i.e. DEBUG = True). The require_debug_true logging filter can be used for this purpose.
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"filters": {
"require_debug_true": {
"()": "django.utils.log.RequireDebugTrue",
},
},
"handlers": {
"django_rich_logging": {
"class": "django_rich_logging.logging.DjangoRequestHandler",
"filters": ["require_debug_true"],
},
},
"loggers": {
"django.server": {"handlers": ["django_rich_logging"]},
"django.request": {"level": "CRITICAL"},
},
}
Column configuration¶
The columns that are logged are configurable via the columns key in the django_rich_logging handler. The default column configuration is as follows.
...
"handlers": {
"django_rich_logging": {
"class": "django_rich_logging.logging.DjangoRequestHandler",
"columns": [
{"header": "Method", "format": "[white]{method}", "style": "{"},
{"header": "Path", "format": "[white bold]{path}", "style": "{"},
{"header": "Status", "format": "{status_code}", "style": "{"},
{"header": "Size", "format": "[white]{size}", "style": "{"},
{
"header": "Time",
"format": "[white]{created}",
"style": "{",
"datefmt": "%H:%M:%S",
},
],
},
},
...
headeris the name of the column headerformatfollows the same conventions as a normal Python logging formatter which uses string interpolation to insert data from the current requestSimilar to a logging formatter,
stylecan be specified for the type of string interpolation to use (e.g.%,{, or$); to follow legacy Python conventions,styledefaults to%
The available information that be specified in format:
method: HTTP method, e.g. GET, POSTpath: The path of the request, e.g. /indexstatus_code: Status code of the request, e.g. 200, 404, 500size: Length of the contentcreated:datetimeof when the log was generated; can be additionally formatted into a string withdatefmt
Formatted output can be colored or styled with the use of rich markup, e.g. [white bold]something here[\white bold]
Style attributes, e.g. bold, italic
Available colors, e.g. red, blue
Emojis, e.g. :warning:
More information about Django logging¶
Information about logging
django.server: https://docs.djangoproject.com/en/stable/ref/logging/#django-serverGeneric information about logging with Django: https://docs.djangoproject.com/en/stable/topics/logging/
Other logging approaches¶
Inspiration and thanks¶
https://twitter.com/marcelpociot/status/1491771828091695111 for the initial inspiration and my reaction: https://twitter.com/adamghill/status/1491780864447033348
Dependencies¶
https://github.com/Textualize/rich for making terminal output beautiful