14

I'd like a celery task to be able to get the name of the worker executing it, for logging purposes. I need to handle this from within the task, rather than querying the broker directly. Is there a way to do this? I'm using celery with RabbitMQ, if that matters.

imichaeldotorg
  • 459
  • 1
  • 4
  • 20

4 Answers4

9

Use the celeryd_after_setup signal to capture the worker name like this:

from celery.signals import celeryd_after_setup

@celeryd_after_setup.connect
def capture_worker_name(sender, instance, **kwargs):
    os.environ["WORKER_NAME"] = '{0}'.format(sender)
Teo Sibileau
  • 294
  • 2
  • 5
  • 1
    This should be the accepted answer, however I would put the name inside the celery config, and not in an environment variable – Mart10 Dec 20 '18 at 15:19
  • 1
    If you're using the `celery_worker` fixture to test, use the `worker_init` signal instead as `celeryd_after_setup` is not called in test. – Sirupsen Jan 20 '22 at 22:49
7

You need to utilize billiard which holds the workers:

from celery import task
from billiard import current_process

@task
def getName():
    p = current_process()
    return p.index

Then make a global dictionary that maps ids->names on process creation.

Roy Iacob
  • 412
  • 3
  • 13
  • 3
    This isn't quite what I was looking for. When you start a celery worker, you can give it a name (-n flag). I'm wondering if there is a way to get that name from within the task. – imichaeldotorg May 26 '14 at 17:46
  • 1
    not quite as straight forward but why not make a global dict of ids->names? – Roy Iacob May 27 '14 at 00:43
  • billiard is definitely the key, but this solution does not get the name, as requested. I added a small update in my answer. – cacois Aug 19 '14 at 12:57
7

I also needed the worker name for reporting purposes so I tried @cacois solution but it doesn't seem to work with eventlet (current_process() doesn't have an initargs attribute). So I'll leave my solution here for future references:

from celery import task

@task(bind=True)
def getName(self):
    return self.request.hostname

The name of the attribute sounds weird to me, but that contains the name specified with the "-n" option when launching the worker. self works like you would expect from a class method, you don't need to specify it when calling the function (eg: getName.delay()).

Adrian Macias
  • 95
  • 1
  • 1
3

You were originally looking for the name you put in with the -n flag, right? It's in the initargs array. Here's a modified version of the answer that gets you that:

from celery import task
from billiard import current_process

@task
def getName():
    p = current_process()
    return p.initargs[1].split('@')[1]
cacois
  • 2,036
  • 2
  • 19
  • 19
  • Unfortunately this seems to no longer work with recent celery versions. `current_process()` now returns a `ForkProcess` object, which has no `initargs`. – ForeverWintr Oct 04 '18 at 19:29