Post

Logging Module for Python

Logging Levels

Log LevelNumerical ValuePurpose
DEBUG10Provides detailed information for diagnosing code-related issues, such as printing variable values and function call traces.
INFO20Used to confirm that the program is working as expected, like displaying startup messages and progress indicators.
WARNING30Indicates a potential problem that may not be critical to interrupt the program’s execution but could cause issues later on.
ERROR40Represents an unexpected behavior of the code that impacts its functionality, such as exceptions, syntax errors, or out-of-memory errors.
CRITICAL50Denotes a severe error that can lead to the termination of the program, like system crashes or fatal errors.

1. Setting the log level

1
2
3
4
5
6
7
import logging

# Create a logger
logger = logging.getLogger(__name__)

# Set logger level to DEBUG
logger.setLevel(logging.DEBUG)

2. Creating a Formatter

1
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')

3. Creating Handlers

As discussed previously, handlers manage where your log messages will be sent. We will create two handlers: a console handler to log messages to the console and a file handler to write log messages to a file named ‘app.log’.

1
2
3
4
5
6
7
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(formatter)

file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)

Both handlers are then added to the logger using the addHandler() method.

1
2
logger.addHandler(console_handler)
logger.addHandler(file_handler)

4. Testing the Logging Setup

Now that our setup is complete, let’s test if it’s working correctly before moving to the real-life example. We can log some messages as follows:

1
2
3
4
5
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')

When you run this code, you should see the log messages printed to the console and written to a file named ‘app.log’, like this:

Console

1
2
3
4
2024-05-18 11:51:44,187 - INFO - This is an info message
2024-05-18 11:51:44,187 - WARNING - This is a warning message
2024-05-18 11:51:44,187 - ERROR - This is an error message
2024-05-18 11:51:44,187 - CRITICAL - This is a critical message

app.log

1
2
3
4
5
2024-05-18 11:51:44,187 - DEBUG - This is a debug message
2024-05-18 11:51:44,187 - INFO - This is an info message
2024-05-18 11:51:44,187 - WARNING - This is a warning message
2024-05-18 11:51:44,187 - ERROR - This is an error message
2024-05-18 11:51:44,187 - CRITICAL - This is a critical message

Logging User Activity in a Web Application

In this simple example, we will create a basic web application that logs user activity using Python’s logging module. This application will have two endpoints: one for logging successful login attempts and the other to document failed ones (INFO for success and WARNING for failures).

1. Setting Up Your Environment

Before starting, set up your virtual environment and install Flask:

1
2
3
4
5
6
7
python -m venv myenv

# For Mac
source myenv/bin/activate

#Install fastapi
pip install fastapi

2. Creating a Simple Flask Application

When you send a POST request to the /login endpoint with a username and password parameter, the server will check if the credentials are valid. If they are, the logger records the event using logger.info() to signify a successful login attempt. However, if the credentials are invalid, the logger records the event as a failed login attempt using logger.error().

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#Making Imports
from fastapi import FastAPI, request
import logging
import os

# Initialize the Fastapi app
app = Flask(__name__)
app = FastAPI()


# Configure logging
if not os.path.exists('logs'):
    os.makedirs('logs')
log_file = 'logs/app.log'
logging.basicConfig(filename=log_file, level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
log = logging.getLogger(__name__)


# Define route and handler
@app.get('/login')
def login():
    log.info('Received login request')
    username = request.form['username']
    password = request.form['password']
    if username == 'admin' and password == 'password':
        log.info('Login successful')
        return 'Welcome, admin!'
    else:
        log.error('Invalid credentials')
        return 'Invalid username or password', 401

if __name__ == '__main__':
    app.run(debug=True)

3. Testing the Application

To test the application, run the Python script and access the /login endpoint using a web browser or a tool like curl. For example:

Test Case 01

1
 curl -X POST -d "username=admin&password=password" http://localhost:5000/login

Output

1
Welcome, admin!

Test Case 02

1
curl -X POST -d "username=admin&password=wrongpassword" http://localhost:5000/login

Output

1
Invalid username or password

app.log

1
2
3
4
5
6
2024-05-18 12:36:56,845 - INFO - Received login request
2024-05-18 12:36:56,846 - INFO - Login successful
2024-05-18 12:36:56,847 - INFO - 127.0.0.1 - - [18/May/2024 12:36:56] "POST /login HTTP/1.1" 200 -
2024-05-18 12:37:00,960 - INFO - Received login request
2024-05-18 12:37:00,960 - ERROR - Invalid credentials
2024-05-18 12:37:00,960 - INFO - 127.0.0.1 - - [18/May/2024 12:37:00] "POST /login HTTP/1.1" 200 -
This post is licensed under CC BY 4.0 by the author.