Расширенное форматирование задач в Flower (мониторинг сельдерея) - PullRequest
0 голосов
/ 21 декабря 2018

Я использую Flower для мониторинга своих задач Celery.

Я пытаюсь изменить способ отображения задач (на вкладке Tasks ), чтобы список выглядел немногоболее "организованный".К сожалению, , переопределяющий метод format_task , имеет ограничения:

  • task.args и task.kwargs являются строковыми представлениями, иногда усеченными - , очевидно, из-за сельдереяограничения событий - вместо list / dict
  • HTML экранируется для каждого поля, кроме task.name
  • , если функция не возвращает значение, ошибка AJAXбросается при отображении задач

Во-первых, я хотел бы скрыть / показать задачи в зависимости от их состояния (т. е. SUCCESS, FAILURE), чтобы можно было скрывать неважныеподзадачи, кроме случаев, когда они терпят неудачу.

Чем ближе я могу стать, так это установить все отображаемые поля в пустую строку:

if task.state == 'SUCCESS':
    task.name = ''
    task.args = ''
    # [...]
    task.runtime = 0.0

..., которая все еще отображает пустую строку.Знаете ли вы, как я мог достичь желаемого результата?


Во-вторых, я пытаюсь отформатировать способ отображения аргументов задачи.

Я конвертирую аргументы обратно в ихисходный тип, используя eval(task.args), чтобы потом я мог перебирать их элементы.Оценка случайных строк выглядит для меня немного небезопасно, вы бы порекомендовали лучший способ, чем делать это?

1 Ответ

0 голосов
/ 07 января 2019

Я нашел решение получить аргументы задачи в том виде, в котором они вызваны (list / dict) вместо строк.

Параметры argsrepr и kwargsrepr метода apply_async позволяют указатьпользовательские представления для аргументов задачи.

Я создал собственный класс Task , переопределяя метод delay следующим образом:

import json
from celery import Task

class FlowerTask(Task):
    def delay(self, *args, **kwargs):
        argsrepr, kwargsrepr = [], {}

        for arg in args:
            if isinstance(arg, bytes):
                argsrepr.append("<binary content>")
            elif isinstance(arg, list):
                argsrepr.append("<list ({} items)".format(len(arg)))
            else:
                ...

        for key, value in kwargs.items():
            ...

        # Create and call the task with the reprs we just built
        new_task = super().s(*args, **kwargs)
        return new_task.apply_async(argsrepr=json.dumps(argsrepr), kwargsrepr=json.dumps(kwargsrepr))

Затем я использую этот класс какбаза для моей задачи:

@shared_task(base=FlowerTask)
def test_task(*args, **kwargs):
    return "OK !"

Таким образом, представления аргументов задачи сохраняются в виде JSON, который я могу затем загрузить в format_task Flower и использовать их как объекты, а не строки:

def format_task(task):
    task.args = json.loads(task.args)

    if not task.args:
        task.args = "( )"
    else:
        task.args = ', '.join(arg for arg in task.args)
    # [...]

Я до сих пор не нашел способ скрыть задачи.Я думаю, что мне, возможно, придется настроить CSS из Flower.

...