Flask logging setup

dictConfig, user defined object

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:

[Read More]