LFG
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
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
This commit is contained in:
266
internal/monitoring/monitoring.go
Normal file
266
internal/monitoring/monitoring.go
Normal file
@@ -0,0 +1,266 @@
|
||||
package monitoring
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/iwasforcedtobehere/goRZ/internal/config"
|
||||
"github.com/iwasforcedtobehere/goRZ/internal/logger"
|
||||
)
|
||||
|
||||
// Metrics represents the application metrics
|
||||
type Metrics struct {
|
||||
RequestsTotal int64 `json:"requests_total"`
|
||||
RequestsActive int64 `json:"requests_active"`
|
||||
ResponsesByStatus map[string]int64 `json:"responses_by_status"`
|
||||
TargetMetrics map[string]*TargetMetric `json:"target_metrics"`
|
||||
StartTime time.Time `json:"start_time"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
mu sync.RWMutex `json:"-"`
|
||||
}
|
||||
|
||||
// TargetMetric represents metrics for a specific target
|
||||
type TargetMetric struct {
|
||||
RequestsTotal int64 `json:"requests_total"`
|
||||
ResponsesByStatus map[string]int64 `json:"responses_by_status"`
|
||||
ResponseTimes []time.Duration `json:"response_times"`
|
||||
AvgResponseTime time.Duration `json:"avg_response_time"`
|
||||
Healthy bool `json:"healthy"`
|
||||
LastChecked time.Time `json:"last_checked"`
|
||||
}
|
||||
|
||||
// Monitor represents the monitoring service
|
||||
type Monitor struct {
|
||||
config *config.Config
|
||||
logger *logger.Logger
|
||||
metrics *Metrics
|
||||
server *http.Server
|
||||
authHandler http.Handler
|
||||
}
|
||||
|
||||
// NewMonitor creates a new monitoring service
|
||||
func NewMonitor(cfg *config.Config, logger *logger.Logger) *Monitor {
|
||||
metrics := &Metrics{
|
||||
ResponsesByStatus: make(map[string]int64),
|
||||
TargetMetrics: make(map[string]*TargetMetric),
|
||||
StartTime: time.Now(),
|
||||
LastUpdated: time.Now(),
|
||||
}
|
||||
|
||||
// Initialize target metrics
|
||||
for _, target := range cfg.Proxy.Targets {
|
||||
metrics.TargetMetrics[target.Name] = &TargetMetric{
|
||||
ResponsesByStatus: make(map[string]int64),
|
||||
ResponseTimes: make([]time.Duration, 0),
|
||||
Healthy: target.Healthy,
|
||||
LastChecked: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
monitor := &Monitor{
|
||||
config: cfg,
|
||||
logger: logger,
|
||||
metrics: metrics,
|
||||
}
|
||||
|
||||
// Set up authentication if enabled
|
||||
if cfg.Monitor.Auth {
|
||||
monitor.authHandler = monitor.basicAuthHandler(monitor.metricsHandler)
|
||||
} else {
|
||||
monitor.authHandler = monitor.metricsHandler
|
||||
}
|
||||
|
||||
return monitor
|
||||
}
|
||||
|
||||
// Start starts the monitoring service
|
||||
func (m *Monitor) Start() error {
|
||||
if !m.config.Monitor.Enabled {
|
||||
m.logger.Info("Monitoring is disabled")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create HTTP server
|
||||
m.server = &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", m.config.Monitor.Port),
|
||||
Handler: m.authHandler,
|
||||
}
|
||||
|
||||
// Start server in a goroutine
|
||||
go func() {
|
||||
m.logger.Info("Monitoring server starting", logger.String("address", m.server.Addr))
|
||||
if err := m.server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
m.logger.Error("Monitoring server failed", logger.Error(err))
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop stops the monitoring service
|
||||
func (m *Monitor) Stop() {
|
||||
if m.server != nil {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
m.server.Shutdown(ctx)
|
||||
m.logger.Info("Monitoring server stopped")
|
||||
}
|
||||
}
|
||||
|
||||
// metricsHandler handles HTTP requests for metrics
|
||||
func (m *Monitor) metricsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != m.config.Monitor.Path {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
m.metrics.mu.RLock()
|
||||
defer m.metrics.mu.RUnlock()
|
||||
|
||||
// Update last updated time
|
||||
m.metrics.LastUpdated = time.Now()
|
||||
|
||||
// Set content type
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
// Encode metrics as JSON
|
||||
if err := json.NewEncoder(w).Encode(m.metrics); err != nil {
|
||||
m.logger.Error("Failed to encode metrics", logger.Error(err))
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// basicAuthHandler wraps a handler with basic authentication
|
||||
func (m *Monitor) basicAuthHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
username, password, ok := r.BasicAuth()
|
||||
if !ok || username != m.config.Monitor.Username || password != m.config.Monitor.Password {
|
||||
w.Header().Set("WWW-Authenticate", `Basic realm="goRZ Monitor"`)
|
||||
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// IncrementRequest increments the total request count
|
||||
func (m *Monitor) IncrementRequest() {
|
||||
m.metrics.mu.Lock()
|
||||
defer m.metrics.mu.Unlock()
|
||||
|
||||
m.metrics.RequestsTotal++
|
||||
m.metrics.LastUpdated = time.Now()
|
||||
}
|
||||
|
||||
// IncrementActiveRequest increments the active request count
|
||||
func (m *Monitor) IncrementActiveRequest() {
|
||||
m.metrics.mu.Lock()
|
||||
defer m.metrics.mu.Unlock()
|
||||
|
||||
m.metrics.RequestsActive++
|
||||
m.metrics.LastUpdated = time.Now()
|
||||
}
|
||||
|
||||
// DecrementActiveRequest decrements the active request count
|
||||
func (m *Monitor) DecrementActiveRequest() {
|
||||
m.metrics.mu.Lock()
|
||||
defer m.metrics.mu.Unlock()
|
||||
|
||||
m.metrics.RequestsActive--
|
||||
if m.metrics.RequestsActive < 0 {
|
||||
m.metrics.RequestsActive = 0
|
||||
}
|
||||
m.metrics.LastUpdated = time.Now()
|
||||
}
|
||||
|
||||
// RecordResponse records a response with the given status code
|
||||
func (m *Monitor) RecordResponse(statusCode int, targetName string, responseTime time.Duration) {
|
||||
m.metrics.mu.Lock()
|
||||
defer m.metrics.mu.Unlock()
|
||||
|
||||
status := fmt.Sprintf("%d", statusCode)
|
||||
m.metrics.ResponsesByStatus[status]++
|
||||
|
||||
// Update target metrics
|
||||
if target, exists := m.metrics.TargetMetrics[targetName]; exists {
|
||||
target.RequestsTotal++
|
||||
target.ResponsesByStatus[status]++
|
||||
|
||||
// Keep only the last 100 response times for average calculation
|
||||
if len(target.ResponseTimes) >= 100 {
|
||||
target.ResponseTimes = target.ResponseTimes[1:]
|
||||
}
|
||||
target.ResponseTimes = append(target.ResponseTimes, responseTime)
|
||||
|
||||
// Calculate average response time
|
||||
var total time.Duration
|
||||
for _, rt := range target.ResponseTimes {
|
||||
total += rt
|
||||
}
|
||||
target.AvgResponseTime = total / time.Duration(len(target.ResponseTimes))
|
||||
}
|
||||
|
||||
m.metrics.LastUpdated = time.Now()
|
||||
}
|
||||
|
||||
// UpdateTargetHealth updates the health status of a target
|
||||
func (m *Monitor) UpdateTargetHealth(targetName string, healthy bool) {
|
||||
m.metrics.mu.Lock()
|
||||
defer m.metrics.mu.Unlock()
|
||||
|
||||
if target, exists := m.metrics.TargetMetrics[targetName]; exists {
|
||||
target.Healthy = healthy
|
||||
target.LastChecked = time.Now()
|
||||
}
|
||||
|
||||
m.metrics.LastUpdated = time.Now()
|
||||
}
|
||||
|
||||
// GetMetrics returns a copy of the current metrics
|
||||
func (m *Monitor) GetMetrics() Metrics {
|
||||
m.metrics.mu.RLock()
|
||||
defer m.metrics.mu.RUnlock()
|
||||
|
||||
// Create a deep copy of the metrics
|
||||
metrics := Metrics{
|
||||
RequestsTotal: m.metrics.RequestsTotal,
|
||||
RequestsActive: m.metrics.RequestsActive,
|
||||
ResponsesByStatus: make(map[string]int64),
|
||||
TargetMetrics: make(map[string]*TargetMetric),
|
||||
StartTime: m.metrics.StartTime,
|
||||
LastUpdated: m.metrics.LastUpdated,
|
||||
}
|
||||
|
||||
// Copy response status counts
|
||||
for k, v := range m.metrics.ResponsesByStatus {
|
||||
metrics.ResponsesByStatus[k] = v
|
||||
}
|
||||
|
||||
// Copy target metrics
|
||||
for k, v := range m.metrics.TargetMetrics {
|
||||
targetMetric := &TargetMetric{
|
||||
RequestsTotal: v.RequestsTotal,
|
||||
ResponsesByStatus: make(map[string]int64),
|
||||
ResponseTimes: make([]time.Duration, len(v.ResponseTimes)),
|
||||
AvgResponseTime: v.AvgResponseTime,
|
||||
Healthy: v.Healthy,
|
||||
LastChecked: v.LastChecked,
|
||||
}
|
||||
|
||||
// Copy response status counts for target
|
||||
for rk, rv := range v.ResponsesByStatus {
|
||||
targetMetric.ResponsesByStatus[rk] = rv
|
||||
}
|
||||
|
||||
// Copy response times
|
||||
copy(targetMetric.ResponseTimes, v.ResponseTimes)
|
||||
|
||||
metrics.TargetMetrics[k] = targetMetric
|
||||
}
|
||||
|
||||
return metrics
|
||||
}
|
312
internal/monitoring/monitoring_test.go
Normal file
312
internal/monitoring/monitoring_test.go
Normal file
@@ -0,0 +1,312 @@
|
||||
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)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user