【问题标题】:Advanced task formatting in Flower (Celery monitoring)Flower 中的高级任务格式化(Celery 监控)
【发布时间】:2019-05-22 02:57:36
【问题描述】:

我使用 Flower 来监控我的 Celery 任务。

我正在尝试更改任务的显示方式(在 Tasks 选项卡下),以使列表看起来更“有条理”。例如,显示<list (6 items)> 而不是[1, 2, 3, ...

很遗憾,overriding the format_task method 有限制:

  • task.argstask.kwargs 是字符串表示,通常被截断,而不是 list/dict
  • 除了task.name之外的每个字段都对HTML进行了转义
  • 如果函数没有返回值,显示任务时会抛出 AJAX 错误

为了取回原始的 argskwargs 对象,我使用了 eval(task.args) 以便之后可以遍历它们的项目。评估随机字符串对我来说似乎有点不安全,你会推荐比这样做更好的方法吗?

【问题讨论】:

    标签: python task celery display flower


    【解决方案1】:

    我找到了一个解决方案,可以将 format_task 中的任务参数作为对象(列表/字典等)而不是截断的字符串表示形式。

    apply_async() 方法的 argsreprkwargsrepr 参数允许为任务的参数指定自定义表示。

    我创建了一个自定义 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)))
                elif isinstance(arg, dict):
                    argsrepr.append("<dict ({} keys)>".format(len(arg)))
                else:
                    # Format your args the way you prefer
                
            for key, value in kwargs.items():
                # Format your kwargs the same way as above
                # if ... :
                # kwargsrepr.append(...)
            
            # Create the task
            new_task = super().s(*args, **kwargs)
    
            # Use our representations as JSON
            return new_task.apply_async(
                argsrepr=json.dumps(argsrepr),
                kwargsrepr=json.dumps(kwargsrepr)
            )
    

    然后,我使用 base 参数将此类用作我的任务的基础:

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

    这样,任务的参数表示形式存储为 JSON,之后可以加载到 Flower 的 format_task() 中,并将它们用作对象而不是字符串:

    def format_task(task):
        argsrepr = json.loads(task.args)
        kwargsrepr = json.loads(task.kwargs)
    
        if not argsrepr:
            task.args = "( )"
        else:
            task.args = ', '.join(argsrepr)
    
        if not kwargsrepr:
            task.kwargs = "( )"
        else:
            task.kwargs = ', '.join(f'{key} = {value}' for key, value in kwargsrepr.items())
        # [...]
    

    这样,参数显示如下:

    参数: &lt;list (3 items)&gt;, &lt;binary content&gt;

    Kwargs: callback = &lt;function&gt;, items = &lt;dict (5 items)&gt;

    【讨论】:

      猜你喜欢
      • 2019-01-07
      • 2017-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-12
      相关资源
      最近更新 更多