@@ -33,6 +33,7 @@ def get_file_handler():
3333 root_logger = logging .getLogger ()
3434
3535 # 检查现有handler,避免重复创建
36+ root_logger = logging .getLogger ()
3637 for handler in root_logger .handlers :
3738 if isinstance (handler , logging .handlers .RotatingFileHandler ):
3839 if hasattr (handler , "baseFilename" ) and Path (handler .baseFilename ) == log_file_path :
@@ -65,56 +66,51 @@ def get_console_handler():
6566 return _console_handler
6667
6768
68- class CompressedRotatingFileHandler (logging .handlers . RotatingFileHandler ):
69- """支持压缩的轮转文件处理器 """
69+ class TimestampedFileHandler (logging .Handler ):
70+ """基于时间戳的文件处理器,避免重命名操作 """
7071
71- def __init__ (self , filename , maxBytes = 0 , backupCount = 0 , encoding = None , compress = True , compress_level = 6 ):
72- super ().__init__ (filename , "a" , maxBytes , backupCount , encoding )
72+ def __init__ (self , log_dir , max_bytes = 10 * 1024 * 1024 , backup_count = 5 , encoding = 'utf-8' , compress = True , compress_level = 6 ):
73+ super ().__init__ ()
74+ self .log_dir = Path (log_dir )
75+ self .log_dir .mkdir (exist_ok = True )
76+ self .max_bytes = max_bytes
77+ self .backup_count = backup_count
78+ self .encoding = encoding
7379 self .compress = compress
7480 self .compress_level = compress_level
75- self ._rollover_lock = threading .Lock () # 添加轮转锁
76-
77- def doRollover (self ):
78- """执行日志轮转,并压缩旧文件"""
79- with self ._rollover_lock :
80- if self .stream :
81- self .stream .close ()
82- self .stream = None
83-
84- # 如果有备份文件数量限制
85- if self .backupCount > 0 :
86- # 删除最旧的压缩文件
87- old_gz = f"{ self .baseFilename } .{ self .backupCount } .gz"
88- old_file = f"{ self .baseFilename } .{ self .backupCount } "
89-
90- if Path (old_gz ).exists ():
91- self ._safe_remove (old_gz )
92- if Path (old_file ).exists ():
93- self ._safe_remove (old_file )
94-
95- # 重命名现有的备份文件
96- for i in range (self .backupCount - 1 , 0 , - 1 ):
97- source_gz = f"{ self .baseFilename } .{ i } .gz"
98- dest_gz = f"{ self .baseFilename } .{ i + 1 } .gz"
99- source_file = f"{ self .baseFilename } .{ i } "
100- dest_file = f"{ self .baseFilename } .{ i + 1 } "
101-
102- if Path (source_gz ).exists ():
103- self ._safe_rename (source_gz , dest_gz )
104- elif Path (source_file ).exists ():
105- self ._safe_rename (source_file , dest_file )
106-
107- # 处理当前日志文件
108- dest_file = f"{ self .baseFilename } .1"
109- if Path (self .baseFilename ).exists ():
110- if self ._safe_rename (self .baseFilename , dest_file ):
111- # 在后台线程中压缩文件
112- if self .compress :
113- threading .Thread (target = self ._compress_file , args = (dest_file ,), daemon = True ).start ()
114-
115- # 重新创建日志文件
116- if not self .delay :
117- self .stream = self ._open ()
81+ self ._lock = threading .Lock ()
82+
83+ # 当前活跃的日志文件
84+ self .current_file = None
85+ self .current_stream = None
86+ self ._init_current_file ()
87+
88+ def _init_current_file (self ):
89+ """初始化当前日志文件"""
90+ timestamp = datetime .now ().strftime ("%Y%m%d_%H%M%S" )
91+ self .current_file = self .log_dir / f"app_{ timestamp } .log.jsonl"
92+ self .current_stream = open (self .current_file , 'a' , encoding = self .encoding )
93+
94+ def _should_rollover (self ):
95+ """检查是否需要轮转"""
96+ if self .current_file and self .current_file .exists ():
97+ return self .current_file .stat ().st_size >= self .max_bytes
98+ return False
99+
100+ def _do_rollover (self ):
101+ """执行轮转:关闭当前文件,创建新文件"""
102+ if self .current_stream :
103+ self .current_stream .close ()
104+
105+ # 压缩旧文件
106+ if self .compress and self .current_file :
107+ threading .Thread (target = self ._compress_file , args = (self .current_file ,), daemon = True ).start ()
108+
109+ # 清理旧文件
110+ self ._cleanup_old_files ()
111+
112+ # 创建新文件
113+ self ._init_current_file ()
118114
119115 def _safe_rename (self , source , dest ):
120116 """安全重命名文件,处理Windows文件占用问题"""
@@ -205,7 +201,7 @@ def close_handlers():
205201
206202
207203def remove_duplicate_handlers ():
208- """移除重复的handler,特别是文件handler """
204+ """移除重复的文件handler """
209205 root_logger = logging .getLogger ()
210206 log_file_path = str (LOG_DIR / "app.log.jsonl" )
211207
@@ -314,7 +310,7 @@ def reconfigure_existing_loggers():
314310
315311 # 重新设置根logger的所有handler的格式化器
316312 for handler in root_logger .handlers :
317- if isinstance (handler , logging . handlers . RotatingFileHandler ):
313+ if isinstance (handler , TimestampedFileHandler ):
318314 handler .setFormatter (file_formatter )
319315 elif isinstance (handler , logging .StreamHandler ):
320316 handler .setFormatter (console_formatter )
@@ -354,7 +350,7 @@ def reconfigure_existing_loggers():
354350
355351 # 如果logger有自己的handler,重新配置它们(避免重复创建文件handler)
356352 for handler in original_handlers :
357- if isinstance (handler , logging . handlers . RotatingFileHandler ):
353+ if isinstance (handler , TimestampedFileHandler ):
358354 # 不重新添加,让它使用根logger的文件handler
359355 continue
360356 elif isinstance (handler , logging .StreamHandler ):
0 commit comments