自定义 Celery的logging模块

news/2025/1/2 14:45:55/

为什么需要自定义 Celery 日志

默认的 Celery 日志配置虽然满足基本需求,但在以下情况下可能需要进行自定义:

  • 支持日志滚动:原生celery不支持日志滚动。
  • 更详细的日志信息:需要包含更多上下文信息,以便更好地理解任务的执行过程。
  • 日志格式调整:适应现有的日志管理系统,如 ELK(Elasticsearch, Logstash, Kibana)堆栈。
  • 多日志目标:将日志同时输出到多个地方,例如控制台、文件和远程日志服务器。
  • 日志级别控制:根据不同的模块或任务设定不同的日志级别。

Celery 日志为什么复杂

Celery的日志记录看起来不符合Python的风格,并且显得复杂。这不是Celery的问题,而是因为Python的日志系统默认不支持Celery所需的各种并发环境,如eventlets、greenlets、prefork和线程等。因此,Celery需要自定义日志记录。

Celery提供了一个特殊的函数get_task_logger,它在celery.utils.log中用于获取日志记录器。这个记录器会自动包含任务名称和唯一ID。Celery的文档建议使用get_task_logger。

在worker中应用日志,我更喜欢使用标准的logging.getLogger方法,因为这样可以保持代码库的清晰,并与Celery应用的上下文分离。

策略1:增强Celery日志记录器

