Skill - Logging in python flask applications
Skills Required
- Setup python development environment
- Basic Printing in Python
- Managing Variables in python
- Logging in Python
Please make sure to have all the skills mentioned above to understand and execute the code mentioned below. Go through the above skills if necessary for reference or revision
In this post we will learn how to customize logging in python flask applications
- Logging is very important in web applications
- Flask applications use standard python logging module
- Flask logger can be to create application logs instead of using a separate logger object
Basic logging in flask
- Configure the root logger before creating the flask application, this is because, while instantiating a flask web application, the handlers of the root logger will be copied by the flask logger
from flask import Flask
import logging
# One line configuration like this can also be used
# logging.basicConfig(filename="logs.log", format="%(levelname)s:%(name)s:%(message)s")
# get the root logger
logger = logging.getLogger()
# create a formatter object
logFormatter = logging.Formatter("%(levelname)s:%(name)s:%(message)s")
# add console handler to the root logger
consoleHanlder = logging.StreamHandler()
consoleHanlder.setFormatter(logFormatter)
logger.addHandler(consoleHanlder)
# add file handler to the root logger
fileHandler = logging.FileHandler("logs.log")
fileHandler.setFormatter(logFormatter)
logger.addHandler(fileHandler)
# create flask application
app = Flask(__name__)
@app.route("/")
def hello():
# using logger inside the route handler
app.logger.info("This is from a route handler...")
return "Hello World!!!"
# run the flask application
app.run(host="0.0.0.0", port=50100, debug=True)
Inject contextual information into logs using custom log formatter
from flask import has_request_context, request, Flask
import logging
# using custom formatter to inject contextual data into logging
class RequestFormatter(logging.Formatter):
def format(self, record):
if has_request_context():
record.url = request.url
record.remote_addr = request.remote_addr
else:
record.url = None
record.remote_addr = None
return super().format(record)
formatter = RequestFormatter(
'[%(asctime)s] %(remote_addr)s requested %(url)s\n'
'%(levelname)s in %(module)s: %(message)s'
)
logger = logging.getLogger()
consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(formatter)
logger.addHandler(consoleHandler)
app = Flask(__name__)
@app.route("/")
def home():
app.logger.info("Calling from request handler...")
return "Hello World!!!"
app.run(host="0.0.0.0", port=50100, debug=True)
- In the above example, a custom formatter is used to inject request related data into the logs
- Notice that the method
has_request_context
is used to know whether the flask application context is setup while logging. This way, the formatter can be aware of the presence of a flask request
access app logger inside blueprints or extensions using current_app
- The flask application variable may not be available in the blueprints or extensions python files
- The app variable can be accessed in such cases using the
current_app
variable from flask as shown below - Note that the
current_app
variable can be available only in the context of a request
# this is an example blueprint python file
from flask import Blueprint, current_app
api = Blueprint('codes')
@api.route("/info")
def api_route1():
current_app.logger.info("called from api route method1 inside blueprint")
return "Hello World!!!"
Video
The video for this post can be seen here
References
- Flask logging documentation - https://flask.palletsprojects.com/en/2.2.x/logging/
- logging cookbook - https://docs.python.org/3/howto/logging-cookbook.html#using-loggeradapters-to-impart-contextual-information
- Official documentation - https://docs.python.org/3/library/logging.html
- Access flask logger inside blueprint - https://stackoverflow.com/questions/16994174/in-flask-how-to-access-app-logger-within-blueprint
Comments
Post a Comment