FastAPI项目如何通过config.ini配置日志按大小和时间双重轮转?
实现同时按大小和时间轮转日志
Python标准库的logging模块没有内置同时支持大小轮转和时间轮转的Handler,你需要自定义一个Handler来结合两种轮转逻辑,或者使用第三方库。下面是自定义Handler的实现方案:
步骤1:自定义轮转Handler
在你的FastAPI项目的api目录下创建log_handlers.py文件,写入以下代码:
import logging from logging.handlers import RotatingFileHandler import os import time class SizeAndTimeRotatingFileHandler(RotatingFileHandler): def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False, when='s', interval=1, utc=False): # 初始化大小轮转相关参数 super().__init__(filename, mode, maxBytes, backupCount, encoding, delay) # 初始化时间轮转相关参数 self.when = when.upper() self.interval = interval self.utc = utc # 日志文件后缀格式(按秒轮转的话,精确到秒) self.suffix = "%Y-%m-%d_%H-%M-%S" # 计算下一次轮转的时间点 if os.path.exists(filename): self.rolloverAt = self.compute_rollover_time(os.path.getmtime(filename)) else: self.rolloverAt = self.compute_rollover_time(time.time()) def compute_rollover_time(self, current_time): # 计算下一次时间轮转的时间点(这里仅实现秒级轮转,可扩展其他时间单位) if self.when == 'S': rollover_seconds = self.interval current_time = current_time - (current_time % rollover_seconds) + rollover_seconds return current_time def shouldRollover(self, record): # 同时判断两个轮转条件:大小达标 或 时间到点 size_trigger = super().shouldRollover(record) time_trigger = time.time() >= self.rolloverAt return size_trigger or time_trigger def doRollover(self): # 执行轮转操作:重命名当前日志文件,生成带时间后缀的备份 if self.stream: self.stream.close() self.stream = None # 生成带时间后缀的备份文件名 current_time = time.time() time_str = time.strftime(self.suffix, time.gmtime(current_time) if self.utc else time.localtime(current_time)) backup_filename = f"{self.baseFilename}.{time_str}" if os.path.exists(backup_filename): os.remove(backup_filename) os.rename(self.baseFilename, backup_filename) # 删除超过备份数量限制的旧日志 if self.backupCount > 0: for old_file in self.getFilesToDelete(): os.remove(old_file) # 更新下一次时间轮转的时间点 self.rolloverAt = self.compute_rollover_time(current_time) # 重新打开新的日志文件 if not self.delay: self.stream = self._open()
步骤2:修改日志配置文件logconfig.ini
更新handler_logfile部分,指定自定义Handler的类路径,并传入你的参数(大小限制500字节,10秒轮转,备份数1000):
[loggers] keys=root [handlers] keys=logfile [formatters] keys=logfileformatter [logger_root] level=INFO handlers=logfile [formatter_logfileformatter] format=[%(asctime)s.%(msecs)03d] %(levelname)s [%(thread)d] - %(message)s [handler_logfile] class=api.log_handlers.SizeAndTimeRotatingFileHandler args=('C:\\path\\api.log', 'a', 500, 1000, None, False, 's', 10, False)
参数说明:
'C:\\path\\api.log': 日志文件路径'a': 写入模式(追加)500: 单文件最大字节数1000: 最大备份文件数None: 编码(默认None)False: 是否延迟打开文件's': 时间轮转单位(秒,可选值:S/秒、M/分、H/时、D/天等)10: 时间轮转间隔(10秒)False: 是否使用UTC时间
步骤3:移除冲突的日志配置
删除main.py中的logging.basicConfig代码块,因为你已经通过--log-config指定了日志配置,重复配置会导致日志重复输出或冲突:
# 删掉这段代码 # logging.basicConfig( # level=logging.INFO, # )
可选方案:使用第三方库
如果你不想自定义Handler,可以使用第三方库concurrent-log-handler,它支持同时按大小和时间轮转:
- 安装库:
pip install concurrent-log-handler
- 修改
logconfig.ini的handler_logfile部分:
[handler_logfile] class=concurrent_log_handler.ConcurrentRotatingFileHandler args=('C:\\path\\api.log', 'a', 500, 1000) kwargs={"when": "S", "interval": 10}
内容的提问来源于stack exchange,提问作者Hannon qaoud
相关产品推荐
相关产品推荐

