Feat v0.6.4 admin health/metrics tab + cluster merge
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 4s
CI/CD / test-frontend (pull_request) Successful in 5s
CI/CD / test-go-pg (pull_request) Successful in 2m40s
CI/CD / test-sqlite (pull_request) Successful in 2m46s
CI/CD / build-and-deploy (pull_request) Successful in 1m1s

Admin Health tab under Monitoring with auto-refreshing runtime, DB,
cluster, and extension metrics panels. New GET /api/v1/admin/metrics
endpoint. Fattened heartbeat JSONB with stack, GC CPU%, extension
count, sandbox stats, trigger fires. Sandbox runner and trigger engine
now track cumulative execution counters. Event bus tracks publish/deliver
counts. Health endpoints consolidated via shared builder. Block renderers
(mermaid, katex, csv-table, diff-viewer) no longer require chat.
cluster-dashboard package retired — merged into admin Health tab.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-31 13:06:09 +00:00
parent 3d4228f868
commit 4bc11c2f4e
22 changed files with 917 additions and 281 deletions

View File

@@ -75,6 +75,46 @@ func TestCollectStats(t *testing.T) {
}
}
func TestCollectStatsFattened(t *testing.T) {
hub := &mockHub{count: 3}
reg := NewRegistry("test-node", "", nil, hub, RegistryConfig{
HeartbeatInterval: 10 * time.Second,
StaleThreshold: 30 * time.Second,
})
reg.SetSandboxStats(func() (uint64, uint64, float64) { return 100, 5, 12.3 })
reg.SetTriggerFireCount(func() int64 { return 42 })
reg.SetExtensionCount(func() int { return 8 })
data := reg.collectStats()
var stats map[string]any
if err := json.Unmarshal(data, &stats); err != nil {
t.Fatalf("collectStats returned invalid JSON: %v", err)
}
// New fattened keys
fatKeys := []string{
"stack_in_use", "gc_cpu_pct",
"extensions_loaded", "starlark_exec_total", "starlark_errors_total",
"starlark_avg_duration_ms", "trigger_fires_total",
}
for _, key := range fatKeys {
if _, ok := stats[key]; !ok {
t.Errorf("missing fattened stats key: %s", key)
}
}
if v := stats["extensions_loaded"].(float64); int(v) != 8 {
t.Errorf("extensions_loaded = %v, want 8", v)
}
if v := stats["starlark_exec_total"].(float64); int(v) != 100 {
t.Errorf("starlark_exec_total = %v, want 100", v)
}
if v := stats["trigger_fires_total"].(float64); int(v) != 42 {
t.Errorf("trigger_fires_total = %v, want 42", v)
}
}
func TestRegistryStartStop(t *testing.T) {
ms := &mockClusterStore{heartbeatRows: 1}
hub := &mockHub{count: 0}