Flask logging - Cannot get it to write to a file
Solution 1
Why not do it like this:
if __name__ == '__main__':
init_db() # or whatever you need to do
import logging
logging.basicConfig(filename='error.log',level=logging.DEBUG)
app.run(host="0.0.0.0")
If you now start you application, you'll see that error.log contains:
INFO:werkzeug: * Running on http://0.0.0.0:5000/
For more info, visit http://docs.python.org/2/howto/logging.html
Okay, as you insist that you cannot have two handler with the method I showed you, I'll add an example that makes this quite clear. First, add this logging code to your main:
import logging, logging.config, yaml
logging.config.dictConfig(yaml.load(open('logging.conf')))
Now also add some debug code, so that we see that our setup works:
logfile = logging.getLogger('file')
logconsole = logging.getLogger('console')
logfile.debug("Debug FILE")
logconsole.debug("Debug CONSOLE")
All what is left is the "logging.conf" program. Let's use that:
version: 1
formatters:
hiformat:
format: 'HI %(asctime)s - %(name)s - %(levelname)s - %(message)s'
simple:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: hiformat
stream: ext://sys.stdout
file:
class: logging.FileHandler
level: DEBUG
formatter: simple
filename: errors.log
loggers:
console:
level: DEBUG
handlers: [console]
propagate: no
file:
level: DEBUG
handlers: [file]
propagate: no
root:
level: DEBUG
handlers: [console,file]
This config is more complicated than needed, but it also shows some features of the logging module.
Now, when we run our application, we see this output (werkzeug- and console-logger):
HI 2013-07-22 16:36:13,475 - console - DEBUG - Debug CONSOLE
HI 2013-07-22 16:36:13,477 - werkzeug - INFO - * Running on http://0.0.0.0:5000/
Also note that the custom formatter with the "HI" was used.
Now look at the "errors.log" file. It contains:
2013-07-22 16:36:13,475 - file - DEBUG - Debug FILE
2013-07-22 16:36:13,477 - werkzeug - INFO - * Running on http://0.0.0.0:5000/
Solution 2
Ok, my failure stemmed from two misconceptions:
1) Flask will apparently ignore all your custom logging unless it is running in production mode
2) debug=False is not enough to let it run in production mode. You have to wrap the app in any sort of WSGI server to do so
After i started the app from gevent's WSGI server (and moving logging initialization to a more appropriate place) everything seems to work fine
Solution 3
The output you see in the console of your app is from the underlying Werkzeug logger that can be accessed through logging.getLogger('werkzeug').
Your logging can function in both development and release by also adding handlers to that logger as well as the Flask one.
More information and example code: Write Flask Requests to an Access Log.
Solution 4
This works:
if __name__ == '__main__':
import logging
logFormatStr = '[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s'
logging.basicConfig(format = logFormatStr, filename = "global.log", level=logging.DEBUG)
formatter = logging.Formatter(logFormatStr,'%m-%d %H:%M:%S')
fileHandler = logging.FileHandler("summary.log")
fileHandler.setLevel(logging.DEBUG)
fileHandler.setFormatter(formatter)
streamHandler = logging.StreamHandler()
streamHandler.setLevel(logging.DEBUG)
streamHandler.setFormatter(formatter)
app.logger.addHandler(fileHandler)
app.logger.addHandler(streamHandler)
app.logger.info("Logging is set up.")
app.run(host='0.0.0.0', port=8000, threaded=True)
Solution 5
I didn't like the other answers so I kept at it and it seems like I had to make my logging config AFTER Flask did it's own setup.
@app.before_first_request
def initialize():
logger = logging.getLogger("your_package_name")
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter(
"""%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n%(message)s"""
)
ch.setFormatter(formatter)
logger.addHandler(ch)
My app is structured like
/package_name
__main__.py <- where I put my logging configuration
__init__.py <- conveniance for myself, not necessary
/tests
/package_name <- Actual flask app
__init__.py
/views
/static
/templates
/lib
Following these directions http://flask.pocoo.org/docs/0.10/patterns/packages/
fleshgolem
Updated on August 01, 2020Comments
-
fleshgolem almost 4 years
Ok, here's the code where I setup everything:
if __name__ == '__main__': app.debug = False applogger = app.logger file_handler = FileHandler("error.log") file_handler.setLevel(logging.DEBUG) applogger.setLevel(logging.DEBUG) applogger.addHandler(file_handler) app.run(host='0.0.0.0')
What happens is
- error.log gets created
- Nothing is ever written to it
- Despite not adding a StreamHandler and setting debug to false I still get everything to STDOUT (this might be correct, but still seems weird)
Am I totally off here somewhere or what is happening?