Prevent Flask from double logging when running in console

Question:

I’m using Python Flask and Connexion to create a REST API. It’s hard to figure out how logging is working with using these two libraries, and I’ve run in to a strange issue with double logging when trying to run/debug locally.

app/log.py

import logging
from flask import g, has_request_context
import uuid

def request_id():
    if 'request_id' not in g:
        g.request_id = uuid.uuid4()

    return g.request_id

class AppFilter(logging.Filter):
    def filter(self, record):
        record.request_id = request_id() if has_request_context() else 'app'
        return True

formatter = logging.Formatter('%(asctime)s %(request_id)s %(module)s:%(levelname)s %(message)s')
handler = logging.StreamHandler()
handler.setFormatter(formatter)
handler.addFilter(AppFilter())

main.py

import connexion
from config import config
import json
import logging
from app.log import handler

# initiate swagger/connexion
application = connexion.App(__name__, specification_dir='./')
application.add_api('swagger.yml')

# logging
application.app.logger.handlers.pop() 
application.app.logger.addHandler(handler)
application.app.logger.setLevel(logging.DEBUG)
application.app.logger.debug('application starting...')

# if we're running in standalone mode, run the application
if __name__ == '__main__':
    application.run(host='0.0.0.0', port=5000)

The above code lets me use a custom log format whereby each request gets a UUID for the duration of the requests. Whilst this works, I can not figure out how to stop double logging. As you can see in main.py I pop the (only) handler and add my own, and when I print the handlers to the console there is only one – the one I add.

This works, but after a certain number of messages it just starts double logging:

2019-10-17 10:00:22,737 09031bdb-5105-4b73-9e7d-a609f42a471e inbound:application starting...
2019-10-17 10:00:22,747 09031bdb-5105-4b73-9e7d-a609f42a471e inbound:INFO inbound
2019-10-17 10:00:22,755 09031bdb-5105-4b73-9e7d-a609f42a471e config:DEBUG Cache miss: 90002
2019-10-17 10:00:22,755 09031bdb-5105-4b73-9e7d-a609f42a471e firewall:DEBUG Connecting to x
2019-10-17 10:00:22,861 09031bdb-5105-4b73-9e7d-a609f42a471e firewall:DEBUG Get x for "90002"
2019-10-17 10:00:23,062 09031bdb-5105-4b73-9e7d-a609f42a471e firewall:DEBUG interfaces: source=v1 dest=v2
DEBUG:flask.app:interfaces: source=v1 dest=v2
2019-10-17 10:00:23,062 09031bdb-5105-4b73-9e7d-a609f42a471e firewall:DEBUG Found matching policy: 980cf552-5aaf-51e9-6c39-6480d51af2ad
DEBUG:flask.app:Found matching policy: 980cf552-5aaf-51e9-6c39-6480d51af2ad
2019-10-17 10:00:23,062 09031bdb-5105-4b73-9e7d-a609f42a471e firewall:DEBUG Found matching policy: eff53daa-b4f6-51e9-b79f-25b26b9f8537
DEBUG:flask.app:Found matching policy: eff53daa-b4f6-51e9-b79f-25b26b9f8537

As if the handler has been added back in. I’m not sure if the handler is being re-added, or if I’m going about this the wrong way.

Here’s how I am logging throughout the app, example:

inbound.py

from flask import request, current_app

def index():
    current_app.logger.info('inbound')
    # do stuff....

Asked By: Dan Walker

||

Answers:

Use

application.app.logger.handlers.clear()

instead of

application.app.logger.handlers.pop()
Answered By: Kevin Martins

I had the same issue. It was because the app was logging before the logging was configured. If you can configure logging before app is created then good, else do not log before configuring logging.

If using factory patter configure logging before create_app is called.

Answered By: codeomascot
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.