Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

prevent duplicate celery logging

How do I prevent duplicate celery logs in an application like this?

# test.py
from celery import Celery

import logging

app = Celery('tasks', broker='redis://localhost:6379/0')
app.logger = logging.getLogger("new_logger")
file_handler = logging.handlers.RotatingFileHandler("app.log", maxBytes=1024*1024, backupCount=1)
file_handler.setFormatter(logging.Formatter('custom_format %(message)s'))
app.logger.addHandler(file_handler)

@app.task
def foo(x, y):
    app.logger.info("log info from foo")

I start the application with: celery -A test worker --loglevel=info --logfile celery.log

Then I cause foo to be run with python -c "from test import foo; print foo.delay(4, 4)"

This results in the "log info from foo" being displayed in both celery.log and app.log.

Here is app.log contents:

custom_format log info from foo

And here is celery.log contents:

[2017-07-26 21:17:24,962: INFO/MainProcess] Connected to redis://localhost:6379/0
[2017-07-26 21:17:24,967: INFO/MainProcess] mingle: searching for neighbors
[2017-07-26 21:17:25,979: INFO/MainProcess] mingle: all alone
[2017-07-26 21:17:25,991: INFO/MainProcess] celery@jd-t430 ready.
[2017-07-26 21:17:38,224: INFO/MainProcess] Received task: test.foo[e2c5e6aa-0d2d-4a16-978c-388a5e3cf162]  
[2017-07-26 21:17:38,225: INFO/ForkPoolWorker-4] log info from foo
[2017-07-26 21:17:38,226: INFO/ForkPoolWorker-4] Task test.foo[e2c5e6aa-0d2d-4a16-978c-388a5e3cf162] succeeded in 0.000783085000876s: None

I considered removing the custom logger handler from the python code, but I don't want to just use celery.log because it doesn't support rotating files. I considered starting celery with --logfile /dev/null but then I would loose the mingle and other logs that don't show up in app.log.

Can I prevent "log info from foo" from showing up in celery.log? Given that I created the logger from scratch and only setup logging to app.log why is "log info from foo" showing up in celery.log anyway?

Is it possible to get the celery MainProcess and Worker logs (e.g. Connected to redis://localhost:6379/0) to be logged by a RotatingFileHandler (e.g. go in my app.log)?

like image 628
JDiMatteo Avatar asked Jul 27 '17 03:07

JDiMatteo


1 Answers

Why is "log info from foo" showing up in celery.log?

The logging system is basically a tree of logging.Logger objects with main logging.Logger in the root of the tree (you get the root with call logging.getLogger() without parameters).

When you call logging.getLogger("child") you get reference to the logging.Logger processing the "child" logs. The problem is when you call logging.getLogger("child").info() the info message is delivered to the "child" but also to the parent of the "child" and to its parent until it arrives to the root.

To avoid sending logs to the parent you have to setup the logging.getLogger("child").propagate = False.

like image 106
Qeek Avatar answered Nov 18 '22 06:11

Qeek