使用celery推入flask上下文时打印多次同样日志的处理方法

由于我们很多统计和备份的任务,所以单独使用celery来做这些耗时或者需要定时处理的工作,但是在使用的过程中出现一些问题,就是发现日志中打印的celery相关的日志时会多次打印同样的信息,次数和我的flask和celery进程数量能够对应上,所以解决这个问题的同时也顺便记录下,方便后续使用。

问题现象如下

202508290942209004715212.png

在应用工厂中我目前的日志配置如下

#日志配置
def configure_logger(app):
    if not os.path.exists(app.config["LOG_PATH"]):
        os.makedirs(app.config["LOG_PATH"], mode=0o777)
    log_level = logging.INFO
    log_file_path = app.config["LOG_PATH"] + os.sep + "blog.log"
    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s')
    handler = TimedRotatingFileHandler(log_file_path, when="midnight", interval=1, backupCount=15,encoding="UTF-8")
    handler.setLevel(log_level)
    handler.setFormatter(formatter)
    app.logger.addHandler(handler)

需要对上述代码进行改造,主要创建添加一个日志过滤器来让进程感知过滤器,改造代码如下

#日志过滤器
class ProcessFilter(logging.Filter):
    def filter(self, record):
        record.process_id = os.getpid()
        return True

#日志配置
def configure_logger(app):
    if not os.path.exists(app.config["LOG_PATH"]):
        os.makedirs(app.config["LOG_PATH"], mode=0o777)
    log_level = logging.INFO
    log_file_path = app.config["LOG_PATH"] + os.sep + "blog.log"
    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s')
    handler = TimedRotatingFileHandler(log_file_path, when="midnight", interval=1, backupCount=15,encoding="UTF-8")
    handler.setLevel(log_level)
    handler.setFormatter(formatter)
    
    #添加进程过滤器,防止进程重复
    process_filter = ProcessFilter()
    handler.addFilter(process_filter)
    
    app.logger.handlers.clear()
    app.logger.addHandler(handler)
    app.logger.setLevel(log_level)

根据上述修改以后日志就不会再次输出多次同样的日志了。

还有另外一种处理方式,就是flask和celery使用不同的日志文件,下面方法查到的,但是还没实践过,先记录,后面可能用的上

ef configure_logger(app):
    if not os.path.exists(app.config["LOG_PATH"]):
        os.makedirs(app.config["LOG_PATH"], mode=0o777)
    
    # 获取进程标识
    process_type = os.environ.get('PROCESS_TYPE', 'flask')
    process_id = os.getpid()
    
    # 为不同进程类型创建不同的日志文件
    if process_type == 'celery':
        log_file_name = f"celery_{process_id}.log"
    else:
        log_file_name = f"flask_{process_id}.log"
    
    log_file_path = os.path.join(app.config["LOG_PATH"], log_file_name)
    
    log_level = logging.INFO
    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s')
    
    handler = TimedRotatingFileHandler(
        log_file_path, 
        when="midnight", 
        interval=1, 
        backupCount=15,
        encoding="UTF-8"
    )
    handler.setLevel(log_level)
    handler.setFormatter(formatter)
    
    # 清除可能存在的其他处理器
    app.logger.handlers.clear()
    app.logger.addHandler(handler)
    app.logger.setLevel(log_level)

这种方式就是用设置进程类型,然后根据不同的进程类型将日志写入不同的日志文件中。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://sulao.cn/post/1126

评论列表

0%