Celery提供了一个after_setup_logger信号,该信号在Celery设置日志记录器后触发
(http://docs.celeryproject.org/en/latest/userguide/signals.html#after-setup-logger)。该信号传递了日志记录器对象(以及其他一些参数),你可以方便地向其添加自定义日志处理程序。

Celery 使用 Python 的标准 logging 模块进行日志记录。首先,需要获取 Celery 默认的日志记录器。

python">import os
import logging
from celery import Celery
from celery.signals import after_setup_logger@after_setup_logger.connect
def setup_loggers(logger, *args, **kwargs):formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# FileHandlerfh = logging.FileHandler('logs.log')fh.setFormatter(formatter)logger.addHandler(fh)# SysLogHandlerslh = logging.handlers.SysLogHandler(address=('logsN.papertrailapp.com', '...'))slh.setFormatter(formatter)logger.addHandler(slh)

策略2:重写Celery根记录器

您可以通过连接setup_logging信号来阻止Celery配置任何记录器。这使您可以完全用自己的配置重写日志配置。

python">import logging
import logging.config
from celery.signals import setup_logging@setup_logging.connect
def setup_logging(**kwargs):logfile = kwargs.get("logfile")loglevel = kwargs.get("loglevel")loglevel_str = logging.getLevelName(loglevel)config = {'version': 1,'disable_existing_loggers': False,'formatters': {'default': {'format': ' %(asctime)s - %(name)s - %(levelname)s - %(message)s','datefmt': "%Y/%m/%d %H:%M:%S"}},'handlers': {'rotatingHandler': {'class': 'logging.handlers.RotatingFileHandler','filename': logfile,'maxBytes': 2*1024*1024,'backupCount': 3,'formatter': 'default','encoding': 'utf-8'},'timedHandler': {'class': 'logging.handlers.TimedRotatingFileHandler','filename': logfile,'when': 'midnight','interval': 1,'backupCount': 7,'formatter': 'default','encoding': 'utf-8'},},'loggers': {'celery': {'handlers': ['timedHandler'],'level': loglevel_str,'propagate': False},},'root': {'handlers': ['rotatingHandler'],'level': loglevel_str,'propagate': False},}logging.config.dictConfig(config)

策略3:禁用Celery logger配置

另一种解决方案是让Celery设置其日志记录器但不使用它,并防止其劫持根日志记录器。
默认情况下,Celery会移除根日志记录器上任何先前配置的处理程序。如果你想自定义自己的日志处理程序而不被Celery干扰,可以通过设置worker_hijack_root_logger=False来禁用此行为。
这允许你重新控制根日志记录器并回退到标准的Python日志设置。
使用这种方法时要小心,因为你需要完全负责确保你的Python日志记录与Celery设置(eventlets、greenlets、prefork(子进程)、线程等)兼容。

python">import os
import logging
from celery import Celery
from celery.signals import setup_loggingapp = Celery('app')
app.conf.update({'worker_hijack_root_logger': False})formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger()# StreamHandler
sh = logging.StreamHandler()
sh.setFormatter(formatter)
logger.addHandler(sh)# FileHandler
fh = logging.FileHandler('logs.log')
fh.setFormatter(formatter)
logger.addHandler(fh)# SysLogHandler
slh = logging.handlers.SysLogHandler(address=('logsN.papertrailapp.com', '...'))
slh.setFormatter(formatter)
logger.addHandler(slh)

http://www.ppmy.cn/news/1559465.html

相关文章

Redis 数据类型全解析:基础与进阶应用场景

前言:Redis 是一个高性能的内存数据库,支持多种数据类型,能够高效处理各种场景的数据存储和操作。 以下是Redis数据类型的数据结构及其应用场景的详细说明: 基础数据类型 1. 字符串 (String) 底层数据结构 Simple Dynamic Stri…

我的软件架构师——Java 职位面试经历。

最近,我参加了一家领先的服务型公司的软件架构师(Java)职位的面试。我在这里分享了一些面试官问我的问题。我只列出了与 Java 相关的问题,因为本文主要关注 Java。面试官问我有关 AWS、Docker、Kubernetes、Kafka、Elastic Search、SQL/NoSQL 和设计模式的问题。 ClassNotF…

数据可视化-16. 日历图

目录 1. 日历图的概念 2. 日历图的适用场景 2.1 事件或活动的频率分析 2.2 数据的时间周期性分析 2.3 异常值检测 2.4 绩效监控 3. 日历图的缺陷 3.1 粒度受限于天数 3.2 数据密度过高时候难以解读 3.3 难以比较多个数据集 3.4 周期性较长的数据不易展示 4. 日历图…

PDF书籍《手写调用链监控APM系统-Java版》第6章 链路的架构(Trace+TraceSegment+Span)

本人阅读了 Skywalking 的大部分核心代码,也了解了相关的文献,对此深有感悟,特此借助巨人的思想自己手动用JAVA语言实现了一个 “调用链监控APM” 系统。本书采用边讲解实现原理边编写代码的方式,看本书时一定要跟着敲代码。 作者…

集成学习(模型融合)

简介 模型融合(Model Fusion),也被称为集成学习(Ensemble Learning),是一种将多个不同模型或算法结合在一起,通过一定的策略来进行预测或分类等任务的方法。这种技术能够帮助我们利用不同模型的…

抖去推碰一碰系统技术源码/open SDK转发技术开发

抖去推碰一碰系统技术源码/open SDK转发技术开发 碰一碰智能系统#碰碰卡系统#碰一碰系统#碰一碰系统技术源头开发 碰碰卡智能营销系统开发是一种集成了人工智能和NFC技术的工具,碰碰卡智能营销系统通过整合数据分析、客户关系管理、自动化营销活动、多渠道整合和个…

利用Dockerfile构建自定义镜像

当一个系统开发完成,需要将系统打包为一个镜像文件,让docker能够运行该镜像,成为一个可以被访问的容器。 上述操作可以通过自定义镜像的方式来实现,本文章基于VMware虚拟机中安装的Centos7操作系统来完成。前面的操作步骤&#x…

手机发烫怎么解决?

在当今这个智能手机不离手的时代,手机发烫成了不少人头疼的问题。手机发烫不仅影响使用手感,长期过热还可能损害手机硬件、缩短电池寿命,甚至引发安全隐患。不过别担心,下面这些方法能帮你有效给手机 “降温”。 一、使用习惯方面…