尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Yao 进程级监控服务(Monitor)实战指南:Watcher 注册、告警分级与健康检查

发布时间:2026/9/28 18:21:07

资讯中心
01
ARTICLE

Yao 进程级监控服务(Monitor)实战指南:Watcher 注册、告警分级与健康检查

Yao 进程级监控服务(Monitor)实战指南:Watcher 注册、告警分级与健康检查
Agent 框架后端低代码RAG【免费下载链接】yao✨ All your agents and workspaces in one place, on every device you own. Track tasks on a board, accessible from desktop, mobile, browser, or API. Self-hosted.项目地址https://gitcode.com/gh_mirrors/ya/yao点击查看免费下载Yao 的monitor包是一个进程级检查服务它负责调度周期性健康检查Watcher并记录异常本身不包含任何业务逻辑——检查什么、如何判定、采取什么动作全部由业务层定义。本文以 monitor/README.md 为核心结合 monitor 包源码与仓库内真实调用方完整讲解如何在 Yao 中实现自定义 Watcher、配置告警级别、通过 Alert Action 自动修复、订阅告警并读取运行健康状态。Monitor 的设计定位Yao 是一个自托管的 Agent 与工作区平台其内部运行着沙箱容器、机器人任务等大量有状态组件。这些组件需要持续的健康巡检容器是否空闲超时、任务是否变成僵尸进程、状态是否发生切换。monitor包承担了这一职责其设计原则非常明确It knows nothing about business logic — the business layer defines what to check, how to judge, and what action to take.它不感知任何业务逻辑——业务层决定检查什么、如何判定、采取什么动作。这种调度框架与业务解耦的架构体现在三个核心抽象上Watcher 接口业务模块实现检查什么与多久检查一次Alert一次检查的产出携带级别、目标、消息与可选的修复动作monitorService统一注册、调度、分发、记录与业务完全无关。monitor包源码仅 5 个文件types.go、service.go、logger.go、service_test.go 与 README实现极其精简便于任何业务模块以极低成本接入。快速开始实现并注册一个 Watcher第一步实现 Watcher 接口Watcher 是一个仅有三个方法的 Go 接口见 monitor/types.gotype Watcher interface { // Name 返回全局唯一的 watcher 名称用于日志与去重。 Name() string // Interval 返回检查频率。 Interval() time.Duration // Check 执行一次检查并返回发现的告警空切片表示一切正常。 // ctx 在 monitor 停止时被取消。 Check(ctx context.Context) []Alert }仓库 README 中的最小示例沙箱巡检场景package sandbox import ( context time github.com/yaoapp/yao/monitor ) type sandboxWatcher struct{} func (w *sandboxWatcher) Name() string { return sandbox } func (w *sandboxWatcher) Interval() time.Duration { return 30 * time.Second } func (w *sandboxWatcher) Check(ctx context.Context) []monitor.Alert { // 检查容器、对比状态、检测空闲超时等 // 一切正常时返回空切片 return nil }值得注意的是Check()的ctx语义它并非仅仅传递超时而是由 monitor 的停止流程触发的取消信号。测试 service_test.goTestContextCancelledDuringCheck验证了这一点——一个耗时的Check()在Stop()后能通过ctx.Done()感知取消否则Stop()会一直等待该 watcher 结束。因此长耗时的 Check 实现必须监听ctx否则可能阻塞引擎卸载。第二步通过 init() 注册func init() { monitor.Register(sandboxWatcher{}) }注册发生在monitor.Start()被调用之前。由于init()在包加载阶段执行Watcher 会在引擎启动时被自动拾取。从 service.go 的Register实现可以看到两个值得注意的行为同名替换注册同名 Watcher 会替换旧实例若旧实例已在运行其 goroutine 会被先取消old.cancel()运行中注册Register对已启动状态做了兼容——Start()之后再注册的 Watcher 也会立即启动这一点被TestRegisterAfterStartservice_test.go专门覆盖为动态加载业务模块提供了可能。第三步无需关心调度引擎在加载/卸载期间自动调用monitor.Start()/monitor.Stop()见 engine/load.go 与 engine/load.go。你只需完成上述两步Watcher 的Check()就会在自己的 goroutine中按指定间隔被调用。从 service.go 的runLoop可以看出调度细节每个 watcher 启动后立即执行一次首次检查不等第一个 tick随后按time.Ticker周期执行并在收到ctx.Done()时优雅退出。这意味着无论间隔多长Watcher 都能在进程启动后第一时间完成一次快照式巡检。告警级别Alert LevelsAlert携带的Level用于表达严重程度定义见 monitor/types.go级别常量典型用途Tracemonitor.Trace心跳、周期性状态同步、例行检查Infomonitor.Info值得注意的事件状态变更、服务注册Warnmonitor.Warn需要关注空闲超时、状态降级Errormonitor.Error需要立即处理崩溃、不可达选哪个级别完全由业务 Watcher 决定——monitor 只负责记录被告知的内容。所有级别都会通过Subscribe()送达订阅者。按运行模式过滤日志级别写入monitor.log的最低级别取决于 Yao 的运行模式YAO_ENV对应 logger.go 中initLogger的逻辑模式最低级别效果productionInfoTrace 告警不写入日志文件developmentTrace所有内容均写入源码中slogLevelTrace slog.Level(-8)logger.go为 Trace 定义了低于 slog 内置级别的自定义级别levelToSloglogger.go将业务级别映射到 slog 级别。生产模式借助slog.HandlerOptions{Level: minLevel}在 Handler 层直接过滤 Trace保持日志精简同时开发模式给出全量可见性。告警动作Alert Actions巡检即修复一个 Alert 可以携带Action—— 一个由 monitor 在本次 tick 内同步执行的函数。README 中的示例monitor.Alert{ Level: monitor.Warn, Target: box:abc123, Message: idle timeout exceeded, stopping, Action: func(ctx context.Context) { box.Stop(ctx) }, }关于 Action 的执行语义README 明确了三点源码亦有对应实现同步执行execActionservice.go在 watcher 的 goroutine 内直接调用a.Action(ctx)panic 恢复execAction内部有defer/recover某个 Action panic 只记录 Error 日志action panic同 tick 内后续告警继续处理相互隔离长耗时 Action 只阻塞本 watcher的下一个 tick不影响其他 watcher每个 watcher 独立 goroutine。这一机制使发现即修复成为可能巡检发现问题后直接在同一个 tick 内完成修复动作无需外部介入。API 一览monitor包对外暴露的完整 API见 service.go// 注册一个 watcher在 Start 前调用通常在 init 中。 monitor.Register(w Watcher) // 启动 monitor由引擎调用。 monitor.Start(ctx context.Context) error // 停止 monitor由引擎调用。 monitor.Stop() error // 订阅告警通知返回订阅 ID。 // 非阻塞channel 已满时该订阅者的告警会被丢弃。 monitor.Subscribe(ch chan- *monitor.Alert) string // 按 ID 取消订阅。 monitor.Unsubscribe(id string) // 返回 monitor 及所有 watcher 的运行状态。 monitor.Health() HealthStatus补充几个源码层面的 API 细节Start幂等保护重复调用Start()会返回错误monitor: already startedservice.go测试TestDoubleStartErrorservice_test.go验证了该行为而Stop()在未启动时调用则是安全的空操作TestStopWithoutStart。GetWatcher(name string)一个 README 未列出的辅助函数可按名称取回已注册的 Watcher 实例service.go。Subscribe的订阅 ID形如sub-1、sub-2的自增序列service.go用于后续Unsubscribe。非阻塞投递notifyservice.go用select { case ch - a: default: }实现非阻塞投递——订阅者消费不及时导致 channel 满时告警被静默丢弃不会阻塞巡检循环。TestSubscribeFullChanDropsservice_test.go专门验证了这一点面对高频告警洪泛monitor 绝不因慢订阅者而卡死。健康检查Health Checkstatus : monitor.Health() // status.Running — monitor 是否在运行 // status.Watchers — 每个 watcher 的统计 // .Name — watcher 名称 // .Interval — 检查频率 // .LastTick — 上一次 tick 完成时间 // .LastAlerts — 上一次 tick 产生的告警数 // .TotalTicks — 启动以来的总 tick 数 // .Panics — 捕获到的 panic 总数HealthStatus与WatcherHealth结构定义在 service.go并带有 JSON tagjson:name、json:last_tick等可直接序列化输出。健康状态由watcherEntry中的多个原子计数器维护service.golastTick、lastAlerts、totalTicks、panics均为atomic.Int64无需加锁即可安全并发读取每个 tick 结束后defer中统一更新totalTicks与lastTickservice.go即使Check()panic 也会完成更新。健康判定标准一个 watcher 被视为健康当且仅当LastTick距离当前时间在Interval × 3以内。也就是说若连续多个周期未完成 tick如被长任务阻塞或进程卡死该 watcher 即判定为不健康。日志体系LoggingMonitor 写入独立的logs/monitor.log与application.log分离由 logger.go 中独立的slog.Logger负责。写入规则生命周期事件Infomonitor 启动/停止、watcher 启动/停止Warn/Error 告警始终写入并携带 watcher 名称、target 与消息Info 告警生产与开发模式均写入Trace 告警仅开发模式写入生产模式跳过Panic始终以 Error 级别写入。日志轮转使用 lumberjack 库配置为50 MB 单文件、保留 3 个备份、最长 7 天见 logger.go 的lumberjack.Logger参数。日志格式由YAO_LOG_MODE决定JSON时使用slog.NewJSONHandler否则使用slog.NewTextHandlerlogger.go。日志目录在启动时自动创建MkdirAll(logDir, 0755)。Panic 安全Panic Safety巡检代码难免出现运行时异常monitor 为此提供了两层防御Check()panic由tick的defer/recover捕获service.go记录watcher panicError 日志watcher 在下一个 tick 继续运行不会因一次 panic 而永久退出Action()panic由execAction的defer/recover捕获service.go记录action panic日志同 tick 内剩余告警继续处理计数可观测panic 总数通过Health().Watchers[].Panics暴露。测试TestPanicRecovery_Checkservice_test.go证明第一次 Check panic 后watcher 仍持续执行后续检查count 持续增长TestPanicRecovery_Action与TestHealth_PanicCount则分别验证了 Action panic 的恢复与计数逻辑。源码级架构剖析一次完整巡检的内部流程结合 service.go 的完整实现一次巡检的完整链路如下启动Start(ctx)初始化 logger依据config.Conf.Root、LogMode、Mode创建可取消的根 context并为每个已注册 watcher 调用startWatcher启动独立 goroutineservice.go调度runLoop立即执行首次tick随后由time.NewTicker(interval)周期驱动ctx.Done()时退出service.go巡检tick调用Check(ctx)统计告警数并为每条告警补齐Watcher来源名service.go——测试TestAlertWatcherName验证了 alert 的Watcher字段由 monitor 自动填充记录告警按级别过滤后写入日志service.go动作若带Action则同步执行带 panic 保护分发notify非阻塞地推送给所有订阅者停止Stop()取消 context、等待所有 watcher goroutine 结束wg.Wait()再记录停止日志service.go。引擎在加载/卸载流程中分别触发Start/Stopengine/load.go、engine/load.go因此业务模块只需完成注册生命周期完全由框架接管。仓库内真实应用案例monitor 并非纸面框架仓库中已有两个生产级调用方可直接作为最佳实践参考案例一Sandbox 容器巡检sandbox/v2/watcher.gosandboxWatcher以 30 秒为周期巡检所有沙箱容器覆盖三类场景状态切换告警容器状态变化如idle → running产生 Info 告警恢复运行时重置心跳时间Touch长驻容器生命周期LongRunning策略下生命周期过期且超过宽限期DefaultLifetimeGrace时产生 Warn 告警并携带Action: mgr.Remove(ctx, b.id)直接移除容器若刚活跃则降级为 Info 延迟删除OneShot 安全网一次性容器超过DefaultOneShotMaxAge仍存在说明清理失败如进程崩溃时Warn Action 强制按创建时间移除避免误杀仍在执行的容器空闲超时回收Session/LongRunning 策略容器空闲超时后分别以mgr.Remove/b.Stop作为 Action 完成回收。这个案例完整展示了 README 所述三种能力状态对比、分级告警、Action 自动修复的落地方式。案例二机器人任务巡检agent/robot/watcher.gorobotTasksWatcher默认每 5 分钟巡检一次通过WatcherConfig提供可调参数MaxRunDuration4 小时、WaitingTimeout24 小时、ConfirmTimeout1 小时检查三类异常任务僵尸运行任务运行超时且已不在内存执行控制器跟踪范围内Warn 告警 Action 通过模型条件更新CAS将记录标记为 Failed等待超时任务超过 24 小时仍处于 waitingWarn 告警 Action 标记为 Cancelled确认超时任务超过 1 小时仍处于 confirmingInfo 告警 Action 标记为 Cancelled。该案例示范了 Watcher 如何结合数据存储层store.ExecutionStore与模型层model.Select完成业务巡检并通过init()注册、defaultConfig提供默认参数。文件结构monitor/ ├── DESIGN.md — 架构与设计决策 ├── README.md — 本文档 ├── types.go — Level、Alert、Watcher 接口 ├── logger.go — 独立的 slog.Logger → monitor.log ├── service.go — Register、Start、Stop、Subscribe、Health └── service_test.go — 单元测试调度、panic 恢复、订阅、健康状态整个包对外暴露的入口集中在 service.go类型定义在 types.go日志行为在 logger.go测试覆盖度极高调度、双启动、panic 恢复、订阅去重、满 channel 丢弃、运行中注册、健康统计等。若需为 Yao 的新业务模块如新的后台组件、外部服务连通性增加进程级健康巡检参照 sandbox/v2/watcher.go 的模式实现Watcher接口、init()注册、按需携带Action即可无缝接入统一的巡检、告警、日志与健康观测体系。赞分享Agent 框架后端低代码RAG【免费下载链接】yao✨ All your agents and workspaces in one place, on every device you own. Track tasks on a board, accessible from desktop, mobile, browser, or API. Self-hosted.项目地址https://gitcode.com/gh_mirrors/ya/yao点击查看免费下载相关推荐ACI.dev健康检查服务状态监控与告警ACI.dev健康检查服务状态监控与告警 ACI.dev作为连接AI智能体与600工具集成的开源平台其服务稳定性直接影响智能体的运行可靠性。本文将详细介绍后端前端MCP 服务工具调用AI 应用API网关人工智能AllData监控体系服务健康检查与告警AllData监控体系服务健康检查与告警 引言大数据平台的监控挑战 在大数据平台运维中你是否经常遇到以下痛点 服务突然宕机业务中断后才被发现 系统资源大数据数据工程数据集成数据治理数据可视化后端前端Apache Iceberg与AWS Glue集成实战构建现代化数据湖的完整步骤Apache Iceberg与AWS Glue集成实战构建现代化数据湖的完整步骤 AWS Glue作为强大的ETL服务与Apache Iceberg这一开源创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。