How do I write Flask's excellent debug log message to a file in production?

Ben :

I have a Flask application that works well and produces an occasional error, which is visible when it is running with debug=True:

if __name__ == '__main__':
    app.run(debug=True)

I get useful error messages such as:

Traceback (most recent call last):
  File "./main.py", line 871, in index_route

KeyError: 'stateIIIII'

I would like to get error messages like these saved to a file when I run the application in production (using Lighttpd + fastcgi).

After looking at various StackOverflow questions (http://flask.pocoo.org/docs/errorhandling/, http://docs.python.org/2/library/logging.html, etc.); the Flask mailing list; and a few blogs, it seems there is no easy way just to send all the great error messages to a file - I need to use the Python logging module to customise things. So I came up with the following code.

At the top of my application file I have various imports followed by:

app = Flask(__name__)

if app.debug is not True:   
    import logging
    from logging.handlers import RotatingFileHandler
    file_handler = RotatingFileHandler('python.log', maxBytes=1024 * 1024 * 100, backupCount=20)
    file_handler.setLevel(logging.ERROR)
    app.logger.setLevel(logging.ERROR)
    app.logger.addHandler(file_handler)

I have then put the code for each route in a try/except statement and use traceback to work out which line the error came from and print a nice error message:

def some_route():
    try:
        # code for route in here (including a return statement)

    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        app.logger.error(traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2))
        return render_template('error.html')

And then right at the end of the file I remove the debug=True statement. Though I don't think I need to do that as the application is being run by a fastcgi server(?) when it is run in production. The last two lines of my application code look like this:

if __name__ == '__main__':
    app.run()

I am struggling to get this working. I think the best I have managed is to get a single error log message to be saved in the file using (app.logger.error('test message') ), but it only prints that one message. An attempt to log another error directly after that one is simply ignored.

codecool :

I don't know why it's not working but I can tell how am doing this.

First of all, you don't need to set the level of app.logger. So remove this line app.logger.setLevel().

You want to save exception and return error page for every view. It is a lot of work to write this code everywhere. Flask provides a method to do this. Define an errorhandler method like this.

    @app.errorhandler(500)
    def internal_error(exception):
        app.logger.error(exception)
        return render_template('500.html'), 500

Whenever a view raises an exception, this method will be called and passed the exception as argument. Python logging provides exception method that is used to save full traceback of the exception.

Since this handles all exception, you don't even need to put code in try/except block. Though, if you want to do something before calling the errorhandler(for e.g. rollback session or transaction) then do this:

    try:
        #code
    except:
        #code
        raise

If you would like the date and time added for each entry in your log file, the following code can be used (in place of the similar code featured in the question).

if app.debug is not True:   
    import logging
    from logging.handlers import RotatingFileHandler
    file_handler = RotatingFileHandler('python.log', maxBytes=1024 * 1024 * 100, backupCount=20)
    file_handler.setLevel(logging.ERROR)
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    file_handler.setFormatter(formatter)
    app.logger.addHandler(file_handler)

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How do I write a message timestamp to a log file?

log4perl: How to write ERROR message to file and DEBUG message to stderr?

How do I display this Log message in the Debug area using Xcode9?

With DEBUG=False, how can I log django exceptions to a log file

How do I disable PHP's file read/write buffers?

Flask - how to write werkzeug logs to log file using RotatingFileHandler?

How do I write outputs to the Log in Android?

How to write a message to log file or console using extension method

How to always write log message to file regardless of level setting

How do I write a Java text file viewer for big log files

How do I write error info in a separate file using log4j

How do I debug crashes with the message "outlined copy of Optional"?

What is a debug.log file and how can I get rid of it?

How do I log a Python error with debug information?

How to write log to file

how do I get the type of the file in flask?

I'm trying to "teach" myself flask, how do I write the information submitted in the html form box to a local file?

which log file or how do I locate this log file?

How do I return an error message in Flask-resful?

How can I make a dockerized Flask app write output to file?

How do I fetch lines in a log file

How do i Empty log file on here?

How do I write a DOM Document to File?

How do I write xPath for the XML file

How do I write image to file?

How do I write to a file in Kotlin?

How do I write a formatted string to a file?

How do I write an automake file for CxxTest?

How do I create a file and write to it in Java?