How to setup custom logging in Python|Flask with dictConf?

Logging is a very important feature and requirement while we are working on any type of project, either small or large. Because with the help of log messages, we could identify the issue in running applications and could solve it with less effort.

Python came up with the default logging module that we could use to implement logging in python applications such as core python project/ flask project etc. 

For example:

import logging
logger = logging.getLogger(testproject) or logger = logging.getLogger()

logger.info(‘This is info level message’)
logger.error(‘This is error level message’)
logger.warning(‘This is warning level message’)
logger.debug(‘This is debug level message’)

But sometimes, we need custom implementations:

  • Such as, instead of writing messages on console, we want to write messages on logging files.
  • Might need to log additional information to each log file
  • Might need to file rotation of logs file
  • Might need to apply custom filter etc.

So, here I am sharing, like how we can achieve the above points within the Flask project.

Let’s suppose your project structure is:

  • Project-Folder
    • app
      • __init__.py
    • moduleA
    • moduleB
    • config
      • __init__.py
      • default.py
      • deployment.py
      • production.py
    • Instance
      • default.py
      • development.py
    • main.py
    • uwsgi.py
    • Requirments.txt
    • gitignore

Step 1: Let’s create a logger_mod.py file under your project root folder.

  • Project-Folder
    • logger_mod.py

Step 2: Define your custom filter that will add additional information to each log.

class CustomFilter(logging.Filter):

    def filter(self, record):
        record.appName = 'my-application-name'
        return True

Step 3: Define your logging dictConfig structure

logging_configuration = {
    'version': 1,
    "disable_existing_loggers": False,
    'formatters': {
        'default': {
            'format': '[%(asctime)s] %(levelname)s - APP:%(appName)s - MODULE:%(module)s - FUNCTION:%(funcName)s - LINE:%(lineno)d : %(message)s',
        }
    },
    'filters': {
        'additional': {
            '()': CustomFilter
        }
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'default',
            'level': 'INFO',
            'stream': 'ext://sys.stdout'
        },
        "info_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "formatter": "default",
            "filename": app.config['APPLICATION_LOG_PATH'] + "/info.log",
            "maxBytes": 10000,
            "backupCount": 10,
            "delay": "True",
            'level': 'INFO',
        },
        "error_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "formatter": "default",
            "filename": app.config['APPLICATION_LOG_PATH'] + "/error.log",
            "maxBytes": 10000,
            "backupCount": 10,
            "delay": "True",
            'level': 'ERROR',
        }
    },
    'loggers': {
        'testProject': {
            'handlers': ['console',  'info_file', 'error_file'],
            'level': 'INFO',
            'filters': ['additional'],
            'propagate': False
        }
    }
}

Step 4: Configure custom logging to project

def setup_logging():
    # Create a logs folder if it does not exist.
    if not os.path.exists(app.config['APPLICATION_LOG_PATH']):
        os.makedirs(app.config['APPLICATION_LOG_PATH'])

    dictConfig(logging_configuration)

    # Disable flask internal logger.
    logging.getLogger('werkzeug').disabled = True

Step 4: Apply custom logging to the project. Flask main.py file as above structure.

import os
# Set configuration environment variable, to load defined config.
os.environ['APP_CONFIG_FILE'] = 'development.py'

from app import app as application
from logging_setup import setup_logging


if __name__ == "__main__":
    setup_logging()
    application.run(debug=True, host='0.0.0.0', port=5000)

Final code that you need to apply as file wise:

#### logger_mod.py

import os
import logging

from logging.config import dictConfig
from app import app

class CustomFilter(logging.Filter):

    def filter(self, record):
        record.appName = 'my-application-name'
        return True

logging_configuration = {
    'version': 1,
    "disable_existing_loggers": False,
    'formatters': {
        'default': {
            'format': '[%(asctime)s] %(levelname)s - APP:%(appName)s - MODULE:%(module)s - FUNCTION:%(funcName)s - LINE:%(lineno)d : %(message)s',
        }
    },
    'filters': {
        'additional': {
            '()': CustomFilter
        }
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'default',
            'level': 'INFO',
            'stream': 'ext://sys.stdout'
        },
        "info_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "formatter": "default",
            "filename": app.config['APPLICATION_LOG_PATH'] + "/info.log",
            "maxBytes": 10000,
            "backupCount": 10,
            "delay": "True",
            'level': 'INFO',
        },
        "error_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "formatter": "default",
            "filename": app.config['APPLICATION_LOG_PATH'] + "/error.log",
            "maxBytes": 10000,
            "backupCount": 10,
            "delay": "True",
            'level': 'ERROR',
        }
    },
    'loggers': {
        'testProject': {
            'handlers': ['console',  'info_file', 'error_file'],
            'level': 'INFO',
            'filters': ['additional'],
            'propagate': False
        }
    }
}



def setup_logging():
    # Create logs folder if does not exist.
    if not os.path.exists(app.config['APPLICATION_LOG_PATH']):
        os.makedirs(app.config['APPLICATION_LOG_PATH'])

    dictConfig(logging_configuration)

    # Disable flask internal logger.
    logging.getLogger('werkzeug').disabled = True


#### main.py
import os
# Set configuration environment variable, to load defined config.
os.environ['APP_CONFIG_FILE'] = 'development.py'

from app import app as application
from logging_setup import setup_logging


if __name__ == "__main__":
    setup_logging()
    application.run(debug=True, host='0.0.0.0', port=5000)

### test.py
import logging
logger = logging.getLogger('testProject')

logger.info(‘This is info level message’)
logger.error(‘This is error level message’)


How to setup custom logging in Python|Flask with dictConf?
Show Buttons
Hide Buttons