# flask_app/logger_setup.py import logging import sys import uuid from datetime import datetime, timedelta from logging.handlers import RotatingFileHandler from flask import g import os class CSTFormatter(logging.Formatter): """自定义的 Formatter,将日志的时间戳调整为中国标准时间(UTC+8)""" def formatTime(self, record, datefmt=None): ct = datetime.fromtimestamp(record.created) + timedelta(hours=8) if datefmt: s = ct.strftime(datefmt) else: try: s = ct.strftime("%Y-%m-%d %H:%M:%S") if self.usesTime(): s = f"{s},{record.msecs:03d}" except ValueError: s = ct.strftime("%Y-%m-%d %H:%M:%S") return s def create_logger_main(log_name, log_dir='/flask_project/flask_app/static/output', max_bytes=10*1024*1024, backup_count=5): """ 根据名称创建全局日志记录器,并将日志写入指定的 .txt 文件中。 """ os.makedirs(log_dir, exist_ok=True) # 确保日志目录存在 logger = logging.getLogger(log_name) if not logger.hasHandlers(): # 防止重复添加处理器 logger.setLevel(logging.INFO) # 将文件名设置为 model_log.txt(如果 log_name 为 "model_log") log_file_path = os.path.join(log_dir, f'{log_name}.txt') file_handler = RotatingFileHandler( log_file_path, maxBytes=max_bytes, backupCount=backup_count, encoding='utf-8' ) file_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')) logger.addHandler(file_handler) return logger def create_logger(app, subfolder): """ 创建一个唯一的 logger 和对应的输出文件夹。 参数: subfolder (str): 子文件夹名称,如 'output1', 'output2', 'output3' """ unique_id = str(uuid.uuid4()) g.unique_id = unique_id output_folder = os.path.join("flask_app", "static", "output", subfolder, unique_id) os.makedirs(output_folder, exist_ok=True) log_filename = "log.txt" log_path = os.path.join(output_folder, log_filename) logger = logging.getLogger(unique_id) if not logger.handlers: file_handler = logging.FileHandler(log_path) file_formatter = CSTFormatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') file_handler.setFormatter(file_formatter) logger.addHandler(file_handler) stream_handler = logging.StreamHandler() stream_handler.setFormatter(logging.Formatter('%(message)s')) logger.addHandler(stream_handler) logger.setLevel(logging.INFO) #Logger 只会处理大于或等于 INFO 级别的日志消息(例如 INFO、WARNING、ERROR、CRITICAL),而 DEBUG 级别的消息会被忽略。 logger.propagate = False g.logger = logger g.output_folder = output_folder #输出文件夹路径