Django + Celery日志记录:自定义处理程序在主进程中工作,但在celery工作进程中不工作

kulphzqa  于 2023-08-08  发布在  Go
关注(0)|答案(1)|浏览(120)

关于这个主题有很多资源,但不幸的是没有一个有效。
1.以下是我的django日志设置:

LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
    "default": {
        "format": "[%(asctime)s: %(levelname)s/%(processName)s] [%(name)s] %(message)s"
    }
},
"filters": {"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"}},
"handlers": {
    "console": {
        "level": "INFO",
        "class": "logging.StreamHandler",
        "formatter": "default",
    },
    "mail_admins": {
        "level": "ERROR",
        "filters": ["require_debug_false"],
        "class": "django.utils.log.AdminEmailHandler",
    },
    "my_custom_handler": {
        "level": "INFO",
        "class": "my_custom_handler_class",
    },
},
"loggers": {
    "django.request": {
        "handlers": ["mail_admins"],
        "level": "ERROR",
        "propagate": True,
    },
    "": {
        "handlers": ["console", "my_custom_handler"],
        "level": "INFO",
        "propagate": True,
        "formatter": "default",
    },
    "celery": {
        "handlers": ["console", "my_custom_handler"],
        "level": "INFO",
        "propagate": True,
    },
},

字符串
}

  1. Celery是在导入www.example.com/初始化设置之前初始化的(这可能是罪魁祸首),我在celery任务中用于登录的记录器是base.py
    第一个月
    1.我尝试设置CELERYD_HIJACK_ROOT_LOGGER = False,使用after_setup_task_logger信号(我尝试打印以查看该信号是否被调度,但它没有),它们都没有任何效果
    1.我尝试使用setup_logging,它可以工作:
@setup_logging.connect
def config_loggers(*args, **kwags):
   my_handler = MyCustomHandler()
   root_logger = logging.getLogger()
   root_logger.addHandler(my_handler)
   root_logger.level = logging.INFO

@worker_process_init.connect
def init_worker(**kwargs):
    logger = get_task_logger(__name__) # or Logger.get_logger(__name__), no difference

    logger.info("My log message")


我说它有点工作,只是因为当我在init_worker中检查记录器对象的时,我看到处理程序在那里,但它不在记录器的处理程序中,而且它似乎没有传播(即我没有看到日志消息)。只有当我直接将处理程序附加到记录器对象时,我才能看到消息,但很明显,这样做的问题是,每当我在新文件中声明一个记录器时,我都必须附加处理程序,这是没有意义的。

c3frrgcw

c3frrgcw1#

如果你使用prefork的默认Celery worker_pool选项,那么如果你的自定义处理程序做了一些不“fork安全”的事情(比如启动一个线程),那么fork的worker子进程将不会像预期的那样运行。
例如,fluent-logger提供了fluent.asynchandler.FluentHandler,它创建了一个异步发送器来启动一个线程--如果这个线程已经在父进程celery中启动,那么分叉的子进程认为他们不需要启动一个线程,但实际上这个线程在分叉时被杀死了。
这意味着任何来自子进程的日志记录都不会被发送,最终fluent-logger队列会满,要么被阻塞,要么被丢弃。
有关详细信息,请参阅本期。

相关问题