Files
gorz/internal/monitoring/monitoring_test.go
Dev 5440884b85
Some checks failed
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
CI/CD Pipeline / Build Docker Image (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Create Release (push) Has been cancelled
LFG
2025-09-11 18:59:15 +03:00

312 lines
9.1 KiB
Go

package monitoring
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/iwasforcedtobehere/goRZ/internal/config"
"github.com/iwasforcedtobehere/goRZ/internal/logger"
)
func TestMonitorStartStop(t *testing.T) {
cfg := &config.Config{
Monitor: config.MonitorConfig{
Enabled: true,
Port: 9090,
Path: "/metrics",
Auth: false,
},
}
logger := logger.NewLogger()
monitor := NewMonitor(cfg, logger)
// Start the monitor
err := monitor.Start()
if err != nil {
t.Fatalf("Failed to start monitor: %v", err)
}
// Stop the monitor
monitor.Stop()
// Test that we can start and stop again
err = monitor.Start()
if err != nil {
t.Fatalf("Failed to start monitor: %v", err)
}
monitor.Stop()
}
func TestMonitorDisabled(t *testing.T) {
cfg := &config.Config{
Monitor: config.MonitorConfig{
Enabled: false,
},
}
logger := logger.NewLogger()
monitor := NewMonitor(cfg, logger)
// Start the monitor
err := monitor.Start()
if err != nil {
t.Fatalf("Failed to start monitor: %v", err)
}
// Stop the monitor
monitor.Stop()
}
func TestMonitorMetricsHandler(t *testing.T) {
cfg := &config.Config{
Monitor: config.MonitorConfig{
Enabled: true,
Port: 9090,
Path: "/metrics",
Auth: false,
},
Proxy: config.ProxyConfig{
Targets: []config.TargetConfig{
{Name: "target1", Address: "http://localhost:8081", Protocol: "http", Weight: 1, Healthy: true},
{Name: "target2", Address: "http://localhost:8082", Protocol: "http", Weight: 1, Healthy: false},
},
},
}
logger := logger.NewLogger()
monitor := NewMonitor(cfg, logger)
// Create a test HTTP server
server := httptest.NewServer(monitor.authHandler)
defer server.Close()
// Test metrics endpoint
resp, err := http.Get(server.URL + cfg.Monitor.Path)
if err != nil {
t.Fatalf("Failed to get metrics: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected status code %d, got %d", http.StatusOK, resp.StatusCode)
}
// Decode and check metrics
var metrics Metrics
if err := json.NewDecoder(resp.Body).Decode(&metrics); err != nil {
t.Fatalf("Failed to decode metrics: %v", err)
}
if metrics.RequestsTotal != 0 {
t.Errorf("Expected requests total 0, got %d", metrics.RequestsTotal)
}
if metrics.RequestsActive != 0 {
t.Errorf("Expected requests active 0, got %d", metrics.RequestsActive)
}
if len(metrics.TargetMetrics) != 2 {
t.Errorf("Expected 2 target metrics, got %d", len(metrics.TargetMetrics))
}
if !metrics.TargetMetrics["target1"].Healthy {
t.Error("Expected target1 to be healthy")
}
if metrics.TargetMetrics["target2"].Healthy {
t.Error("Expected target2 to be unhealthy")
}
}
func TestMonitorBasicAuth(t *testing.T) {
cfg := &config.Config{
Monitor: config.MonitorConfig{
Enabled: true,
Port: 9090,
Path: "/metrics",
Auth: true,
Username: "admin",
Password: "secret",
},
}
logger := logger.NewLogger()
monitor := NewMonitor(cfg, logger)
// Create a test HTTP server
server := httptest.NewServer(monitor.authHandler)
defer server.Close()
// Test without authentication
resp, err := http.Get(server.URL + cfg.Monitor.Path)
if err != nil {
t.Fatalf("Failed to get metrics: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusUnauthorized {
t.Errorf("Expected status code %d, got %d", http.StatusUnauthorized, resp.StatusCode)
}
// Test with incorrect authentication
req, err := http.NewRequest("GET", server.URL+cfg.Monitor.Path, nil)
if err != nil {
t.Fatalf("Failed to create request: %v", err)
}
req.SetBasicAuth("wrong", "credentials")
client := &http.Client{}
resp, err = client.Do(req)
if err != nil {
t.Fatalf("Failed to send request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusUnauthorized {
t.Errorf("Expected status code %d, got %d", http.StatusUnauthorized, resp.StatusCode)
}
// Test with correct authentication
req, err = http.NewRequest("GET", server.URL+cfg.Monitor.Path, nil)
if err != nil {
t.Fatalf("Failed to create request: %v", err)
}
req.SetBasicAuth(cfg.Monitor.Username, cfg.Monitor.Password)
resp, err = client.Do(req)
if err != nil {
t.Fatalf("Failed to send request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected status code %d, got %d", http.StatusOK, resp.StatusCode)
}
}
func TestMonitorMetricsTracking(t *testing.T) {
cfg := &config.Config{
Monitor: config.MonitorConfig{
Enabled: true,
Port: 9090,
Path: "/metrics",
Auth: false,
},
Proxy: config.ProxyConfig{
Targets: []config.TargetConfig{
{Name: "target1", Address: "http://localhost:8081", Protocol: "http", Weight: 1, Healthy: true},
},
},
}
logger := logger.NewLogger()
monitor := NewMonitor(cfg, logger)
// Test incrementing request count
monitor.IncrementRequest()
metrics := monitor.GetMetrics()
if metrics.RequestsTotal != 1 {
t.Errorf("Expected requests total 1, got %d", metrics.RequestsTotal)
}
// Test incrementing active request count
monitor.IncrementActiveRequest()
metrics = monitor.GetMetrics()
if metrics.RequestsActive != 1 {
t.Errorf("Expected requests active 1, got %d", metrics.RequestsActive)
}
// Test decrementing active request count
monitor.DecrementActiveRequest()
metrics = monitor.GetMetrics()
if metrics.RequestsActive != 0 {
t.Errorf("Expected requests active 0, got %d", metrics.RequestsActive)
}
// Test recording response
monitor.RecordResponse(http.StatusOK, "target1", 100*time.Millisecond)
metrics = monitor.GetMetrics()
if metrics.ResponsesByStatus["200"] != 1 {
t.Errorf("Expected 1 response with status 200, got %d", metrics.ResponsesByStatus["200"])
}
if metrics.TargetMetrics["target1"].RequestsTotal != 1 {
t.Errorf("Expected target1 to have 1 request, got %d", metrics.TargetMetrics["target1"].RequestsTotal)
}
if metrics.TargetMetrics["target1"].ResponsesByStatus["200"] != 1 {
t.Errorf("Expected target1 to have 1 response with status 200, got %d", metrics.TargetMetrics["target1"].ResponsesByStatus["200"])
}
if len(metrics.TargetMetrics["target1"].ResponseTimes) != 1 {
t.Errorf("Expected target1 to have 1 response time, got %d", len(metrics.TargetMetrics["target1"].ResponseTimes))
}
if metrics.TargetMetrics["target1"].AvgResponseTime != 100*time.Millisecond {
t.Errorf("Expected target1 to have average response time 100ms, got %v", metrics.TargetMetrics["target1"].AvgResponseTime)
}
// Test updating target health
monitor.UpdateTargetHealth("target1", false)
metrics = monitor.GetMetrics()
if metrics.TargetMetrics["target1"].Healthy {
t.Error("Expected target1 to be unhealthy")
}
}
func TestMonitorMultipleResponses(t *testing.T) {
cfg := &config.Config{
Monitor: config.MonitorConfig{
Enabled: true,
Port: 9090,
Path: "/metrics",
Auth: false,
},
Proxy: config.ProxyConfig{
Targets: []config.TargetConfig{
{Name: "target1", Address: "http://localhost:8081", Protocol: "http", Weight: 1, Healthy: true},
},
},
}
logger := logger.NewLogger()
monitor := NewMonitor(cfg, logger)
// Record multiple responses with different status codes and response times
monitor.RecordResponse(http.StatusOK, "target1", 100*time.Millisecond)
monitor.RecordResponse(http.StatusOK, "target1", 200*time.Millisecond)
monitor.RecordResponse(http.StatusNotFound, "target1", 50*time.Millisecond)
monitor.RecordResponse(http.StatusInternalServerError, "target1", 300*time.Millisecond)
metrics := monitor.GetMetrics()
// Check overall metrics
if metrics.RequestsTotal != 0 {
t.Errorf("Expected requests total 0, got %d", metrics.RequestsTotal)
}
if metrics.ResponsesByStatus["200"] != 2 {
t.Errorf("Expected 2 responses with status 200, got %d", metrics.ResponsesByStatus["200"])
}
if metrics.ResponsesByStatus["404"] != 1 {
t.Errorf("Expected 1 response with status 404, got %d", metrics.ResponsesByStatus["404"])
}
if metrics.ResponsesByStatus["500"] != 1 {
t.Errorf("Expected 1 response with status 500, got %d", metrics.ResponsesByStatus["500"])
}
// Check target metrics
if metrics.TargetMetrics["target1"].RequestsTotal != 4 {
t.Errorf("Expected target1 to have 4 requests, got %d", metrics.TargetMetrics["target1"].RequestsTotal)
}
if metrics.TargetMetrics["target1"].ResponsesByStatus["200"] != 2 {
t.Errorf("Expected target1 to have 2 responses with status 200, got %d", metrics.TargetMetrics["target1"].ResponsesByStatus["200"])
}
if metrics.TargetMetrics["target1"].ResponsesByStatus["404"] != 1 {
t.Errorf("Expected target1 to have 1 response with status 404, got %d", metrics.TargetMetrics["target1"].ResponsesByStatus["404"])
}
if metrics.TargetMetrics["target1"].ResponsesByStatus["500"] != 1 {
t.Errorf("Expected target1 to have 1 response with status 500, got %d", metrics.TargetMetrics["target1"].ResponsesByStatus["500"])
}
// Check average response time
expectedAvg := time.Duration((100 + 200 + 50 + 300) / 4)
if metrics.TargetMetrics["target1"].AvgResponseTime != expectedAvg {
t.Errorf("Expected target1 to have average response time %v, got %v", expectedAvg, metrics.TargetMetrics["target1"].AvgResponseTime)
}
}