Files
sub2api-cn-relay-manager/internal/metrics/metrics_test.go
phamnazage-jpg dd6f332b53
Some checks failed
CI / Build & Test (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Release (push) Has been cancelled
feat: close v3 slo gates and lifecycle metrics
2026-06-08 14:49:06 +08:00

261 lines
6.3 KiB
Go

package metrics
import (
"context"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
)
func TestHTTPRequestsTotal(t *testing.T) {
RecordHTTPRequest("GET", "/test", 200, 100*time.Millisecond)
// Verify the counter was incremented
// Note: We can't easily read the counter value directly, but we can verify
// the handler returns the metric
req := httptest.NewRequest("GET", "/metrics", nil)
rr := httptest.NewRecorder()
Handler().ServeHTTP(rr, req)
if rr.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", rr.Code)
}
body := rr.Body.String()
if !strings.Contains(body, "http_requests_total") {
t.Error("Expected metrics endpoint to contain http_requests_total")
}
if !strings.Contains(body, `status="200"`) {
t.Fatalf("expected numeric HTTP status label, got: %s", body)
}
}
func TestRecordRouteDecision(t *testing.T) {
RecordRouteDecision("test-group", "success")
RecordRouteDecision("test-group", "success")
RecordRouteDecision("test-group", "failed")
req := httptest.NewRequest("GET", "/metrics", nil)
rr := httptest.NewRecorder()
Handler().ServeHTTP(rr, req)
if rr.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", rr.Code)
}
body := rr.Body.String()
if !strings.Contains(body, "route_decisions_total") {
t.Error("Expected metrics endpoint to contain route_decisions_total")
}
}
func TestRecordRouteFailover(t *testing.T) {
RecordRouteFailover()
req := httptest.NewRequest("GET", "/metrics", nil)
rr := httptest.NewRecorder()
Handler().ServeHTTP(rr, req)
body := rr.Body.String()
if !strings.Contains(body, "route_failovers_total") {
t.Error("Expected metrics endpoint to contain route_failovers_total")
}
}
func TestRecordUserKeyOperation(t *testing.T) {
RecordUserKeyOperation("create", "success")
RecordUserKeyOperation("pause", "success")
req := httptest.NewRequest("GET", "/metrics", nil)
rr := httptest.NewRecorder()
Handler().ServeHTTP(rr, req)
body := rr.Body.String()
if !strings.Contains(body, "user_key_operations_total") {
t.Error("Expected metrics endpoint to contain user_key_operations_total")
}
}
func TestRecordUserKeyChatRequest(t *testing.T) {
RecordUserKeyChatRequest("ok")
RecordUserKeyChatRequest("key_paused")
req := httptest.NewRequest("GET", "/metrics", nil)
rr := httptest.NewRecorder()
Handler().ServeHTTP(rr, req)
body := rr.Body.String()
if !strings.Contains(body, "user_key_chat_requests_total") {
t.Error("Expected metrics endpoint to contain user_key_chat_requests_total")
}
}
func TestSetActiveHosts(t *testing.T) {
SetActiveHosts(10)
req := httptest.NewRequest("GET", "/metrics", nil)
rr := httptest.NewRecorder()
Handler().ServeHTTP(rr, req)
body := rr.Body.String()
if !strings.Contains(body, "active_hosts") {
t.Error("Expected metrics endpoint to contain active_hosts")
}
}
func TestSetActiveProviders(t *testing.T) {
SetActiveProviders(5)
req := httptest.NewRequest("GET", "/metrics", nil)
rr := httptest.NewRecorder()
Handler().ServeHTTP(rr, req)
body := rr.Body.String()
if !strings.Contains(body, "active_providers") {
t.Error("Expected metrics endpoint to contain active_providers")
}
}
func TestRecordDBOperation(t *testing.T) {
RecordDBOperation("insert", "hosts")
RecordDBOperation("select", "hosts")
req := httptest.NewRequest("GET", "/metrics", nil)
rr := httptest.NewRecorder()
Handler().ServeHTTP(rr, req)
body := rr.Body.String()
if !strings.Contains(body, "db_operations_total") {
t.Error("Expected metrics endpoint to contain db_operations_total")
}
}
func TestRecordLogFlushError(t *testing.T) {
RecordLogFlushError()
RecordLogFlushError()
req := httptest.NewRequest("GET", "/metrics", nil)
rr := httptest.NewRecorder()
Handler().ServeHTTP(rr, req)
body := rr.Body.String()
if !strings.Contains(body, "log_flush_errors_total") {
t.Error("Expected metrics endpoint to contain log_flush_errors_total")
}
}
func TestRecordLogDroppedEvent(t *testing.T) {
RecordLogDroppedEvent()
req := httptest.NewRequest("GET", "/metrics", nil)
rr := httptest.NewRecorder()
Handler().ServeHTTP(rr, req)
body := rr.Body.String()
if !strings.Contains(body, "log_dropped_events_total") {
t.Error("Expected metrics endpoint to contain log_dropped_events_total")
}
}
func TestMiddleware(t *testing.T) {
handler := Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated)
w.Write([]byte("OK"))
}))
req := httptest.NewRequest("POST", "/api/test", nil)
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
if rr.Code != http.StatusCreated {
t.Errorf("Expected status 201, got %d", rr.Code)
}
if rr.Body.String() != "OK" {
t.Errorf("Expected body 'OK', got '%s'", rr.Body.String())
}
}
func TestResponseWriter(t *testing.T) {
base := httptest.NewRecorder()
rw := &responseWriter{ResponseWriter: base, statusCode: 200}
rw.WriteHeader(http.StatusTeapot)
if rw.statusCode != http.StatusTeapot {
t.Errorf("Expected status code %d, got %d", http.StatusTeapot, rw.statusCode)
}
}
func TestStartServer(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Start metrics server on a random port
server := StartServer(ctx, "127.0.0.1:0")
// Give server time to start
time.Sleep(100 * time.Millisecond)
// Verify server is running by making a request
addr := server.Addr
if addr == "" {
t.Fatal("Server address not available")
}
// Server should shut down gracefully when context is cancelled
cancel()
// Give server time to shut down
time.Sleep(100 * time.Millisecond)
}
func TestHandlerContent(t *testing.T) {
// Set some metrics values
SetActiveHosts(42)
SetActiveProviders(7)
req := httptest.NewRequest("GET", "/metrics", nil)
rr := httptest.NewRecorder()
Handler().ServeHTTP(rr, req)
if rr.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", rr.Code)
}
contentType := rr.Header().Get("Content-Type")
if !strings.Contains(contentType, "text/plain") && !strings.Contains(contentType, "application/openmetrics") {
t.Errorf("Expected text/plain or openmetrics content type, got %s", contentType)
}
body := rr.Body.String()
// Check for expected metrics
expectedMetrics := []string{
"# HELP",
"# TYPE",
"active_hosts",
"active_providers",
}
for _, metric := range expectedMetrics {
if !strings.Contains(body, metric) {
t.Errorf("Expected metrics to contain '%s'", metric)
}
}
}