日志¶
Flask 使用标准的 Python logging
模块。与 Flask 应用相关的消息都使用 app.logger
记录,该记录器的名称与 app.name
相同。这个日志记录器也可以用于你自己的日志记录。
@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)
若不进行日志配置,Python 的默认日志级别通常是 ‘warning’。低于你所配置日志级别的消息将不可见。
基本配置¶
若想为你的项目配置日志,应当在程序启动前尽早进行配置。如果在日志配置前访问 app.logger
对象,它会添加一个默认日志处理器。尽可能在创建应用对象之前配置日志。
这个例子使用 dictConfig()
创建与 Flask 类似的默认日志配置:
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__)
默认配置¶
若未自行配置日志,Flask 会自动添加一个 StreamHandler
到 app.logger
。在请求过程中,它将写入到由 WSGI 服务器指定的、保存在 environ['wsgi.errors']
中的日志流(这个值通常是 sys.stderr
)。请求之外的日志则会记录到 sys.stderr
。
移除默认日志处理器¶
若你在访问 app.logger
对象之后进行日志配置,并且需要移除默认的日志处理器,可以导入后移除它:
from flask.logging import default_handler
app.logger.removeHandler(default_handler)
将错误信息通过电子邮件发送给管理员¶
在生产环境中,当应用在远程服务器上运行时,你可能不会经常查看日志消息。WSGI 服务器可能会将日志消息输出到文件,而你将只在用户告诉你出错时才会查看日志文件。
为了主动发现并修复错误,可以配置一个 logging.handlers.SMTPHandler
,当错误或者更高级别的日志被记录下来时就会发送一封电子邮件:
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)
这需要你在同一台服务器上搭建一个 SMTP 服务器。关于日志处理器的更多内容请参阅 Python 官方文档。
注入请求信息¶
了解请求的更多信息,例如 IP 地址,可能有助于调试某些错误。可以继承 logging.Formatter
来注入自己的字段内容,用在日志消息上。然后,可以修改格式器 (Formatter) 用在 Flask 的默认处理器、上文定义的邮件处理器或者其他处理器上:
from flask import has_request_context, request
from flask.logging import default_handler
class RequestFormatter(logging.Formatter):
def format(self, record):
if has_request_context():
record.url = request.url
record.remote_addr = request.remote_addr
else:
record.url = None
record.remote_addr = None
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)
其他库¶
其他库可能会广泛地使用日志,而你也希望看到与之相关的日志。最简单的方式是向根日志记录器 (root logger) 添加处理器,而不仅仅是 app 日志记录器:
from flask.logging import default_handler
root = logging.getLogger()
root.addHandler(default_handler)
root.addHandler(mail_handler)
单独为每个你关心的记录器进行配置,可能比只配置根记录器对你更有益,这取决于你的项目:
for logger in (
app.logger,
logging.getLogger('sqlalchemy'),
logging.getLogger('other_package'),
):
logger.addHandler(default_handler)
logger.addHandler(mail_handler)
Werkzeug¶
Werkzeug 记录基本的请求、响应信息到 'werkzeug'
日志记录器。如果根记录器没有配置任何处理器,Werkzeug 会向记录器添加一个 StreamHandler
。
Flask 扩展¶
根据情况不同,扩展可能会选择将日志记录到 app.logger
或者自己命名的记录器上。详情请参阅对应扩展的文档。