Setup a python logging configuration with dictConfig
Logging configuration can be defined on different ways like a dict, ini file, yaml or json somethimes is more flexible to do it on code with python, all depends on the use case.
This small example show how to setup the logging configuration using dictConfig
method and how to add an user defined object to the logging filter.
import os
import logging
import socket
from flask import Flask
from logging.config import dictConfig
class ContextFilter(logging.Filter):
hostname = socket.gethostname()
def filter(self, record):
record.hostname = ContextFilter.hostname
return True
logging_configuration = dict(
version=1,
disable_existing_loggers=False,
formatters={
"default": {"format": "[%(hostname)s %(asctime)s] %(levelname)s in %(module)s: %(message)s"},
},
filters={"hostname_filter": {"()": ContextFilter}},
handlers={
"console": {
"class": "logging.StreamHandler",
"formatter": "default",
"filters": ["hostname_filter"],
}
},
root={"handlers": ["console"], "level": os.getenv("LOG_LEVEL", "INFO")},
)
dictConfig(logging_configuration)
app = Flask(__name__)
logger = logging.getLogger(__name__)
@app.route("/")
def home():
logger.debug("debug message")
logger.info("info message")
logger.warning("warning message")
logger.error("error message")
logger.critical("critical error message")
return "Hello World"
if __name__ == "__main__":
app.run()
The filter hostname_filter
use the special key "()"
which means that user-defined instantiation is wanted. ContextFilter
subclass logging.Filter
and overrides the filter
method so when key hostname
is found it will get his value from the ContextFilter
class using socket.gethostname()
and the application output will show:
# running the flask app inside the virtualenv
(.venv) $ flask run
* Environment: developement
* Debug mode: off
[test.lab 2019-05-27 18:20:05,193] INFO in _internal: * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
[test.lab 2019-05-27 18:20:08,437] DEBUG in app: debug message
[test.lab 2019-05-27 18:20:08,437] INFO in app: info message
[test.lab 2019-05-27 18:20:08,437] WARNING in app: warning message
[test.lab 2019-05-27 18:20:08,437] ERROR in app: error message
[test.lab 2019-05-27 18:20:08,437] CRITICAL in app: critical error message
[test.lab 2019-05-27 18:20:08,438] INFO in _internal: 127.0.0.1 - - [27/May/2019 18:20:08] "GET / HTTP/1.1" 200 -
# default formatter: "[%(hostname)s %(asctime)s] %(levelname)s in %(module)s: %(message)s"
reference: Python logging - user-defined-objects