celery如何运行为每一个任务生成一个日志

celery后台执行脚本,基本所有日志都集中在一个日志中,对于追踪单独一个任务执行结果会比较麻烦,每次都要去后端找日志记录进行查看,运维不是很遍历,celery其实已经支持单独日志模块
参考官网信号
关注两个信号
task_prerun
task_postrun
一个是开始执行前一个执行结束(不一定成功)
这两个信号执行时候创建独立日志,celery启动时候after_setup_logger总日志

after_setup_logger = Signal(
    name='after_setup_logger',
    providing_args={
        'logger', 'loglevel', 'logfile', 'format', 'colorize',
    },
)
task_prerun = Signal(
    name='task_prerun',
    providing_args={'task_id', 'task', 'args', 'kwargs'},
)
task_postrun = Signal(
    name='task_postrun',
    providing_args={'task_id', 'task', 'args', 'kwargs', 'retval'},
)

这是几个函数参数singals.py定义
接下来我们开始写日志定义
定义在celery.py中核心代码如下

_task_local = threading.local()

@after_setup_logger.connect
def setup_loggers(logger, *args, **kwargs):
    """配置Celery主日志记录器"""
    # 确保logs目录存在
    if not os.path.exists('logs'):
        os.makedirs('logs')

    # 文件处理器
    file_handler = logging.FileHandler('logs/celery.log')
    file_handler.setLevel(logging.INFO)

    formatter = logging.Formatter(
        '[%(asctime)s] %(levelname)s %(name)s - %(message)s'
    )
    file_handler.setFormatter(formatter)

    # 控制台处理器
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    console_handler.setFormatter(formatter)

    logger.addHandler(file_handler)
    logger.addHandler(console_handler)
    logger.setLevel(logging.INFO)

@after_setup_task_logger.connect
def setup_task_loggers(logger, *args, **kwargs):
    """为任务设置独立的日志记录器"""
    pass

@task_prerun.connect
def task_prerun_handler(task_id, task, args, kwargs, **kwds):
    """任务开始执行前的处理 - 为每个任务创建独立的日志记录器"""
    # 确保logs目录存在
    if not os.path.exists('logs'):
        os.makedirs('logs')

    # 创建任务特定的日志文件
    task_log_file = f'logs/task_{task.name}_{task_id}.log'

    # 创建文件处理器
    file_handler = logging.FileHandler(task_log_file)
    formatter = logging.Formatter(
        '[%(asctime)s] [%(name)s] %(levelname)s - %(message)s'
    )
    file_handler.setFormatter(formatter)
    file_handler.setLevel(logging.INFO)

    # 创建控制台处理器
    console_handler = logging.StreamHandler()
    console_handler.setFormatter(formatter)
    console_handler.setLevel(logging.INFO)

    # 为当前任务创建独立的日志记录器
    task_logger = logging.getLogger(f'celery.task.{task_id}')

    # 清除可能存在的旧处理器
    for handler in task_logger.handlers[:]:
        handler.close()
        task_logger.removeHandler(handler)

    # 添加新的处理器
    task_logger.addHandler(file_handler)
    task_logger.addHandler(console_handler)
    task_logger.setLevel(logging.INFO)
    task_logger.propagate = False

    # 存储处理器以便后续清理
    _task_local.file_handler = file_handler
    _task_local.console_handler = console_handler
    _task_local.logger = task_logger

    # 记录任务开始日志
    task_logger.info(f"Task {task.name} ({task_id}) started with args={args}, kwargs={kwargs}")

@task_postrun.connect
def task_postrun_handler(task_id, task, args, kwargs, retval, state, **kwds):
    """任务执行完成后的处理 - 清理日志记录器"""
    # 获取任务的日志记录器
    task_logger = logging.getLogger(f'celery.task.{task_id}')

    # 记录任务结束日志
    task_logger.info(f"Task {task.name} ({task_id}) finished with state={state}, result={retval}")

    # 关闭并移除所有处理器
    if hasattr(_task_local, 'file_handler'):
        _task_local.file_handler.close()
        task_logger.removeHandler(_task_local.file_handler)

    if hasattr(_task_local, 'console_handler'):
        _task_local.console_handler.close()
        task_logger.removeHandler(_task_local.console_handler)

    # 清理本地存储
    if hasattr(_task_local, 'logger'):
        del _task_local.logger

tasks.py进行请求时候

@shared_task(bind=True, acks_late=True)
def add(self, *args):
    # 使用task_prerun中创建的独立日志记录器
    logger = logging.getLogger(f'celery.task.{self.request.id}')
    logger.info('requst.id传递的值是:%s',self.request.id)
    logger.info('参数是 %s', args)
    logger.info('开始执行加法任务')
    time.sleep(10)
    result = int(reduce(lambda x, y: x + y, args))
    logger.info('加法任务完成,结果是 %s', result)
    return result

这个self.request.id就是任务ID日志可以看出来

[root@mysql01 logs]# cat task_tasks.tasks.add_b2f829ef-3028-4117-b253-4d99758faae0.log
[2025-09-16 16:44:12,220] [celery.task.b2f829ef-3028-4117-b253-4d99758faae0] INFO - Task tasks.tasks.add (b2f829ef-3028-4117-b253-4d99758faae0) started with args=[2, 677782323], kwargs={}
[2025-09-16 16:44:12,226] [celery.task.b2f829ef-3028-4117-b253-4d99758faae0] INFO - requst.id传递的值是:b2f829ef-3028-4117-b253-4d99758faae0
[2025-09-16 16:44:12,226] [celery.task.b2f829ef-3028-4117-b253-4d99758faae0] INFO - 参数是 (2, 677782323)
[2025-09-16 16:44:12,226] [celery.task.b2f829ef-3028-4117-b253-4d99758faae0] INFO - 开始执行加法任务
[2025-09-16 16:44:22,226] [celery.task.b2f829ef-3028-4117-b253-4d99758faae0] INFO - 加法任务完成,结果是 677782325
[2025-09-16 16:44:22,231] [celery.task.b2f829ef-3028-4117-b253-4d99758faae0] INFO - Task tasks.tasks.add (b2f829ef-3028-4117-b253-4d99758faae0) finished with state=SUCCESS, result=677782325

剩下的就是把日志进行关联展示在网页,如果想知道最新结果也是可以使用websocket获取
创作不易,如果需要源码可以联系作者付费给源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值