在使用Python Flask开发Web应用的过程中,记录请求日志是排查接口问题、统计服务运行状态的重要手段。Flask本身内置了日志功能,但默认的日志配置只会将日志输出到控制台,且没有自动滚动机制,长期运行后日志会不断堆积,既不方便查看也会占用大量磁盘空间。通过Python标准库中的logging模块,我们可以灵活配置日志的存储方式、滚动规则,实现按文件大小或者按日期自动切割日志文件的需求。

基础环境准备
首先需要确保已经安装了Flask框架,如果没有安装可以通过以下命令完成安装:
pip install flask
本文示例基于Flask 2.0以上版本,logging模块是Python标准库自带,不需要额外安装。
按日志文件大小自动滚动配置
按大小滚动日志需要使用logging模块中的RotatingFileHandler处理器,该处理器可以在日志文件达到指定大小后自动创建新的日志文件,同时可以设置保留的历史日志文件数量。
完整配置代码示例
以下是一个Flask应用按大小滚动请求日志的完整实现:
from flask import Flask, request
import logging
from logging.handlers import RotatingFileHandler
import os
# 创建Flask应用实例
app = Flask(__name__)
# 配置日志相关参数
log_dir = "logs" # 日志存储目录
log_file = "flask_request.log" # 日志文件名
max_file_size = 10 * 1024 * 1024 # 单个日志文件最大大小,这里设置为10MB
backup_count = 10 # 最多保留10个历史日志文件
# 创建日志目录,如果目录不存在则自动创建
if not os.path.exists(log_dir):
os.makedirs(log_dir)
# 创建RotatingFileHandler实例
rotating_handler = RotatingFileHandler(
filename=os.path.join(log_dir, log_file),
maxBytes=max_file_size,
backupCount=backup_count,
encoding="utf-8"
)
# 设置日志格式
log_formatter = logging.Formatter(
"%(asctime)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
rotating_handler.setFormatter(log_formatter)
# 获取Flask应用的logger对象,添加处理器
app.logger.addHandler(rotating_handler)
# 设置日志级别为INFO,只记录INFO及以上级别的日志
app.logger.setLevel(logging.INFO)
# 定义请求日志记录的装饰器,用于记录每个请求的详细信息
def log_request_info(f):
from functools import wraps
@wraps(f)
def decorated_function(*args, **kwargs):
# 记录请求方法、路径、客户端IP
log_msg = f"Request: {request.method} {request.path} | Client IP: {request.remote_addr}"
app.logger.info(log_msg)
return f(*args, **kwargs)
return decorated_function
# 给所有路由添加请求日志记录装饰器
app.before_request(log_request_info)
# 测试路由
@app.route("/")
def index():
return "Hello Flask Logging"
@app.route("/test")
def test():
return "Test Route"
if __name__ == "__main__":
app.run(debug=False, host="127.0.0.1", port=5000)
配置参数说明
上述代码中几个关键参数的作用如下:
- maxBytes:单个日志文件的最大大小,单位是字节,示例中设置为10MB,当日志文件达到这个大小后会自动切割。
- backupCount:保留的历史日志文件数量,超过这个数量的旧日志文件会被自动删除。
- encoding:日志文件的编码格式,设置为utf-8可以避免中文乱码问题。
运行上述代码后,所有请求日志都会写入logs/flask_request.log文件,当该文件大小达到10MB时,会自动重命名为flask_request.log.1,新的日志会继续写入flask_request.log,最多保留10个历史文件。
按日期自动滚动日志配置
如果需要按天、按小时等时间维度自动切割日志,可以使用TimedRotatingFileHandler处理器,该处理器支持按照指定的时间间隔自动创建新的日志文件。
完整配置代码示例
以下是按天滚动日志的实现示例:
from flask import Flask, request
import logging
from logging.handlers import TimedRotatingFileHandler
import os
# 创建Flask应用实例
app = Flask(__name__)
# 配置日志相关参数
log_dir = "logs" # 日志存储目录
log_file = "flask_request_daily.log" # 日志文件名
when = "midnight" # 滚动时间,midnight表示每天凌晨滚动
interval = 1 # 间隔时间,配合when使用,1表示每1个midnight滚动一次
backup_count = 30 # 保留30天的历史日志
# 创建日志目录
if not os.path.exists(log_dir):
os.makedirs(log_dir)
# 创建TimedRotatingFileHandler实例
time_rotating_handler = TimedRotatingFileHandler(
filename=os.path.join(log_dir, log_file),
when=when,
interval=interval,
backupCount=backup_count,
encoding="utf-8"
)
# 设置日志格式
log_formatter = logging.Formatter(
"%(asctime)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
time_rotating_handler.setFormatter(log_formatter)
# 添加处理器到Flask logger
app.logger.addHandler(time_rotating_handler)
app.logger.setLevel(logging.INFO)
# 请求日志装饰器
def log_request_info(f):
from functools import wraps
@wraps(f)
def decorated_function(*args, **kwargs):
log_msg = f"Request: {request.method} {request.path} | Client IP: {request.remote_addr}"
app.logger.info(log_msg)
return f(*args, **kwargs)
return decorated_function
app.before_request(log_request_info)
# 测试路由
@app.route("/")
def index():
return "Hello Flask Daily Logging"
if __name__ == "__main__":
app.run(debug=False, host="127.0.0.1", port=5000)
when参数可选值说明
when参数支持多种时间单位,常见的取值如下:
| 参数值 | 含义 |
|---|---|
| S | 每秒滚动一次 |
| M | 每分钟滚动一次 |
| H | 每小时滚动一次 |
| D | 每天滚动一次 |
| midnight | 每天凌晨滚动一次 |
| W0-W6 | 每周指定星期几滚动,W0表示周一,W6表示周日 |
注意事项
- 生产环境中建议关闭Flask的debug模式,避免debug模式的日志输出影响正常日志记录。
- 如果同时配置了按大小滚动和按时间滚动的处理器,两个处理器会同时生效,日志会同时写入两个对应的日志文件中。
- 日志格式可以根据实际需求调整,比如添加请求参数、响应状态码等信息,方便后续问题排查。
- 如果需要记录更详细的请求信息,可以结合
request对象获取请求头、请求体等内容,注意不要记录敏感信息比如用户密码等。
logging模块是线程安全的,在Flask多进程或者多线程部署的场景下可以正常使用,不需要额外做线程同步处理。
通过上述两种配置方式,就可以实现Flask请求日志的自动滚动需求,开发者可以根据实际业务场景选择合适的滚动策略,既可以按大小切割避免单个文件过大,也可以按时间维度切割方便按日期查找日志。