123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- package nginx_log
- import (
- "context"
- "testing"
- "time"
- )
- // TestPerformanceMonitor tests the performance monitoring system
- func TestPerformanceMonitor(t *testing.T) {
- if testing.Short() {
- t.Skip("Skipping performance monitor test in short mode")
- }
- t.Run("BasicFunctionality", func(t *testing.T) {
- // Create monitor with custom thresholds for testing
- thresholds := &Thresholds{
- ParseStreamOpsPerSec: 100.0, // Low threshold for testing
- SIMDOpsPerSec: 1000.0, // Low threshold for testing
- MemoryPoolOpsPerSec: 10000.0, // Low threshold for testing
- RegexCacheOpsPerSec: 100000.0, // Low threshold for testing
- MaxMemoryUsageMB: 1000.0, // High threshold for testing
- MaxResponseTimeMS: 5000.0, // High threshold for testing
- }
- monitor := NewMonitor(thresholds)
- // Test metrics collection
- monitor.collectMetrics()
- metrics := monitor.GetCurrentMetrics()
- // Verify metrics are populated
- if metrics.ParseStreamRate == 0 {
- t.Error("ParseStream rate not measured")
- }
- if metrics.SIMDRate == 0 {
- t.Error("SIMD rate not measured")
- }
- if metrics.MemoryPoolRate == 0 {
- t.Error("Memory pool rate not measured")
- }
- if metrics.RegexCacheRate == 0 {
- t.Error("Regex cache rate not measured")
- }
- t.Logf("Performance Metrics:")
- t.Logf(" ParseStream: %.2f ops/sec", metrics.ParseStreamRate)
- t.Logf(" SIMD: %.2f ops/sec", metrics.SIMDRate)
- t.Logf(" Memory Pool: %.2f ops/sec", metrics.MemoryPoolRate)
- t.Logf(" Regex Cache: %.2f ops/sec", metrics.RegexCacheRate)
- t.Logf(" Cache Hit Rate: %.2f%%", metrics.CacheHitRate*100)
- })
- t.Run("AlertGeneration", func(t *testing.T) {
- // Create monitor with very high thresholds to trigger alerts
- thresholds := &Thresholds{
- ParseStreamOpsPerSec: 1000000.0, // Unrealistically high
- SIMDOpsPerSec: 10000000.0, // Unrealistically high
- MemoryPoolOpsPerSec: 100000000.0, // Unrealistically high
- RegexCacheOpsPerSec: 1000000000.0, // Unrealistically high
- MaxMemoryUsageMB: 1.0, // Very low to trigger alert
- MaxResponseTimeMS: 0.1, // Very low to trigger alert
- }
- monitor := NewMonitor(thresholds)
-
- // Set up alert collection
- alertsReceived := make([]Alert, 0)
- monitor.SetAlertCallback(func(alert Alert) {
- alertsReceived = append(alertsReceived, alert)
- })
- // Collect metrics and check thresholds
- monitor.collectMetrics()
- monitor.checkThresholds()
- // Allow some time for alerts to be processed
- time.Sleep(100 * time.Millisecond)
- // Verify alerts were generated
- recentAlerts := monitor.GetRecentAlerts(time.Minute)
- if len(recentAlerts) == 0 {
- t.Error("Expected alerts to be generated with high thresholds")
- }
- t.Logf("Generated %d alerts:", len(recentAlerts))
- for _, alert := range recentAlerts {
- t.Logf(" [%s] %s: %.2f vs threshold %.2f",
- alert.Level, alert.Component, alert.CurrentValue, alert.ThresholdValue)
- }
- // Test health status
- health := monitor.GetHealthStatus()
- if health == "healthy" {
- t.Error("Expected unhealthy status with high thresholds")
- }
- t.Logf("Health status: %s", health)
- })
- t.Run("MetricsExport", func(t *testing.T) {
- monitor := NewMonitor(DefaultThresholds())
- monitor.collectMetrics()
- // Test JSON export
- jsonData, err := monitor.ExportMetrics()
- if err != nil {
- t.Fatalf("Failed to export metrics: %v", err)
- }
- if len(jsonData) == 0 {
- t.Error("Exported JSON is empty")
- }
- t.Logf("Exported JSON length: %d bytes", len(jsonData))
- // Test performance report generation
- report := GetReport(monitor)
- if len(report) == 0 {
- t.Error("Performance report is empty")
- }
- t.Logf("Performance Report:\n%s", report)
- })
- t.Run("ContinuousMonitoring", func(t *testing.T) {
- monitor := NewMonitor(DefaultThresholds())
-
- // Set up alert tracking
- alertCount := 0
- monitor.SetAlertCallback(func(alert Alert) {
- alertCount++
- })
- // Start monitoring for a short period
- ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
- defer cancel()
- // Start monitoring with short interval
- go monitor.StartMonitoring(ctx, 500*time.Millisecond)
- // Wait for monitoring to run
- <-ctx.Done()
- // Stop monitoring
- monitor.StopMonitoring()
- // Verify some metrics were collected
- metrics := monitor.GetCurrentMetrics()
- if metrics.Timestamp.IsZero() {
- t.Error("No metrics were collected during monitoring")
- }
- t.Logf("Monitoring completed. Final metrics timestamp: %s",
- metrics.Timestamp.Format(time.RFC3339))
- })
- }
- // TestThresholds tests the default thresholds configuration
- func TestThresholds(t *testing.T) {
- thresholds := DefaultThresholds()
- // Verify default thresholds are reasonable
- if thresholds.ParseStreamOpsPerSec < 100.0 {
- t.Error("ParseStream threshold too low")
- }
- if thresholds.SIMDOpsPerSec < 1000.0 {
- t.Error("SIMD threshold too low")
- }
- if thresholds.MemoryPoolOpsPerSec < 10000.0 {
- t.Error("Memory pool threshold too low")
- }
- if thresholds.RegexCacheOpsPerSec < 100000.0 {
- t.Error("Regex cache threshold too low")
- }
- t.Logf("Default thresholds: ParseStream=%.0f, SIMD=%.0f, MemPool=%.0f, Cache=%.0f",
- thresholds.ParseStreamOpsPerSec, thresholds.SIMDOpsPerSec,
- thresholds.MemoryPoolOpsPerSec, thresholds.RegexCacheOpsPerSec)
- }
- // TestOptimizationMonitoringIntegration tests the complete monitoring integration
- func TestOptimizationMonitoringIntegration(t *testing.T) {
- if testing.Short() {
- t.Skip("Skipping optimization monitoring integration test in short mode")
- }
- // Test the high-level monitoring function
- ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
- defer cancel()
- monitor := StartMonitoring(ctx)
- // Wait for some monitoring cycles
- time.Sleep(1 * time.Second)
- // Check that monitoring is working
- metrics := monitor.GetCurrentMetrics()
- if metrics.Timestamp.IsZero() {
- t.Error("Monitoring did not collect metrics")
- }
- // Get performance report
- report := GetReport(monitor)
- if len(report) == 0 {
- t.Error("Performance report generation failed")
- }
- // Check health status
- health := monitor.GetHealthStatus()
- if health == "" {
- t.Error("Health status not determined")
- }
- t.Logf("Integration test completed successfully")
- t.Logf("Health: %s", health)
- t.Logf("Latest metrics: ParseStream=%.2f, SIMD=%.2f ops/sec",
- metrics.ParseStreamRate, metrics.SIMDRate)
- // Stop monitoring
- monitor.StopMonitoring()
- }
- // BenchmarkPerformanceMonitoring benchmarks the monitoring overhead
- func BenchmarkPerformanceMonitoring(b *testing.B) {
- monitor := NewMonitor(DefaultThresholds())
-
- b.ResetTimer()
-
- for i := 0; i < b.N; i++ {
- monitor.collectMetrics()
- monitor.checkThresholds()
- }
- }
|