Logging

Flask uses standard Pythonlogging. Messages about your Flaskapplication are logged withapp.logger,which takes the same name asapp.name. Thislogger can also be used to log your own messages.

@app.route('/login',methods=['POST'])deflogin():user=get_user(request.form['username'])ifuser.check_password(request.form['password']):login_user(user)app.logger.info('%s logged in successfully',user.username)returnredirect(url_for('index'))else:app.logger.info('%s failed to log in',user.username)abort(401)

If you don’t configure logging, Python’s default log level is usually‘warning’. Nothing below the configured level will be visible.

Basic Configuration

When you want to configure logging for your project, you should do it as soonas possible when the program starts. Ifapp.loggeris accessed before logging is configured, it will add a default handler. Ifpossible, configure logging before creating the application object.

This example usesdictConfig() to create a loggingconfiguration similar to Flask’s default, except for all logs:

fromlogging.configimportdictConfigdictConfig({'version':1,'formatters':{'default':{'format':'[%(asctime)s]%(levelname)s in%(module)s:%(message)s',}},'handlers':{'wsgi':{'class':'logging.StreamHandler','stream':'ext://flask.logging.wsgi_errors_stream','formatter':'default'}},'root':{'level':'INFO','handlers':['wsgi']}})app=Flask(__name__)

Default Configuration

If you do not configure logging yourself, Flask will add aStreamHandler toapp.loggerautomatically. During requests, it will write to the stream specified by theWSGI server inenviron['wsgi.errors'] (which is usuallysys.stderr). Outside a request, it will log tosys.stderr.

Removing the Default Handler

If you configured logging after accessingapp.logger, and need to remove the defaulthandler, you can import and remove it:

fromflask.loggingimportdefault_handlerapp.logger.removeHandler(default_handler)

Email Errors to Admins

When running the application on a remote server for production, you probablywon’t be looking at the log messages very often. The WSGI server will probablysend log messages to a file, and you’ll only check that file if a user tellsyou something went wrong.

To be proactive about discovering and fixing bugs, you can configure alogging.handlers.SMTPHandler to send an email when errors and higherare logged.

importloggingfromlogging.handlersimportSMTPHandlermail_handler=SMTPHandler(mailhost='127.0.0.1',fromaddr='server-error@example.com',toaddrs=['admin@example.com'],subject='Application Error')mail_handler.setLevel(logging.ERROR)mail_handler.setFormatter(logging.Formatter('[%(asctime)s]%(levelname)s in%(module)s:%(message)s'))ifnotapp.debug:app.logger.addHandler(mail_handler)

This requires that you have an SMTP server set up on the same server. See thePython docs for more information about configuring the handler.

Injecting Request Information

Seeing more information about the request, such as the IP address, may helpdebugging some errors. You can subclasslogging.Formatter to injectyour own fields that can be used in messages. You can change the formatter forFlask’s default handler, the mail handler defined above, or any otherhandler.

fromflaskimporthas_request_context,requestfromflask.loggingimportdefault_handlerclassRequestFormatter(logging.Formatter):defformat(self,record):ifhas_request_context():record.url=request.urlrecord.remote_addr=request.remote_addrelse:record.url=Nonerecord.remote_addr=Nonereturnsuper().format(record)formatter=RequestFormatter('[%(asctime)s]%(remote_addr)s requested%(url)s\n''%(levelname)s in%(module)s:%(message)s')default_handler.setFormatter(formatter)mail_handler.setFormatter(formatter)

Other Libraries

Other libraries may use logging extensively, and you want to see relevantmessages from those logs too. The simplest way to do this is to add handlersto the root logger instead of only the app logger.

fromflask.loggingimportdefault_handlerroot=logging.getLogger()root.addHandler(default_handler)root.addHandler(mail_handler)

Depending on your project, it may be more useful to configure each logger youcare about separately, instead of configuring only the root logger.

forloggerin(logging.getLogger(app.name),logging.getLogger('sqlalchemy'),logging.getLogger('other_package'),):logger.addHandler(default_handler)logger.addHandler(mail_handler)

Werkzeug

Werkzeug logs basic request/response information to the'werkzeug' logger.If the root logger has no handlers configured, Werkzeug adds aStreamHandler to its logger.

Flask Extensions

Depending on the situation, an extension may choose to log toapp.logger or its own named logger. Consult eachextension’s documentation for details.