Django/Logger/
2022-12-19T07:51:41.881923Z
Published on
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.
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.")
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 is responsible for converting a log record to a string by adding the formatting attributes.
Python 3.8
Django Project
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 }
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.
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
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)
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.
Comments