feat(gateway,admin-web): 可观测面从轮询改为 WS 帧推送(裁决 05.4.3 + 16.4.3-WS)
- 新增三个下行帧(纯新增,既有帧名/形状零改动):observability_log / observability_trace /
observability_metrics,各带 ≤1s 节拍、无新数据不发帧、单帧上限(日志 200 / span 100)
- 帧壳 {type,data} 不带 sessionId;**不进 frameReachesAll 白名单** ⇒ fail-closed 只发 owner+admin
(变异验证两次:加进白名单 → viewer 用例必红)
- 推送开启条件=owner/admin 凭据「读过一次」对应 REST(引导数据仍由该次读取返回),
连接全断即退订并停循环(无常驻 goroutine);既有 REST 端点路径/RBAC/形状完全不变
- 前端:删除 logs/metrics/trace 三处 useAutoReload 轮询;新增 observabilityStream(引导+去重合并+窗口)
与 observabilityViews(三个面板 + WS 徽标),长列表统一走已落地的 VirtualList
- 复核:build/vet 绿 + gateway 全包测试绿(含真 bus→真 /ws/chat 三角色帧断言)+ `-race`;
前端 tsc 0 错 + vite build 成功
- 待登记契约:api-client 需新增「可观测实时推送」一节
This commit is contained in:
1 parent
74b12d87ca
commit
0e1f163ef9
10 files changed
+1449
-312
No files matched your search
@@ -26,6 +26,9 @@ type observability struct {
|
||||
metrics *MetricsCollector
|
||||
traceBuf *RingBuffer
|
||||
audit AuditStore
|
||||
// watches 是日志/指标/trace 推送的订阅登记(裁决 05.4.3 + 16.4.3-WS)。
|
||||
// 没有订阅者时推送循环不运行,见 observability_push.go。
|
||||
watches obsWatches
|
||||
// logBuf 是管理日志尾部端点背后的 logger 日志环形缓冲。
|
||||
// 组合根在网关存在后经 SetLogBuffer 注入它;在那之前
|
||||
// 该端点返回 501,而不是空但虚假的尾部。
|
||||
@@ -38,6 +41,7 @@ func newObservability(deps Deps) *observability {
|
||||
obs := &observability{
|
||||
metrics: newMetricsCollector(),
|
||||
traceBuf: newRingBuffer(defaultTraceBufCap),
|
||||
watches: newObsWatches(),
|
||||
}
|
||||
if deps.AuditStore != nil {
|
||||
obs.audit = deps.AuditStore
|
||||
@@ -78,8 +82,11 @@ func (s *Server) recordMetric(method, path string, status int, durMs int64) {
|
||||
s.obs.metrics.Record(method, path, status, durMs)
|
||||
}
|
||||
|
||||
// adminObservabilityMetrics 返回当前网关指标(管理读)。
|
||||
// adminObservabilityMetrics 返回当前网关指标(管理读)。读取同时充当
|
||||
// 实时推送的订阅握手(见 observability_push.go):此后指标由 WS 帧推来,
|
||||
// 面板不再轮询。
|
||||
func (s *Server) adminObservabilityMetrics(w http.ResponseWriter, r *http.Request) {
|
||||
s.watchObservability(r)
|
||||
if s.obs == nil {
|
||||
writeJSON(w, http.StatusOK, AdminMetrics{
|
||||
PerMethod: map[string]int64{}, PerPath: map[string]int64{}, StatusCounts: map[string]int64{},
|
||||
@@ -89,8 +96,10 @@ func (s *Server) adminObservabilityMetrics(w http.ResponseWriter, r *http.Reques
|
||||
writeJSON(w, http.StatusOK, s.obs.metrics.Snapshot(time.Now()))
|
||||
}
|
||||
|
||||
// adminObservabilityTrace 返回最近的已追踪 span(管理读)。
|
||||
// adminObservabilityTrace 返回最近的已追踪 span(管理读)。读取同时充当
|
||||
// 实时推送的订阅握手(见 observability_push.go)。
|
||||
func (s *Server) adminObservabilityTrace(w http.ResponseWriter, r *http.Request) {
|
||||
s.watchObservability(r)
|
||||
if s.obs == nil {
|
||||
writeJSON(w, http.StatusOK, []AdminTraceSpan{})
|
||||
return
|
||||
|
||||
Reference in new issue
Block a user