让 LLM Agent 替你跑三个平台:告警排查自动化的落地思路

2026-06-04 19 预计阅读时间:1 分钟
来源:my.oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:12 分钟

凌晨两点,手机弹出一条告警——服务 A 的 P99 延迟飙升到 3 秒。你爬起来打开日志平台搜关键词,切到 APM 看监控曲线,再跳到链路追踪系统查 trace 详情。三套系统来回切换,眼睛在五个标签页之间跳了十几轮,最终定位到:上游服务 B 在 01:58 发生了一次 GC 停顿,导致下游调用超时。一分钟后流量恢复正常,告警自愈。

整个过程花了 25 分钟,真正分析的时间不到 5 分钟,剩下的 20 分钟全耗在登录、搜索、拼凑分散在各平台的数据上。更扎心的是——同样的告警下个月还会再来,换个人排查可能要 40 分钟。

告警排查的真正瓶颈

传统排查流程的时间分布大致是这样的:

步骤 耗时 瓶颈
打开日志平台、搜索关键词 3-8 min 平台登录、索引延迟
切到 APM 查指标曲线 2-5 min 时间窗口对齐、指标筛选
进链路追踪看 trace 3-10 min trace ID 关联、详情展开
综合判断根因 2-5 min 依赖经验,容易遗漏

核心矛盾不是"分析难",而是数据散落在三个系统里,人成了数据搬运工。经验丰富的工程师能快速跳过无效信息,新手则容易在日志海洋里迷失——同一个告警,排查效率可以差 3 倍以上。

Agent 能做什么:把"搬运"交给机器

LLM Agent 在这个场景的价值很明确:代替人完成跨平台的数据采集和初步关联,把散落的信息拼成一份结构化的排查报告

具体来说,一个告警排查 Agent 可以:

  1. 接收告警事件,自动提取关键字段(服务名、时间窗口、异常指标)。
  2. 并行调用多个工具——日志搜索、指标查询、trace 检索——把原本需要人手动切换的步骤变成并行请求。
  3. 交叉关联——用 trace ID 把日志和链路追踪串起来,用时间窗口把指标和日志对齐。
  4. 生成初步结论——"上游 GC 停顿导致下游超时,持续时间 1 分钟,已自愈"。

人只需要看最终报告,确认结论或补充细节。10-30 分钟的排查压缩到 2-3 分钟。

搭建一个最小可用的告警排查 Agent

下面用一个简化的 Python 示例演示核心逻辑。基于 OpenAI function calling + 自定义工具,不依赖任何 Agent 框架,方便你直接改造接入自己的平台。

定义工具:日志、指标、链路追踪

import json
import openai

