关于Flask日志记录,网上的文章大多都已过时,我在项目开发过程中,结合实际情况,初步采用以下日志方案,后续遇到问题会不断进行优化,并更新文章内容。
日志记录的总体思路如下:
- 在 Flask 工厂函数中,利用钩子函数,将接口每次的请求参数和响应内容写入到日志文件中,并利用
flask_sqlalchemy
提供的get_debug_queries
方法,实现当执行时间超过阈值时,将查询信息按照指定的格式写入到日志文件中; - 接入
Sentry SDK
,收集项目错误日志,然后在Sentry Dashboard查看异常信息;(点击查看官方文档)
工厂函数相关内容如下,注释已经写得很清楚了:
from pathlib import Path
from logging.handlers import RotatingFileHandler
from flask import Flask
from flask_sqlalchemy import get_debug_queries
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
from .config import config
# 递归创建日志存放目录
basedir = Path(__file__).parent.parent # 项目根目录
logdir = basedir.joinpath(r'rethink/logs')
if not logdir.is_dir():
os.makedirs(logdir)
# 初始化Sentry, 必须在工厂函数之前
sentry_sdk.init(
dsn="官网注册账号后会给出",
integrations=[FlaskIntegration()]
)
def make_app(config_name=None):
if config_name is None:
config_name = os.getenv("FLASK_CONFIG", "development")
# 加载配置文件
app = Flask(__name__)
app.config.from_object(config[config_name])
register_logger(app) # 注册日志处理器
# 如果没有未处理的异常抛出,会在每个请求结束后运行
# 必须接受一个响应类对象作为参数,并返回同一个或更新后的响应对象
@app.after_request
def response_logger(response):
# 获取接口响应数据
api_path = request.full_path
api_method = request.method
ip_addr = request.remote_addr
# 获取接口请求数据
try:
request_data = request.get_json(force=True)
except Exception as e:
request_data = request.form.to_dict()
request_data, response_data = str(request_data), str(response.json)
with open(logdir.joinpath('runtime.log'), 'a+', encoding="utf-8") as f:
asctime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
f.write(
asctime + " " + ip_addr + " " + api_method + " " + api_path + '->' + request_data + '\n' + response_data + '\n')
# 记录慢查询日志,在日志处理器函数中会将其写入到文件中
for query in get_debug_queries():
if query.duration >= app.config['FLASK_SLOW_DB_QUERY_TIME']:
app.logger.warning(
'Slow query: %s\n Parameters: %s\n Duration: %fs\n Context: %s'
% (query.statement, query.parameters, query.duration, query.context))
return response
return app
def register_logger(app):
app.logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 设置日志文件最大尺寸和备份数量
# 最大尺寸为10M,当超过10M产生备份文件,最多产生10个备份文件,10个备份文件全部存满后,会开始覆盖之前的文件
file_handler = RotatingFileHandler(logdir.joinpath('runtime.log'), maxBytes=10 * 1024 * 1024, backupCount=10)
file_handler.setFormatter(formatter)
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.info('Autoline Startup...') # 这里额外在日志文件中记录下每次应用服务的启动时间
config.py
是项目配置文件,相关内容如下:
class BaseConfig(object):
# 启用慢查询记录功能(调试模式下自动启用), 为了在生产环境下可用,必须手动配置此项为True
SQLALCHEMY_RECORD_QUERIES = True
# 慢查询阈值
FLASK_SLOW_DB_QUERY_TIME = 0.001
class DevelopmentConfig(BaseConfig):
SQLALCHEMY_DATABASE_URI = os.getenv("DB_DEVELOPMENT_URI")
class TestingConfig(BaseConfig):
SQLALCHEMY_DATABASE_URI = os.getenv("DB_Testing_URI")
class ProductionConfig(BaseConfig):
SQLALCHEMY_DATABASE_URI = os.getenv('DB_PRODUCTION_URI')
config = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig
}
在配置文件中,为了测试慢查询日志记录,特意将FLASK_SLOW_DB_QUERY_TIME
设置为0.001s. 在本地开发环境下请求下flask接口,在控制台可以看到有相关的日志输出,如下:
【To Be Continued...】
网友评论