mirror of https://github.com/mitsuhiko/flask.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
176 lines
5.5 KiB
176 lines
5.5 KiB
7 years ago
|
.. _logging:
|
||
|
|
||
|
Logging
|
||
|
=======
|
||
|
|
||
|
Flask uses standard Python :mod:`logging`. All Flask-related messages are
|
||
|
logged under the ``'flask'`` logger namespace.
|
||
|
:meth:`Flask.logger <flask.Flask.logger>` returns the logger named
|
||
|
``'flask.app'``, and can be used to log messages for your application. ::
|
||
|
|
||
|
@app.route('/login', methods=['POST'])
|
||
|
def login():
|
||
|
user = get_user(request.form['username'])
|
||
|
|
||
|
if user.check_password(request.form['password']):
|
||
|
login_user(user)
|
||
|
app.logger.info('%s logged in successfully', user.username)
|
||
|
return redirect(url_for('index'))
|
||
|
else:
|
||
|
app.logger.info('%s failed to log in', user.username)
|
||
|
abort(401)
|
||
|
|
||
|
|
||
|
Basic Configuration
|
||
|
-------------------
|
||
|
|
||
|
When you want to configure logging for your project, you should do it as soon
|
||
|
as possible when the program starts. If :meth:`app.logger <flask.Flask.logger>`
|
||
|
is accessed before logging is configured, it will add a default handler. If
|
||
|
possible, configure logging before creating the application object.
|
||
|
|
||
|
This example uses :func:`~logging.config.dictConfig` to create a logging
|
||
|
configuration similar to Flask's default, except for all logs::
|
||
|
|
||
|
from logging.config import dictConfig
|
||
|
|
||
|
dictConfig({
|
||
|
'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 a
|
||
|
:class:`~logging.StreamHandler` to :meth:`app.logger <flask.Flask.logger>`
|
||
|
automatically. During requests, it will write to the stream specified by the
|
||
|
WSGI server in ``environ['wsgi.errors']`` (which is usually
|
||
|
:data:`sys.stderr`). Outside a request, it will log to :data:`sys.stderr`.
|
||
|
|
||
|
|
||
|
Removing the Default Handler
|
||
|
````````````````````````````
|
||
|
|
||
|
If you configured logging after accessing
|
||
|
:meth:`app.logger <flask.Flask.logger>`, and need to remove the default
|
||
|
handler, you can import and remove it::
|
||
|
|
||
|
from flask.logging import default_handler
|
||
|
|
||
|
app.logger.removeHandler(default_handler)
|
||
|
|
||
|
|
||
|
Email Errors to Admins
|
||
|
----------------------
|
||
|
|
||
|
When running the application on a remote server for production, you probably
|
||
|
won't be looking at the log messages very often. The WSGI server will probably
|
||
|
send log messages to a file, and you'll only check that file if a user tells
|
||
|
you something went wrong.
|
||
|
|
||
|
To be proactive about discovering and fixing bugs, you can configure a
|
||
|
:class:`logging.handlers.SMTPHandler` to send an email when errors and higher
|
||
|
are logged. ::
|
||
|
|
||
|
import logging
|
||
|
from logging.handlers import SMTPHandler
|
||
|
|
||
|
mail_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'
|
||
|
))
|
||
|
|
||
|
if not app.debug:
|
||
|
app.logger.addHandler(mail_handler)
|
||
|
|
||
|
This requires that you have an SMTP server set up on the same server. See the
|
||
|
Python docs for more information about configuring the handler.
|
||
|
|
||
|
|
||
|
Injecting Request Information
|
||
|
-----------------------------
|
||
|
|
||
|
Seeing more information about the request, such as the IP address, may help
|
||
|
debugging some errors. You can subclass :class:`logging.Formatter` to inject
|
||
|
your own fields that can be used in messages. You can change the formatter for
|
||
|
Flask's default handler, the mail handler defined above, or any other
|
||
|
handler. ::
|
||
|
|
||
|
from flask import request
|
||
|
from flask.logging import default_handler
|
||
|
|
||
|
class RequestFormatter(logging.Formatter):
|
||
|
def format(self, record):
|
||
|
record.url = request.url
|
||
|
record.remote_addr = request.remote_addr
|
||
|
return super().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 relevant
|
||
|
messages from those logs too. The simplest way to do this is to add handlers
|
||
|
to the root logger instead of only the app logger. ::
|
||
|
|
||
|
from flask.logging import default_handler
|
||
|
|
||
|
root = logging.getLogger()
|
||
|
root.addHandler(default_handler)
|
||
|
root.addHandler(mail_handler)
|
||
|
|
||
|
Depending on your project, it may be more useful to configure each logger you
|
||
|
care about separately, instead of configuring only the root logger. ::
|
||
|
|
||
|
for logger in (
|
||
|
app.logger,
|
||
|
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 a
|
||
|
:class:`~logging.StreamHandler` to its logger.
|
||
|
|
||
|
|
||
|
Flask Extensions
|
||
|
````````````````
|
||
|
|
||
|
Depending on the situation, an extension may choose to log to
|
||
|
:meth:`app.logger <flask.Flask.logger>` or its own named logger. Consult each
|
||
|
extension's documentation for details.
|