# --- 工具定义 ---
tools = [
    {
        "type": "function",
        "function": {
            "name": "search_logs",
            "description": "在日志平台搜索指定服务在指定时间窗口的关键词日志",
            "parameters": {
                "type": "object",
                "properties": {
                    "service": {"type": "string", "description": "服务名,如 order-service"},
                    "keyword": {"type": "string", "description": "搜索关键词,如 timeout、error"},
                    "start_time": {"type": "string", "description": "开始时间,ISO 8601 格式"},
                    "end_time": {"type": "string", "description": "结束时间,ISO 8601 格式"},
                },
                "required": ["service", "keyword", "start_time", "end_time"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "query_metrics",
            "description": "查询 APM 平台指定服务的指标曲线",
            "parameters": {
                "type": "object",
                "properties": {
                    "service": {"type": "string", "description": "服务名"},
                    "metric": {"type": "string", "description": "指标名,如 p99_latency、error_rate"},
                    "start_time": {"type": "string", "description": "开始时间"},
                    "end_time": {"type": "string", "description": "结束时间"},
                },
                "required": ["service", "metric", "start_time", "end_time"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_trace_detail",
            "description": "根据 trace ID 获取链路追踪详情",
            "parameters": {
                "type": "object",
                "properties": {
                    "trace_id": {"type": "string", "description": "链路追踪 ID"},
                },
                "required": ["trace_id"],
            },
        },
    },
]

工具执行层:对接你的真实平台

这里用模拟数据演示,实际部署时替换成你公司的 API 调用:

# --- 工具执行(模拟,实际替换为真实 API 调用) ---
def execute_tool(name: str, args: dict) -> str:
    if name == "search_logs":
        # 实际: 调用 Elasticsearch / Loki API
        return json.dumps({
            "total": 12,
            "hits": [
                {"timestamp": "2024-01-15T01:58:03Z", "level": "ERROR",
                 "message": "upstream timeout: service-B /api/data took 3200ms"},
                {"timestamp": "2024-01-15T01:58:04Z", "level": "WARN",
                 "message": "retrying call to service-B, attempt 2/3"},
            ],
            "trace_ids": ["trace-abc123", "trace-def456"],
        })

    if name == "query_metrics":
        # 实际: 调用 Prometheus / Grafana API
        return json.dumps({
            "service": args["service"],
            "metric": args["metric"],
            "datapoints": [
                {"time": "01:57", "value": 120},
                {"time": "01:58", "value": 3200},  # 延迟飙升
                {"time": "01:59", "value": 150},
                {"time": "02:00", "value": 110},    # 恢复
            ],
        })

    if name == "get_trace_detail":
        # 实际: 调用 Jaeger / SkyWalking API
        return json.dumps({
            "trace_id": args["trace_id"],
            "root_span": {"service": "service-B", "operation": "/api/data",
                          "duration_ms": 3200, "status": "ERROR"},
            "spans": [
                {"service": "service-B", "operation": "GC pause",
                 "duration_ms": 2800, "tags": {"gc.type": "Full"}},
            ],
        })

    return json.dumps({"error": f"unknown tool: {name}"})

Agent 主循环:让 LLM 自主编排工具调用

# --- Agent 主循环 ---
client = openai.OpenAI()  # 需设置 OPENAI_API_KEY

def run_alert_agent(alert_event: str, max_rounds: int = 5) -> str:
    """接收告警描述,自动排查并返回结论"""

    messages = [
        {
            "role": "system",
            "content": (
                "你是一个告警排查助手。根据告警信息,依次调用日志搜索、指标查询、"
                "链路追踪工具来收集数据,然后综合分析给出根因结论。"
                "结论格式:根因、影响范围、持续时间、是否自愈、建议动作。"
            ),
        },
        {"role": "user", "content": alert_event},
    ]

    for _ in range(max_rounds):
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            tools=tools,
            tool_choice="auto",
        )

        msg = response.choices[0].message

        # 如果 LLM 不再调用工具,说明分析完成
        if not msg.tool_calls:
            return msg.content or "排查完成,但未生成结论。"

        # 执行所有工具调用(可并行,这里简化为顺序执行)
        messages.append(msg)
        for tc in msg.tool_calls:
            result = execute_tool(tc.function.name, json.loads(tc.function.arguments))
            messages.append({
                "role": "tool",
                "tool_call_id": tc.id,
                "content": result,
            })

    return "排查轮次超限,请人工介入。"

运行示例

# --- 运行 ---
alert = """
告警事件:
- 服务: order-service
- 时间: 2024-01-15 01:57 ~ 02:00
- 异常: P99 延迟从 120ms 飙升至 3200ms,错误率同步上升
- trace 样本: trace-abc123
请排查根因。
"""

report = run_alert_agent(alert)
print(report)

预期输出类似:

根因:上游服务 service-B 在 01:58 发生 Full GC 停顿(耗时 2800ms),
导致下游 order-service 调用 /api/data 超时。

影响范围:order-service 的 /api/data 接口,P99 延迟峰值 3200ms。
持续时间:约 1 分钟(01:58 ~ 01:59)。
是否自愈:已自愈,02:00 指标恢复正常。
建议动作:无需紧急干预;建议优化 service-B 的 GC 配置,
考虑增大堆内存或切换到 G1/ZGC 收集器以减少 Full GC 频率。

execute_tool 里的模拟数据换成你公司的真实 API——Elasticsearch 的 _search、Prometheus 的 /api/v1/query_range、Jaeger 的 /api/traces/{traceID}——Agent 就能跑在生产环境了。

落地时需要留意的几个坑

工具返回的数据量要控制。 日志搜索返回 500 条原始日志,LLM 上下文窗口会被撑爆,token 费用也会飙升。在工具层做预聚合:只返回统计摘要(错误数、Top5 错误消息、关联 trace ID 列表),而不是原始日志全文。

Agent 不适合做最终决策。 它擅长数据采集和初步关联,但"是否需要扩容""是否要回滚"这类决策应该由人确认。把 Agent 的输出定位为"排查报告 + 初步结论",而不是"自动修复指令"。

敏感信息要脱敏。 日志里经常有用户 ID、手机号、内部 IP。在 execute_tool 层做字段过滤,不要把原始数据直接喂给 LLM——尤其是用第三方 API 的时候。

冷启动问题。 Agent 第一次面对某种新告警类型时,可能不知道该查什么关键词、看什么指标。解决方案:维护一份告警类型 → 排查策略的映射表,作为 system prompt 的一部分注入,让 Agent 有"经验"可参考。

上线 Checklist

  • [ ] 三个平台的 API 已打通,工具层能稳定返回结构化数据
  • [ ] 工具层做了数据量裁剪和敏感字段脱敏
  • [ ] Agent 输出只作为排查报告,不触发自动修复动作
  • [ ] 常见告警类型的排查策略已整理成 prompt 知识库
  • [ ] 设置了 max_rounds 上限,防止 Agent 无限循环调用工具
  • [ ] 每次排查结果存入历史库,用于后续评估 Agent 准确率
  • [ ] 先在低优先级告警上试跑两周,对比人工排查耗时和结论准确率

告警排查不是最难的工程问题,但它是最耗日常精力的重复劳动之一。Agent 不替代判断,但它能把 20 分钟的数据搬运压缩到 30 秒——剩下的时间留给真正需要人做的决策。


相关推荐