feat: 模型健康/熔断态 surface 到管理端(T4.F 可观测)
failover/熔断的运行时态原来只在 dispatcher 日志、admin 看不到 —— 本次接到概览可见:
- harness: CircuitBreaker.Snapshot() 只读观测访问器(state + fails,不动状态机)
- llm: Pool.ModelHealth() 上报主备链每模型 {provider,model,role,state,fails};
buildWithFallbacks 把模型名↔breaker 配对(同包直接读 failoverModel.breakers);
newFailoverModel 改返回具体类型以便读 breakers
- dispatcher 心跳 payload 加 models[]
- gateway /admin/overview 独立超时 Ping dispatcher,合并进 models.health
- admin 概览「模型路由」新增「运行时链路态(实时)」:逐模型状态点
(🟢在线/🔴熔断中+失败数/🟡半开探测/单点)
- 单测:Snapshot、Pool.ModelHealth(名字↔态配对/单点/空)
- live:配坏主→提交任务打熔断→概览显示 broken-demo「熔断中·失败3」,备用在线
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -119,6 +119,30 @@ func (h *Handler) AdminOverview(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// 模型运行时健康态:Ping dispatcher 心跳取每模型 failover/熔断态(在线/熔断中/半开)。
|
||||
// 权威配置来自 DB(上面 chat/emb),运行时态只有 dispatcher 知道 → 二者互补。
|
||||
modelHealth := []gin.H{}
|
||||
dctx, dcancel := context.WithTimeout(ctx, 2*time.Second) // 独立超时,不与 mcp-go 探活共用 cctx(避免被挤掉)
|
||||
defer dcancel()
|
||||
if data, err := h.bus.Ping(dctx, contract.SubjectHealthDispatcher); err == nil && len(data) > 0 {
|
||||
var dh struct {
|
||||
Models []struct {
|
||||
Provider string `json:"provider"`
|
||||
Model string `json:"model"`
|
||||
Role string `json:"role"`
|
||||
State string `json:"state"`
|
||||
Fails int `json:"fails"`
|
||||
} `json:"models"`
|
||||
}
|
||||
if json.Unmarshal(data, &dh) == nil {
|
||||
for _, m := range dh.Models {
|
||||
modelHealth = append(modelHealth, gin.H{
|
||||
"provider": m.Provider, "model": m.Model, "role": m.Role, "state": m.State, "fails": m.Fails,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"users": users, "kb_count": kbs, "kb_docs": docs,
|
||||
"tasks_today": ov.TasksToday, "tasks_total": ov.TasksTotal,
|
||||
@@ -127,6 +151,7 @@ func (h *Handler) AdminOverview(c *gin.Context) {
|
||||
"models": gin.H{
|
||||
"chat_count": len(chat), "embedding_count": len(emb),
|
||||
"active_chat": activeChat, "active_embedding": activeEmb, "fallbacks": fallbacks,
|
||||
"health": modelHealth, // 运行时每模型 failover/熔断态
|
||||
},
|
||||
"prompts": gin.H{"managed": len(prompts.Known), "overrides": len(overrides)},
|
||||
"services": services,
|
||||
|
||||
Reference in New Issue
Block a user