Flask: Ability to disable Flasks internal logger

Created on 27 Feb 2015  路  9Comments  路  Source: pallets/flask

Hi, I need to be able to disable flasks internal logger as I have implemented my own within my application that utilises Flask.

I would like this ability whether I am in debug mode or not.

TAI

Most helpful comment

Had similar issue, and created a decorator for this...

import logging
from functools import partial, wraps
from flask import request


class HealthCheckFilter(logging.Filter):
    """Filter for logging output"""

    def __init__(self, path, name=''):
        """Class constructor.
        We pass 'path' argument to instance  which is
        used by to filter logging for Flask routes.
        """
        self.path = path
        super().__init__(name)

    def filter(self, record):
        """Main filter function.
        We add a space after path here to ensure subpaths
        are not unintentionally excluded from logging"""
        return f"{self.path} " not in record.getMessage()


def disable_logging(func=None, *args, **kwargs):
    """Disable log messages for werkzeug log handler
    for a specific Flask routes.

    :param (function) func: wrapped function
    :param (list) args: decorator arguments
    :param (dict) kwargs: decorator keyword arguments
    :return (function) wrapped function
    """
    _logger = 'werkzeug'
    if not func:
        return partial(disable_logging, *args, **kwargs)

    @wraps(func)
    def wrapper(*args, **kwargs):
        path = request.environ['PATH_INFO']
        log = logging.getLogger(_logger)
        log.addFilter(HealthCheckFilter(path))
        return func(*args, **kwargs)
    return wrapper

Usage:

@disable_logging
def health():
    return {'status': 'ok'}

All 9 comments

Hi @geekscrapy, are you talking about the HTTP request logs? For example the logs that are in the format:

127.0.0.1 - - [28/Feb/2015 01:15:17] "POST /post/ HTTP/1.1" 200 -

If so, my understanding is that this is a part of Werkzeug, but you can change logging settings, see here: http://stackoverflow.com/questions/14888799/disable-console-messages-in-flask-server

Thanks @keyanp, but I was after stopping the Werkzeug/Flask logger from even initialising as it tries to bind to the same port as my current logger (insert big error msg here!).

This is kinda what I mean. Is it correct? https://www.snip2code.com/Snippet/84701/Really-disable-logger-logging-in-Flask

Even better would be to redirect these logs to my own logger...

@geekscrapy, I don't understand why that code snippet has cf.logging.getLogger if you remove the cf. it will work fine. I tried it out with a bare app successfully: https://gist.github.com/keyanp/c163b7b01ed6aa0f9ccf

I hope that answers your question, but regardless, this is not an issue with Flask. Please direct such questions to the irc channel or stackoverflow.

To be honest, not really :) I was after a way to stop Flask/Werkzeug (since they both have a logger instance no?) initialising a logger instance. Started question on SO

I ended up here via a Google search. Unfortunately Werkzeug's log format is hard-coded, but you can monkey-patch the function if you're really keen, eg:

    werkzeug_logger = logging.getLogger('werkzeug')

    # Override the built-in werkzeug logging function in order to change the log line format.
    from werkzeug.serving import WSGIRequestHandler
    WSGIRequestHandler.log = lambda self, type, message, *args: \
        getattr(werkzeug_logger, type)('%s %s' % (self.address_string(), message % args))

i resolved this by redirecting the 'werkzeug' log to another log file. At the top of 'app.py', here is:

from logging.handlers import RotatingFileHandler
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger('werkzeug')
handler = RotatingFileHandler('access.log', maxBytes=10000, backupCount=1)

but it's still outputting to console, and then i fixed it by redirecting to /dev/null with bash.

python app.py &> /dev/null 

The issue seems to be during the initialisation of werkzeug which create the handler.

Best solution I found so far:

@app.before_first_request
def ensure_spe_logging():
    print 'Ensure logger'
    for l, v in logging.Logger.manager.loggerDict.iteritems():
        v.handlers = [handler]

Which remove (here replace) the werkzeug handler before first requests.

Had similar issue, and created a decorator for this...

import logging
from functools import partial, wraps
from flask import request


class HealthCheckFilter(logging.Filter):
    """Filter for logging output"""

    def __init__(self, path, name=''):
        """Class constructor.
        We pass 'path' argument to instance  which is
        used by to filter logging for Flask routes.
        """
        self.path = path
        super().__init__(name)

    def filter(self, record):
        """Main filter function.
        We add a space after path here to ensure subpaths
        are not unintentionally excluded from logging"""
        return f"{self.path} " not in record.getMessage()


def disable_logging(func=None, *args, **kwargs):
    """Disable log messages for werkzeug log handler
    for a specific Flask routes.

    :param (function) func: wrapped function
    :param (list) args: decorator arguments
    :param (dict) kwargs: decorator keyword arguments
    :return (function) wrapped function
    """
    _logger = 'werkzeug'
    if not func:
        return partial(disable_logging, *args, **kwargs)

    @wraps(func)
    def wrapper(*args, **kwargs):
        path = request.environ['PATH_INFO']
        log = logging.getLogger(_logger)
        log.addFilter(HealthCheckFilter(path))
        return func(*args, **kwargs)
    return wrapper

Usage:

@disable_logging
def health():
    return {'status': 'ok'}

@etos This is EXACTLY what I needed, thank you! Have you considered contributing this back to flask core? Seems like such a decorator ought to be part of the base code.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

greyli picture greyli  路  3Comments

davidism picture davidism  路  3Comments

maangulo12 picture maangulo12  路  4Comments

sungjinp11 picture sungjinp11  路  3Comments

stillesjo picture stillesjo  路  4Comments