Computer scienceBackendFlaskAdvanced application configuration

Logging

9 minutes read

In this topic, we will discuss the way we log our data. It's a good thing to know because some errors are difficult to track down just by looking at the code. Provided that you have a log of all queries and their results (code and decryption), it takes no pain to do it. Let's start!

Simple logging

First things first — we need to create an application that stores our requests. For this, we need to import the necessary objects:

from flask import request
from flask import make_response
from flask import Flask
import datetime as dt

We also import the datetime module. It allows us to get the current time and date. Next, let's create a function that will log our information to a .txt file:

def log(*args):
    text = ' '.join([str(element) for element in args])
    with open('log.txt', 'a') as log_file:
        log_file.write(text + '\n')

We refer to *args here to store an unlimited number of positional arguments to the args variable (yes, args is the variable name, and we can change it to any other). We will use it as a container for all information we want to log. Of course, we can log data directly in the view function, but using a separate function is considered good coding practice. The next step is familiar to us: we need to create a standard web application:

app = Flask('main')

@app.route('/no-content')
def no_data():
    response = make_response('Hello there!', 204)
    return response

@app.route('/some-content')
def data():
    response = make_response('Hello there! There are data!', 200)
    return response

We've defined two view functions, and now, it's time for something new! Let's create a function that will log every request that our server receives. We can do this by using the decorator @app.after_request. As the name indicates, the following function is executed after every request. This is a neat device if we need to create a callback function. There are more decorators like this, such as @app.before_request and @app.before_first_request. You can find them in the Official documentation.

@app.after_request
def after_request(response):
    log(dt.datetime.now(), 
        request.remote_addr, 
        request.method, 
        request.scheme, 
        request.full_path, 
        response.status
    )

    return response

This function receives the response and transfers its content to the log function:

remote_addr

Displays the client remote address

method

Displays a request method

scheme

Shows a request HTTP scheme

full_path

Shows full URL to a certain web app or site

status

Shows the request status code

This information is passed to the log function and to the log file!

To see that it works, let's start our app and make requests to it. In the console, the server displays the requests in the following form:

server displays requests

If we open log.txt, we will find a lot of different requests there. You can configure logging by adjusting the log function:

adjusting the log function

Our logging works! We've created a function to store the records of our server. There are also more advanced ways to logging. Let's figure them out!

Advanced logging

In this part of the topic, we will talk about a very cool module called logging. It can log our information quickly and conveniently — we need to write one code line; it will log whatever we want! First, we need to understand the urgency hierarchy. There are 5 urgency levels: DEBUG, INFO, WARNING, ERROR, and CRITICAL. The CRITICAL messages are of most importance, while DEBUG is less important. We import the logging library and configure the logging options:

import logging

logging.basicConfig(filename='app.txt', level=logging.DEBUG)

We've specified the filename of the log file and the logging level. Now, we are ready to log!

logging.info('This is just information message')
logging.warning('This is some warning message')
logging.error('This is quite severe message')
logging.critical('This is a very severe message. Please, take some actions')

When we open the file, we will see something like this:

filename of the log file

We can log any information we need just by selecting different urgency levels. Depending on the task, you can log only the most important notifications, or, for example, errors for debugging or info messages for checking whether the information has reached the users and processed, and so on.

Conclusion

In this topic, we've discussed basic and advanced logging. We can now effectively receive and save messages, requests, errors, and many more. Good luck with your study!

15 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo