本文首发于公众号:Hunter后端
原文链接:Flask笔记五之日志操作
之前在 Django 笔记里详细介绍了 logging 模块关于 formatters,handlers,loggers 等基础介绍,这里就不做多的介绍了,详情可以直接跳转查看相应文章:Django笔记三十之log日志的记录详解
这里直接介绍如何在 Flask 中配置日志信息。
本篇笔记的代码都已经提交到 github 上,可使用下面的操作获取代码:
git clone https://github.com/x1204604036/flask_backend.git
首先,我们创建一些日志输出的文件地址变量,在 config/config.py
中记录,根据环境判断来源于测试环境变量文件或者生产环境变量文件,我这里是在 development.py
中,内容如下:
LOGGING_PATH = "e:/code/log_file/flask_backend/flask.log"
LOGGING_ERROR_PATH = "e:/code/log_file/flask_backend/flask_error.log"
接着在 app/config/
文件夹下创建一个文件 logging_config.py
,内容如下:
# app/config/logging_config.py
from app.config import config
LoggingConfig = {
"version": 1,
"formatters": {
"verbose": {
"format": "%(levelname)s %(asctime)s %(filename)s %(lineno)s %(message)s",
}
},
"handlers": {
"file": {
"level": "INFO",
"filename": config.LOGGING_PATH,
"formatter": "verbose",
"class": "logging.handlers.RotatingFileHandler",
'maxBytes': 5 * 1024 * 1024,
'backupCount': 20,
},
"error_handler": {
"level": "INFO",
"filename": config.LOGGING_ERROR_PATH,
"formatter": "verbose",
"class": "logging.handlers.RotatingFileHandler",
'maxBytes': 5 * 1024 * 1024,
'backupCount': 20,
},
"email_handler": {
"level": "WARNING",
"class": "logging.handlers.SMTPHandler",
"mailhost": ("smtp.163.com", 25),
"fromaddr": "hunterxxxxx@163.com",
"toaddrs": "120xxxx@qq.com",
"subject": "系统error",
"credentials": ("hunterxxxx@163.com", "JBDMVIxxxxx"),
"timeout": 20,
},
},
"root": {
"handlers": ["file"],
"level": "INFO",
"propagate": True,
},
"loggers": {
"error_log": {
"handlers": ["error_handler", "email_handler"],
"level": "INFO",
}
}
}
这里创建了三个 handler,两个 FileHandler 将日志以文件形式存储,一个用于发送邮件
其下,root 表示用于记录 Flask 全部信息的输出,其他的 logger 都在 loggers 下记录,在这里一个记录 error 的 logger 对应有两个 handler,一个记录日志到文件,一个发送邮件。
在 app/__init__.py
中引入日志配置:
# app/__init__.py
import logging.config
from app.config import looging_config
def create_app():
app = Flask(__name__)
logging.config.dictConfig(looging_config.LoggingConfig)
return app
这里,我们以上一节中的异常处理为例进行日志记录,将日志输出的代码都放到异常处理中,exception_handler.py
内容如下:
from werkzeug.exceptions import HTTPException
from flask import jsonify, request
import logging
import traceback
logger = logging.getLogger("error_log")
ERROR_HTTP_CODE = 417
class UserException(Exception):
def __init__(self, code=-1, msg="error", http_code=417):
self.code = code
self.msg = msg
self.http_code = http_code
def init_error_exception(app):
@app.errorhandler(HTTPException)
def handler_http_exception(exception):
trace_info = traceback.format_exc()
log_msg = "request path: %s, traceback info: %s, description: %s" % (
request.path, trace_info, exception.description
)
logger.info(log_msg)
return jsonify({"code": -1, "msg": exception.description}), exception.code
@app.errorhandler(Exception)
def server_exception(exception):
logger.info("request_path: " + request.path)
trace_info = traceback.format_exc()
log_msg = "request path: %s, traceback info: %s" % (request.path, trace_info)
logger.info(log_msg)
logger.error("系统报错信息:%s" % log_msg)
return jsonify({"code": -1, "msg": "内部错误"}), ERROR_HTTP_CODE
@app.errorhandler(UserException)
def user_exception(exception):
trace_info = traceback.format_exc()
log_msg = "request path: %s, traceback info: %s, exception msg: %s" % (
request.path, trace_info, exception.msg
)
logger.info(log_msg)
return jsonify({"code": exception.code, "msg": exception.msg}), exception.http_code
这里,我们将请求路径,报错信息等放到 log_msg 中,然后通过 logger.info() 输出,另外,这里我们还尝试对系统异常的处理发送邮件到指定邮箱。
注意:日志配置中的邮箱信息记得改成自己实际的,这里我对我的信息做了模糊处理。
重新运行系统后,尝试触发这三种报错,就可以在对应的日志文件里看到错误信息的输出了,触发了 error 的第二种 exception 异常处理还会发送邮件。