After many days I have a working celery and celery beat task list, and the results are stored using django_celery_results. However when I look at the table record, it hasn't got any useful information in there.
is it possible to set the task id to something human readable?
one example would be using the demo task, it returns the no, but an unreadable task id
tasks.py
@app.task
def test(a,b):
return a + b
scheduler in app.settings
CELERYBEAT_SCHEDULE = {
'test_task': {
'task': 'home.tasks.test',
'schedule': crontab(minute='*/1'),
},
The easy answer is No. The task_id
attribute is generated automatically. If you follow the code backwards the core function that generates ID's is in kombu.utils.uuid.uuid(..)
, which interestingly is just a thin wrapper around the builtin uuid.uuid4(..)
.
However, if you look at the function signature:
def uuid(_uuid=uuid4):
"""Generate unique id in UUID4 format.
See Also:
For now this is provided by :func:`uuid.uuid4`.
"""
return str(_uuid())
..it appears like it would be possible to supply your own function that generates the ID, and as long as they're unique they should work. Fundamentally you'd have to patch: celery.__init__.uuid
, celery.utils.__init__.uuid
, and celery.utils.__init__.gen_unique_id
.
I don't think that you'd be able to apply worthwhile names since this function is called with no parameters to simply return something unique.
BUT
If you look at Task.apply
and Task.apply_async
there's an undocumented parameter task_id
!
This would allow you to manually specify the task_id
before the Task is called/created, and as long as they're globally unique you'll still get all of the reporting and metrics. Unfortunately I don't see any easy way to change the task_id
from a Result, to make it more useful after the fact...kinda making your UI's textbox a little silly.
If your project is set up for it, you can use Task Inheritance and modify task behavior that way. In theory you should be able to overwrite apply
and apply_async
to inject a task's ID.
import time
from celery import Task
class NamedTask(Task):
id_gen = lambda: int(time.time() * 1000)
def _gen_task_id(self):
return {
'task_id': '%s-%s' % (
self.name,
self.id_gen())}
def apply(self, *args, **kwargs):
kwargs.update(self._gen_task_id())
return Task.apply(self, *args, **kwargs)
def apply_async(self, *args, **kwargs):
kwargs.update(self._gen_task_id())
return Task.apply_async(self, *args, **kwargs)
@task(base=NamedTask)
def add(x, y):
return x + y
Should make your Task ID look like: project.tasks.add-15073315189870
Implement a custom result backend that overwrites _store_result
to decide what is saved as result to the database.
Depending on which backend you're using find the related class in celery.backends
.
This example extends the result for an amqp backend.
class UsefulInfoBackend(AMQPBackend):
def store_result(self, task_id, result, state,
traceback=None, request=None, **kwargs):
result = super(UsefulInfoBackend, self).store_result(task_id, result, state,
traceback=None, request=None, **kwargs)
result['useful_info'] = 'Very Useful! :)' # determine the rules for extraneous information here contains.
return result
When initializing Celery
pass your result backend class.
celery.Celery(backend=UsefulInfoBackend)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With