You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将日志的ctx.payload.hits.total及错误消息传入Webhook Watcher转换脚本

问题描述

我有一个运行正常的Webhook Watcher,当日志中出现"Error"字样时会自动创建OTRS工单,当前配置如下:

{
  "trigger": {
    "schedule": {
      "interval": "1m"
    }
  },
  "input": {
    "search": {
      "request": {
        "search_type": "query_then_fetch",
        "indices": [
          "*"
        ],
        "rest_total_hits_as_int": true,
        "body": {
          "query": {
            "bool": {
              "must": [
                {
                  "query_string": {
                    "query": "Error"
                  }
                },
                {
                  "range": {
                    "@timestamp": {
                      "gte": "now-1m"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  },
  "condition": {
    "compare": {
      "ctx.payload.hits.total": {
        "gte": 1
      }
    }
  },
  "actions": {
    "create_otrs": {
      "transform": {
        "script": {
          "source": "return ['Ticket':['Queue':'Engineering Team','Priority':'P3','CustomerUser':'root','Title':'RESTCreateTest','State':'new','Type':'Incident'],'Article':['ContentType':'text/plain;charset=utf8','Subject':'RestCreateTest','Body':'This is only a test']]",
          "lang": "painless"
        }
      },
      "webhook": {
        "scheme": "http",
        "host": "myotrs.com",
        "port": 80,
        "method": "post",
        "path": "/otrs/GenericTicketConnectorREST/User=<User>&Pass=<Password>",
        },
        "headers": {},
        "body": "{{#toJson}}ctx.payload{{/toJson}}"
      }
    }
  }
}

目前工单内容固定为This is only a test,我希望将日志中的具体错误消息以及ctx.payload.hits.total(错误数量)传入工单内容中,请问如何在转换脚本中引用这些变量?

附日志文档示例:

{
  "_index": ".ds-logs-elastic_agent.filebeat-default",
  "_source": {
    "input_source": "https://ser.example.com:80/export",
    "agent": {
      "name": "syslog01",
      "id": "5836558b-b17d-445e",
      "type": "filebeat",
      "ephemeral_id": "36bdfeca-3c60",
      "version": "8.3.3"
    },
    "service.name": "filebeat",
    "log": {
      "file": {
        "path": "/opt/Elastic/Agent/data/elastic-agent-0ffbed/logs/default/filebeat-20230127-12.ndjson"
      },
      "offset": 248078415
    },
    "elastic_agent": {
      "id": "5836558b-b17d",
      "version": "8.3.3",
      "snapshot": false
    },
    "message": "\"\"\"Error while processing http request: failed to execute rf.collectResponse: failed to execute http client.Do: failed to execute http client.Do: Post \"https://ser.example.com:80/export\": POST https://ser.example.com:80/export giving up after 6 attempts\"\"\"",
    "log.logger": "input.httpjson-cursor",
    "input": {
      "type": "filestream"
    },
    "log.origin": {
      "file.line": 128,
      "file.name": "httpjson/input.go"
    },
    "@timestamp": "2023-01-27T14:44:42.790Z",
    "ecs": {
      "version": "8.0.0"
    },
    "data_stream": {
      "namespace": "default",
      "type": "logs",
      "dataset": "elastic_agent.filebeat"
    },
    "host": {
      "hostname": "syslog01",
      "os": {
        "kernel": "3.10.25-gentoo",
        "name": "Gentoo",
        "type": "linux",
        "family": "",
        "version": "",
        "platform": "gentoo"
      },
      "containerized": false,
      "log.level": "error",
      "input_url": "https://ser.example.com:8089/export",
      "id": "httpjson-system.security-ba2ec41b-457b-442a",
      "event": {
        "agent_id_status": "verified",
        "ingested": "2023-01-27T14:44:58Z",
        "dataset": "elastic_agent.filebeat"
      }
    },
    "_id": "pCWw84UB8FDLddfs",
    "_score": 2.2840834
  }
}
解决方案

修改transform中的Painless脚本,直接从ctx.payload提取所需数据,同时修正原配置的语法错误(webhook部分多余逗号),以下是完整修改后的配置:

{
  "trigger": {
    "schedule": {
      "interval": "1m"
    }
  },
  "input": {
    "search": {
      "request": {
        "search_type": "query_then_fetch",
        "indices": [
          "*"
        ],
        "rest_total_hits_as_int": true,
        "body": {
          "query": {
            "bool": {
              "must": [
                {
                  "query_string": {
                    "query": "Error"
                  }
                },
                {
                  "range": {
                    "@timestamp": {
                      "gte": "now-1m"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  },
  "condition": {
    "compare": {
      "ctx.payload.hits.total": {
        "gte": 1
      }
    }
  },
  "actions": {
    "create_otrs": {
      "transform": {
        "script": {
          "source": """
            // 获取错误总数
            int errorCount = ctx.payload.hits.total;
            // 拼接所有错误消息
            StringBuilder errorMessages = new StringBuilder();
            for (def hit : ctx.payload.hits.hits) {
              errorMessages.append("- ").append(hit._source.message).append("\\n\\n");
            }
            // 构建工单内容
            return [
              'Ticket': [
                'Queue': 'Engineering Team',
                'Priority': 'P3',
                'CustomerUser': 'root',
                'Title': '系统错误告警 - 共发现' + errorCount + '条错误',
                'State': 'new',
                'Type': 'Incident'
              ],
              'Article': [
                'ContentType': 'text/plain;charset=utf8',
                'Subject': '系统错误告警',
                'Body': '在过去1分钟内共发现' + errorCount + '条错误日志,详情如下:\\n\\n' + errorMessages.toString()
              ]
            ];
          """,
          "lang": "painless"
        }
      },
      "webhook": {
        "scheme": "http",
        "host": "myotrs.com",
        "port": 80,
        "method": "post",
        "path": "/otrs/GenericTicketConnectorREST/User=<User>&Pass=<Password>",
        "headers": {},
        "body": "{{#toJson}}ctx.payload{{/toJson}}"
      }
    }
  }
}

关键修改说明

  • 错误数量获取:直接通过ctx.payload.hits.total拿到本次查询到的错误日志总数,用于工单标题和内容。
  • 错误消息提取:遍历ctx.payload.hits.hits数组,每个元素的_source.message字段就是日志中的错误详情,将所有消息拼接成列表。
  • 工单内容动态生成:将错误数量和消息插入到工单的Title和Body中,替换原来的固定文本。
  • 语法修正:移除原配置中webhook.path后面的多余逗号,避免JSON解析错误。

内容的提问来源于stack exchange,提问作者mrin9san

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 14:50:21