Skip to content

feat: 支持多机实时日志上报,实现跨主机 agent 运行监控 #18

Description

@Camille1024

背景

当前 ui/ dashboard 的日志数据来源是本地文件系统agents/*/logs/run-*/),server 直接 fs.readdirSync 读取。这意味着:

  • dashboard 只能看到当前部署主机上跑出的 agent 日志
  • 如果多位成员各自在本地跑 blueprint-absorber,其他人的运行记录对 dashboard 完全不可见
  • 无法实现跨主机的统一进度监控

目标

不引入重量级外部数据库,以最小改动实现:任何成员在本地跑 agent,日志实时汇聚到部署在服务器上的 dashboard,所有人都能在同一个界面监控。

方案设计

总体思路

成员 A 本地 run.sh          成员 B 本地 run.sh
      │                            │
      │  每条 JSONL event           │
      ▼                            ▼
POST /api/ingest  ────────▶  dashboard server(服务器)
                                   │
                      写入本地文件(保持现有目录结构)
                                   │
                      WebSocket 推送给前端
                                   ▼
                             浏览器实时看到

原有文件结构完全不变,server 侧"读文件"逻辑无需修改,ingest 端点只是另一条写入路径。


改动一:agent 侧——run.sh 加上报 hook

在现有的 JSONL 解析 pipeline 末尾,每 emit 一行到本地 .jsonl 文件时,同时 POST 到远程 server:

# run.sh 新增环境变量(可选,不设则纯本地模式)
INGEST_URL="${KIP_INGEST_URL:-}"   # e.g. http://kip.opensii.ai:8081/api/ingest
INGEST_TOKEN="${KIP_INGEST_TOKEN:-}"

上报逻辑插入到现有 python 日志解析脚本中(约 10 行):

import urllib.request, os

INGEST_URL   = os.getenv("KIP_INGEST_URL", "")
INGEST_TOKEN = os.getenv("KIP_INGEST_TOKEN", "")

def ingest(row: dict):
    if not INGEST_URL:
        return
    payload = json.dumps({
        "agent":  meta["agent"],
        "runId":  RUN_TS,
        "hintFile": meta["hint_file"],
        "row":    row,
    }).encode()
    req = urllib.request.Request(
        INGEST_URL,
        data=payload,
        headers={"Content-Type": "application/json",
                 "Authorization": f"Bearer {INGEST_TOKEN}"},
        method="POST",
    )
    try:
        urllib.request.urlopen(req, timeout=3)
    except Exception:
        pass  # 上报失败不影响本地运行

每次 emit(...) 后调用 ingest(row),fire-and-forget,超时 3s,失败静默,不阻塞 agent。


改动二:server 侧——新增 /api/ingest 端点

// ui/server/src/routes/ingest.ts
POST /api/ingest
Body: { agent: string, runId: string, hintFile: string, row: object }
Auth: Bearer token(读环境变量 KIP_INGEST_TOKEN,为空则不校验)

逻辑:

  1. 校验 token(如果配置了)
  2. 确保 agents/<agent>/logs/<runId>/ 目录存在(mkdir -p
  3. 追加 rowagents/<agent>/logs/<runId>/absorber.jsonl
  4. 如果是第一条 event,写 meta.json(包含 agent/hintFile/startedAt)
  5. 如果 row.event === "session_end",更新 meta.json 的 completedAt/status
  6. 通过现有 WebSocket 机制广播这条 event 给正在查看该日志的前端连接

改动三:start.sh / 部署文档

新增可选环境变量说明:

KIP_INGEST_TOKEN=<随机字符串>   # server 侧设置,用于校验上报来源
KIP_INGEST_URL=http://<server>:8081/api/ingest   # 成员本地设置

两者都是可选的:不设 KIP_INGEST_URL 则纯本地模式,行为与现在完全一致。


改动范围

文件 变更
agents/blueprint-absorber/run.sh(python 内联脚本) ingest() 调用,约 +15 行
ui/server/src/routes/ingest.ts 新文件,约 +60 行
ui/server/src/index.ts 注册新路由,+2 行
ui/start.sh 新增环境变量说明注释

无数据库依赖,无第三方服务,不破坏现有本地工作流。

后续扩展(out of scope)

  • 支持 blueprint-prover 等未来 agent(run.sh 结构一致,同样适用)
  • ingest 端点加速率限制(防止异常打满磁盘)
  • dashboard 上显示"来源主机"字段,区分本地运行与远程上报

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions