celery自定义日志格式,自动为输出日志增加任务名(task name)和任务ID(task id)

由于celery是并发执行任务,当打印日志在同一个文件时,不同进程之间的日志就交错堆叠在了一起,想要查询日志回溯某个问题时,总是非常困难。
如果每条log都能带上当前task的ID,就会方便很多。

核心代码:

from celery._state import get_current_task
task = get_current_task()
if task and task.request:
	task_id = task.request.id
	task_name = task.name

一、准备环境

建议使用root账户操作,以免安装、配置、运行权限不够。

  • 操作系统:推荐Debian系列(或其它Linux,celery4.0开始不再支持windows)
    • redis版本:4.0.8 (sudo apt-get install redis-server, sudo service redis-server start)
    • python版本:3.6.5

二、编写程序

  1. celeryconfig.py
import logging

from celery._state import get_current_task

class Formatter(logging.Formatter):
    """Formatter for tasks, adding the task name and id."""

    def format(self, record):
        task = get_current_task()
        if task and task.request:
            record.__dict__.update(task_id='%s ' % task.request.id,
                                   task_name='%s ' % task.name)
        else:
            record.__dict__.setdefault('task_name', '')
            record.__dict__.setdefault('task_id', '')
        return logging.Formatter.format(self, record)


root_logger = logging.getLogger() # 返回logging.root
root_logger.setLevel(logging.DEBUG)

# 将日志输出到文件
fh = logging.FileHandler('celery_worker.log') # 这里注意不要使用TimedRotatingFileHandler,celery的每个进程都会切分,导致日志丢失
formatter = Formatter('[%(task_name)s%(task_id)s%(process)s %(thread)s %(asctime)s %(pathname)s:%(lineno)s] %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
fh.setFormatter(formatter)
fh.setLevel(logging.DEBUG)
root_logger.addHandler(fh)

# 将日志输出到控制台
sh = logging.StreamHandler()
formatter = Formatter('[%(task_name)s%(task_id)s%(process)s %(thread)s %(asctime)s %(pathname)s:%(lineno)s] %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
sh.setFormatter(formatter)
sh.setLevel(logging.INFO)
root_logger.addHandler(sh)

class CeleryConfig(object):
    BROKER_URL = 'redis://localhost:6379/0'
    CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
    CELERY_TASK_SERIALIZER = 'pickle' # " json从4.0版本开始默认json,早期默认为pickle(可以传二进制对象)
    CELERY_RESULT_SERIALIZER = 'pickle'
    CELERY_ACCEPT_CONTENT = ['json', 'pickle']
    CELERY_ENABLE_UTC = True # 启用UTC时区
    CELERY_TIMEZONE = 'Asia/Shanghai' # 上海时区
    CELERYD_HIJACK_ROOT_LOGGER = False # 拦截根日志配置
    CELERYD_MAX_TASKS_PER_CHILD = 1 # 每个进程最多执行1个任务后释放进程(再有任务,新建进程执行,解决内存泄漏)
  1. tasks.py
import logging

from celery import Celery, platforms

import celeryconfig
import detail

platforms.C_FORCE_ROOT = True # 配置里设置了序列化类型为pickle,操作系统开启允许
app = Celery(__name__)
app.config_from_object(celeryconfig.CeleryConfig)


@app.task(bind=True)
def heavy_task(self, seconds=1):
    logging.info("I'm heavy_task") # 默认使用logging.root
    return detail.process_heavy_task(seconds)
  1. detail.py
import logging
import time

def process_heavy_task(seconds=1):
    logging.info("I'm process_heavy_task") # 默认使用logging.root
    time.sleep(seconds)
    return True

三、启动并测试

  1. 新建shell窗口,启动celery服务
# ls
celeyconfig.py	detail.py	tasks.py
# celery worker -A tasks -l info
  1. 新建shell窗口,监控日志文件
# ls
celeyconfig.py	celery_worker.log	detail.py	tasks.py
# tail -f celery_worker.log
  1. 新建shell窗口,调用celery任务
# ls
celeyconfig.py	celery_worker.log	detail.py	tasks.py
# python3
>>> import tasks
>>> t = tasks.heavy_task.delay(3)
>>> t.result
True

四、结果截图

启动worker
监控日志
调用任务

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python Celery是一个分布式任务队列框架,它可以让你在分布式系统中异步执行任务。它支持定时任务的调度,可以让你在指定的时间间隔或者特定的时间点执行任务。 要使用Celery进行定时任务调度,你需要先安装Celery库。可以使用pip命令进行安装: ``` pip install celery ``` 安装完成后,你需要创建一个Celery实例,并配置它的任务队列和调度器。下面是一个简单的示例: ```python from celery import Celery from datetime import timedelta # 创建Celery实例 app = Celery('tasks', broker='redis://localhost:6379/0') # 配置定时任务调度器 app.conf.beat_schedule = { 'task-name': { 'task': 'tasks.task_name', # 任务函数的路径 'schedule': timedelta(seconds=10), # 任务执行的时间间隔 }, } # 定义任务函数 @app.task def task_name(): # 任务的具体逻辑 pass ``` 在上面的示例中,我们创建了一个为`tasks`的Celery实例,并配置了Redis作为任务队列的中间件。然后,我们使用`app.conf.beat_schedule`配置了一个定时任务调度器,其中`task-name`是任务称,`task`是任务函数的路径,`schedule`是任务执行的时间间隔,这里设置为每10秒执行一次。最后,我们定义了一个为`task_name`的任务函数,你可以在这个函数中编写具体的任务逻辑。 为了启动Celery的定时任务调度器,你需要在终端中执行以下命令: ``` celery -A tasks beat ``` 这样,Celery就会按照你配置的时间间隔或者时间点执行定时任务。 希望以上内容能够帮助到你,如果有任何疑问,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值