All checks were successful
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
188 lines
4.8 KiB
Go
188 lines
4.8 KiB
Go
package handlers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"armature/metrics"
|
|
"armature/store"
|
|
)
|
|
|
|
// mockHub implements metrics.ConnCounter for tests.
|
|
type mockHub struct{ count int }
|
|
|
|
func (m *mockHub) ConnCount() int { return m.count }
|
|
|
|
// mockBus implements metrics.BusCounter for tests.
|
|
type mockBus struct{ pub, del int64 }
|
|
|
|
func (m *mockBus) PublishCount() int64 { return m.pub }
|
|
func (m *mockBus) DeliverCount() int64 { return m.del }
|
|
|
|
func TestMetrics_SQLiteShape(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
collector := metrics.NewCollector(
|
|
"test-node",
|
|
nil, // no DB
|
|
&mockHub{count: 5},
|
|
&mockBus{pub: 10, del: 20},
|
|
store.Stores{}, // no cluster store
|
|
func() (uint64, uint64, float64) { return 42, 3, 12.5 },
|
|
func() int64 { return 7 },
|
|
time.Now().Add(-10*time.Minute),
|
|
)
|
|
|
|
h := NewMetricsHandler(collector)
|
|
r := gin.New()
|
|
r.GET("/api/v1/admin/metrics", h.GetMetrics)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/metrics", nil)
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
|
|
if w.Code != 200 {
|
|
t.Fatalf("status = %d, want 200", w.Code)
|
|
}
|
|
|
|
var snap metrics.Snapshot
|
|
if err := json.Unmarshal(w.Body.Bytes(), &snap); err != nil {
|
|
t.Fatalf("unmarshal: %v", err)
|
|
}
|
|
|
|
// Node ID
|
|
if snap.NodeID != "test-node" {
|
|
t.Errorf("node_id = %q, want %q", snap.NodeID, "test-node")
|
|
}
|
|
|
|
// Runtime
|
|
if snap.Runtime.WSClients != 5 {
|
|
t.Errorf("ws_clients = %d, want 5", snap.Runtime.WSClients)
|
|
}
|
|
if snap.Runtime.UptimeSec < 600 {
|
|
t.Errorf("uptime_sec = %f, want >= 600", snap.Runtime.UptimeSec)
|
|
}
|
|
|
|
// Cluster should be nil (SQLite)
|
|
if snap.Cluster != nil {
|
|
t.Errorf("cluster should be nil for SQLite, got %+v", snap.Cluster)
|
|
}
|
|
|
|
// Extensions
|
|
if snap.Extensions.StarlarkExecTotal != 42 {
|
|
t.Errorf("starlark_exec_total = %d, want 42", snap.Extensions.StarlarkExecTotal)
|
|
}
|
|
if snap.Extensions.StarlarkErrorsTotal != 3 {
|
|
t.Errorf("starlark_errors_total = %d, want 3", snap.Extensions.StarlarkErrorsTotal)
|
|
}
|
|
if snap.Extensions.StarlarkAvgDuration != 12.5 {
|
|
t.Errorf("starlark_avg_duration_ms = %f, want 12.5", snap.Extensions.StarlarkAvgDuration)
|
|
}
|
|
if snap.Extensions.TriggerFiresTotal != 7 {
|
|
t.Errorf("trigger_fires_total = %d, want 7", snap.Extensions.TriggerFiresTotal)
|
|
}
|
|
if snap.Extensions.EventBusPublished != 10 {
|
|
t.Errorf("event_bus_published = %d, want 10", snap.Extensions.EventBusPublished)
|
|
}
|
|
if snap.Extensions.EventBusDelivered != 20 {
|
|
t.Errorf("event_bus_delivered = %d, want 20", snap.Extensions.EventBusDelivered)
|
|
}
|
|
}
|
|
|
|
func TestMetrics_WithCluster(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
mock := &mockClusterStore{
|
|
nodes: []store.ClusterNode{
|
|
{
|
|
NodeID: "node-1",
|
|
Endpoint: "http://node-1:8080",
|
|
Heartbeat: time.Now(),
|
|
Stats: json.RawMessage(`{"uptime_sec":120,"ws_clients":3}`),
|
|
},
|
|
},
|
|
}
|
|
|
|
collector := metrics.NewCollector(
|
|
"test-node",
|
|
nil,
|
|
&mockHub{count: 3},
|
|
&mockBus{},
|
|
store.Stores{Cluster: mock},
|
|
func() (uint64, uint64, float64) { return 0, 0, 0 },
|
|
func() int64 { return 0 },
|
|
time.Now(),
|
|
)
|
|
|
|
h := NewMetricsHandler(collector)
|
|
r := gin.New()
|
|
r.GET("/api/v1/admin/metrics", h.GetMetrics)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/metrics", nil)
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
|
|
if w.Code != 200 {
|
|
t.Fatalf("status = %d, want 200", w.Code)
|
|
}
|
|
|
|
var snap metrics.Snapshot
|
|
if err := json.Unmarshal(w.Body.Bytes(), &snap); err != nil {
|
|
t.Fatalf("unmarshal: %v", err)
|
|
}
|
|
|
|
if snap.Cluster == nil {
|
|
t.Fatal("cluster should not be nil with cluster store")
|
|
}
|
|
if snap.Cluster.Size != 1 {
|
|
t.Errorf("cluster.size = %d, want 1", snap.Cluster.Size)
|
|
}
|
|
if snap.Cluster.Nodes[0].NodeID != "node-1" {
|
|
t.Errorf("node_id = %q, want %q", snap.Cluster.Nodes[0].NodeID, "node-1")
|
|
}
|
|
if snap.Cluster.Nodes[0].UptimeSec != 120 {
|
|
t.Errorf("uptime_sec = %f, want 120", snap.Cluster.Nodes[0].UptimeSec)
|
|
}
|
|
}
|
|
|
|
func TestMetrics_ExtensionCounters(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
collector := metrics.NewCollector(
|
|
"test-node",
|
|
nil,
|
|
&mockHub{},
|
|
&mockBus{pub: 100, del: 500},
|
|
store.Stores{},
|
|
func() (uint64, uint64, float64) { return 1000, 50, 8.3 },
|
|
func() int64 { return 25 },
|
|
time.Now(),
|
|
)
|
|
|
|
h := NewMetricsHandler(collector)
|
|
r := gin.New()
|
|
r.GET("/api/v1/admin/metrics", h.GetMetrics)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/metrics", nil)
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
|
|
var snap metrics.Snapshot
|
|
_ = json.Unmarshal(w.Body.Bytes(), &snap)
|
|
|
|
if snap.Extensions.StarlarkExecTotal != 1000 {
|
|
t.Errorf("exec total = %d, want 1000", snap.Extensions.StarlarkExecTotal)
|
|
}
|
|
if snap.Extensions.EventBusPublished != 100 {
|
|
t.Errorf("bus published = %d, want 100", snap.Extensions.EventBusPublished)
|
|
}
|
|
if snap.Extensions.EventBusDelivered != 500 {
|
|
t.Errorf("bus delivered = %d, want 500", snap.Extensions.EventBusDelivered)
|
|
}
|
|
}
|