Python Flask
Logging
▌Introduction
We are going to apply logging to
Flask app.
The loggers will include:
1. Application-level
logger
2. Custom
logger
▋Related articles
▌Environment
▋Python 3.6.5
▋Flask 1.0.2
▋Flask-SocketIO 3.1.2
▋Socket.IO 2.2.0
▋Vue.js 2.5.21
▋Vue-Socket.io 3.0.4
▌Implement
▋Create logger and its handlers
▋Logger object
Loggers are never instantiated directly.
The proper way is get/create it by using module-level
function: logging.getLogger(name).
Multiple calls to getLogger() with the same name
will always return a reference to the
same Logger object.
import logging
my_logger =
logging.getLogger("myLoggerName")
▋File handler
logging_format
= logging.Formatter('%(asctime)s - %(thread)s - %(levelname)s - %(module)s.%(funcName)s(%(filename)s,
%(lineno)s) - %(message)s')
logfiles_path =
os.path.join(os.path.dirname(os.path.dirname(__file__)), "logs"))
handler = logging.FileHandler('{0}\\mylog.log'.format(logfiles_path),
encoding='UTF-8')
handler.setLevel(logging.DEBUG) # Set
handler's log level
handler.setFormatter(logging_format)
# Set format
my_logger.addHandler(handler)
The above code created a logging.FileHandler
object which was set log level and format.
Then we can add the handler to our logger.
Here are the log levels and their representative numeric
value.
In the example, the handler will deal with the logs
with levels whose numeric value are equals or higher than “DEBUG”.
Level
|
Numeric
value
|
CRITICAL
|
50
|
ERROR
|
40
|
WARNING
|
30
|
INFO
|
20
|
DEBUG
|
10
|
NOTSET
|
0
|
(Reference: Logging
Levels)
For logger, we can set the log level as well like
following.
The logs with non-scoped levels will be ignored.
my_ogger.setLevel(logging.INFO)
▋Start logging
my_logger.debug("[Debug]..")
my_logger.info("[INFO]...")
my_logger.warning("[WARNING]...")
my_logger.error("[ERROR]...")
my_logger.critical("[CRITICAL]...")
▋Result
The logs will be keeped in to logs/mylog.log
And the logs,
2019-01-27 12:13:08,750 - 13660 - DEBUG -
main.<module>(main.py, 35) - [Debug]..
2019-01-27 12:13:08,750 - 13660 - INFO -
main.<module>(main.py, 36) - [INFO]...
2019-01-27 12:13:08,750 - 13660 - WARNING -
main.<module>(main.py, 37) - [WARNING]...
2019-01-27 12:13:08,751 - 13660 - ERROR -
main.<module>(main.py, 38) - [ERROR]...
2019-01-27 12:13:08,751 - 13660 - CRITICAL -
main.<module>(main.py, 39) - [CRITICAL]...
▋(Optional) Create a module to add handlers for logger
Since we can have multiple file
handers to handle different levels, formatted logs.
Here is an sample code for
writing a module for this,
▋logger_config.py
import sys
import os
import logging
from datetime import date
def
init_logging(logger, min_logging_level):
# Add DEBUG
handler
add_handler(logger, logging.DEBUG)
# Add ERROR
handler
add_handler(logger, logging.ERROR)
# Set level for this logger
logger.setLevel(min_logging_level)
def
add_handler(logger:logging.Logger, level):
level_name = logging.getLevelName(level).lower()
logging_format = logging.Formatter('[%(asctime)s][%(thread)s][%(levelname)s][%(module)s.%(funcName)s(%(filename)s,
%(lineno)s)]%(message)s')
logfiles_path =
os.path.join(os.path.dirname(os.path.dirname(__file__)), "logs",
str(date.today()))
create_log_dir(logfiles_path)
handler
= logging.FileHandler('{0}\\mylog.{1}.log'.format(logfiles_path,
level_name), encoding='UTF-8')
handler.setLevel(level) # Set
handler's log level
handler.setFormatter(logging_format) # Set format
logger.addHandler(handler)
def
create_log_dir(directory):
if not
os.path.exists(directory):
os.makedirs(directory)
So when I call the init_logging method, the
application will stores the logs as:
logs/2019-01-27/mylog.bug.log
logs/2019-01-27/mylog.error.log
▋Flask application logger
Flask uses standard Python
logging.
We can get the Flask application-level logger by app.logger
as following,
from flask import Flask,
render_template, request, jsonify
from
modules.logger_config import init_logging
app = Flask(__name__)
init_logging(app.logger, logging.DEBUG)
and logs like this,
app.logger.error("[ERROR]...")
Notice
that the app.logger’s logs will also be shown on the console window.
So if you don’t want to show the Flask app.logger’s logs
on console, you can disable it by
setting the log levels to a number greater than 50 (CRITICAL) :
app.logger.setLevel(100)
▋Sample code
▌Reference