episyche logo

Episyche

Django/Logger/

Logging with Django

Published on

Logging with Django
After deploying the Django application to production, we need to log the messages to debug and monitor the application. In this blog, we will configure the python logging module to log the messages in Django Application.

Introduction:

While developing applications, we can see the data and error messages by printing them in the terminal. But when we move the application to production, we will be running the application in background mode and we cannot monitor the errors and messages. Therefore, we log the messages to a file for monitoring and tracking events.

Django has an inbuilt python logging module that can be used for primary as well as advanced logging features.

The logging module has five log levels and each level has its own severity of events, which can be used to separate logs for relevant situations. Below is the list of log levels

  • DEBUG: logging.DEBUG level indicates that these logs can be used for diagnosing the problem in the code. It can be used to log detailed information for debugging code in development, such as when the app starts.

  • INFO: logging.INFO level indicates that these logs are information about the code, like checking if the code is running as expected. It can be used to log information about the code if it is running as expected, such as when a process starts in the app.

  • WARNING: logging.WARNING level indicates that these logs are about unexpected behavior, but do not affect the current flow. It can be used to report unexpected behavior that could cause a future problem but isn’t impacting the current process of the application, such as when the app detects low memory.

  • ERROR: logging.ERROR level indicates that these logs are about the failed events that affected the flow of the code. It can be used to report events when the software fails to perform some action, such as when the app fails to save data due to insufficient permissions given to the user or a database error.

  • CRITICAL: logging.CRITICAL level indicates that these logs are about the serious errors that affect the execution of the application and the flow of the code. It can be used to report severe errors that impact the continued performance of the application, such as when the application fails to store data due to insufficient memory.

Django

Logger

Loggers are the objects a developer usually interacts with. They are the main APIs that indicate what we want to log.

  • The module-level function logging can create the logger instance.getLogger(name)

import logging

logger = logging.getLogger(__name__)

  • Log levels can be set using the logger object as logger.log_level.

logger.info("Function called.")

Handler

  • Handlers determine where to put each log like directing the log message to the console or a log file.

  • Handlers also have log levels, if the message’s log level doesn't meet the requirements of the handler, the message will be ignored.

  • Loggers can have more than one handler. Because of that, the messages can be logged into multiple files.

Log formatter

  • Log Formatter is responsible for converting a log record to a string by adding the formatting attributes.

Flow Diagram:


flow diagram


\\

Prerequisites:

  • Python 3.8

  • Django Project

Steps:

Step 1: Configuring Logger

  • We can create or configure our own logger inside the Django application by adding the configuration to the settings.py file.

  • Move to the Django root app directory.

1cd <django-project-path>/<root-app-directory>
  • Then open the settings.py file in the root app directory and append the following snippet.

1LOGGING = { 2 'version': 1, 3 'disable_existing_loggers': False, 4 'loggers': { 5 'django': { 6 'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'), 7 'propagate': False, 8 }, 9 }, 10 }

Step 2: Configuring Logging Handlers

  • Now we will use the handlers to direct our message to a log file. To do that edit the logging configuration in the settings.py as follows.

1LOGGING = { 2 'version': 1, 3 'disable_existing_loggers': False, 4 'handlers': { 5 'file': { 6 'level': 'DEBUG', 7 'class': 'logging.FileHandler', 8 'filename': './your/path/debug.log', 9 }, 10 }, 11 'loggers': { 12 '': { # empty string 13 'handlers': ['file'], 14 'level': 'DEBUG', 15 'propagate': True, 16 }, 17 }, 18}
  • In the settings.py file, we created a file handler (i.e logging.FileHandler) with the DEBUG log level, indicating that we want to log the message into a file, and included the newly created handler into the logger.

In the logger, we have used the empty string as key to catch all the messages from Django app.

Step 3: Configuring Log formatters [Optional ]

Please follow the below steps, if you needed to define the log format in a custom manner. Otherwise please skip to the next step.

  • Create a formatter named verbose in the settings.py file

1'formatters': { 2 'verbose': { 3 'format': '{levelname} {asctime} {process:d} {message}', 4 'style': '{', 5 }, 6 },

The above configuration defines the format of the log, in which the format attribute defines the formatting options.

The description of the formats used in the above example is:

levelname: the logging level of the message (like debug, error., )

asctime: time of the log

process:d: Process ID (if available).

message: the message passed into the logger

  • To use other available format attributes, refer to the below link.

  • Now add the above formatter verbose to the handler as shown in the below snippet.

1 'handlers': { 2 'newfile': { 3 'level': 'DEBUG', 4 'class': 'logging.FileHandler', 5 'filename': '</your/path/debug.log>', 6 'formatter': 'verbose' 7 }, 8 },

If you followed the above said steps you’d have configured the logger with your Django Application and the messages will be logged into the file.

And the logging configuration will look like the following logger configuration example.

1LOGGING = { 2 'version': 1, 3 'disable_existing_loggers': False, 4 'formatters': { 5 'verbose': { 6 'format': '{levelname} {asctime} {process:d} {message}', 7 'style': '{', 8 }, 9 }, 10 'handlers': { 11 'newfile': { 12 'level': 'DEBUG', 13 'class': 'logging.FileHandler', 14 'filename': './your/path/debug.log', 15 'formatter': 'verbose' 16 }, 17 }, 18 'loggers': { 19 '': { 20 'level': 'DEBUG', 21 'handlers': ['newfile'], 22 'propagate': False, 23 }, 24 }, 25}

A sample settings.py file can be found in the following git repository file.

https://github.com/episyche/django_loggers_example/blob/master/core/settings.py#L128

Step 4: Adding Logger to Django App

  • To add the logger to the application, we have to import the logger and use the logger.<level>() to print the messages instead of the print() statement.

  • Open any views.py file under any app in your Django Application.

  • Import and create a logger instance inside views.py like below.

1import logging 2logger = logging.getLogger(__name__)
  • Then inside any API (class or function) create the event message (logger.error()) in the place of the print() statement like below.

1class Example_API(APIView): 2 3 def get(self, request): 4 msg = "GET method for the API" 5 logger.error("GET METHOD of EXAMPLE API called") 6 return Response(msg)
  • Now when the API is called, the event message will be logged into the log file in the path you defined in step 2.

  • The whole API will look like the below code snippet.

1from rest_framework.response import Response 2from rest_framework.views import APIView 3import logging 4logger = logging.getLogger(__name__) 5 6class Example_API(APIView): 7 8 def get(self, request): 9 msg = "GET method for the API" 10 logger.error("GET METHOD of EXAMPLE API called") 11 return Response(msg)

Step 5: Result

  • Now go to the path where your log file is located.

  • Use the tail command to stream the log file by running the following command.

    • The -f argument in the tail command continuously streams the file with updation.

1tail -f <path/to/your/log/file> 2 3In my case: 4tail -f /home/ubuntu/django_logger_example/debug_example.log
  • Open a browser and enter the path of your API where the logger is added and hit enter.

  • Then go to the terminal where the log file is opened, and you can see the log is printed.

  • See the below example screenshot for reference.


django logger example result

You can find the full source code for configuring multiple loggers can be found at the following github repo :


Comments