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
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.
Most helpful comment
Had similar issue, and created a decorator for this...
Usage: