performance_monitor_test.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. package nginx_log
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. )
  7. // TestPerformanceMonitor tests the performance monitoring system
  8. func TestPerformanceMonitor(t *testing.T) {
  9. if testing.Short() {
  10. t.Skip("Skipping performance monitor test in short mode")
  11. }
  12. t.Run("BasicFunctionality", func(t *testing.T) {
  13. // Create monitor with custom thresholds for testing
  14. thresholds := &Thresholds{
  15. ParseStreamOpsPerSec: 100.0, // Low threshold for testing
  16. SIMDOpsPerSec: 1000.0, // Low threshold for testing
  17. MemoryPoolOpsPerSec: 10000.0, // Low threshold for testing
  18. RegexCacheOpsPerSec: 100000.0, // Low threshold for testing
  19. MaxMemoryUsageMB: 1000.0, // High threshold for testing
  20. MaxResponseTimeMS: 5000.0, // High threshold for testing
  21. }
  22. monitor := NewMonitor(thresholds)
  23. // Test metrics collection
  24. monitor.collectMetrics()
  25. metrics := monitor.GetCurrentMetrics()
  26. // Verify metrics are populated
  27. if metrics.ParseStreamRate == 0 {
  28. t.Error("ParseStream rate not measured")
  29. }
  30. if metrics.SIMDRate == 0 {
  31. t.Error("SIMD rate not measured")
  32. }
  33. if metrics.MemoryPoolRate == 0 {
  34. t.Error("Memory pool rate not measured")
  35. }
  36. if metrics.RegexCacheRate == 0 {
  37. t.Error("Regex cache rate not measured")
  38. }
  39. t.Logf("Performance Metrics:")
  40. t.Logf(" ParseStream: %.2f ops/sec", metrics.ParseStreamRate)
  41. t.Logf(" SIMD: %.2f ops/sec", metrics.SIMDRate)
  42. t.Logf(" Memory Pool: %.2f ops/sec", metrics.MemoryPoolRate)
  43. t.Logf(" Regex Cache: %.2f ops/sec", metrics.RegexCacheRate)
  44. t.Logf(" Cache Hit Rate: %.2f%%", metrics.CacheHitRate*100)
  45. })
  46. t.Run("AlertGeneration", func(t *testing.T) {
  47. // Create monitor with very high thresholds to trigger alerts
  48. thresholds := &Thresholds{
  49. ParseStreamOpsPerSec: 1000000.0, // Unrealistically high
  50. SIMDOpsPerSec: 10000000.0, // Unrealistically high
  51. MemoryPoolOpsPerSec: 100000000.0, // Unrealistically high
  52. RegexCacheOpsPerSec: 1000000000.0, // Unrealistically high
  53. MaxMemoryUsageMB: 1.0, // Very low to trigger alert
  54. MaxResponseTimeMS: 0.1, // Very low to trigger alert
  55. }
  56. monitor := NewMonitor(thresholds)
  57. // Set up alert collection
  58. alertsReceived := make([]Alert, 0)
  59. monitor.SetAlertCallback(func(alert Alert) {
  60. alertsReceived = append(alertsReceived, alert)
  61. })
  62. // Collect metrics and check thresholds
  63. monitor.collectMetrics()
  64. monitor.checkThresholds()
  65. // Allow some time for alerts to be processed
  66. time.Sleep(100 * time.Millisecond)
  67. // Verify alerts were generated
  68. recentAlerts := monitor.GetRecentAlerts(time.Minute)
  69. if len(recentAlerts) == 0 {
  70. t.Error("Expected alerts to be generated with high thresholds")
  71. }
  72. t.Logf("Generated %d alerts:", len(recentAlerts))
  73. for _, alert := range recentAlerts {
  74. t.Logf(" [%s] %s: %.2f vs threshold %.2f",
  75. alert.Level, alert.Component, alert.CurrentValue, alert.ThresholdValue)
  76. }
  77. // Test health status
  78. health := monitor.GetHealthStatus()
  79. if health == "healthy" {
  80. t.Error("Expected unhealthy status with high thresholds")
  81. }
  82. t.Logf("Health status: %s", health)
  83. })
  84. t.Run("MetricsExport", func(t *testing.T) {
  85. monitor := NewMonitor(DefaultThresholds())
  86. monitor.collectMetrics()
  87. // Test JSON export
  88. jsonData, err := monitor.ExportMetrics()
  89. if err != nil {
  90. t.Fatalf("Failed to export metrics: %v", err)
  91. }
  92. if len(jsonData) == 0 {
  93. t.Error("Exported JSON is empty")
  94. }
  95. t.Logf("Exported JSON length: %d bytes", len(jsonData))
  96. // Test performance report generation
  97. report := GetReport(monitor)
  98. if len(report) == 0 {
  99. t.Error("Performance report is empty")
  100. }
  101. t.Logf("Performance Report:\n%s", report)
  102. })
  103. t.Run("ContinuousMonitoring", func(t *testing.T) {
  104. monitor := NewMonitor(DefaultThresholds())
  105. // Set up alert tracking
  106. alertCount := 0
  107. monitor.SetAlertCallback(func(alert Alert) {
  108. alertCount++
  109. })
  110. // Start monitoring for a short period
  111. ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
  112. defer cancel()
  113. // Start monitoring with short interval
  114. go monitor.StartMonitoring(ctx, 500*time.Millisecond)
  115. // Wait for monitoring to run
  116. <-ctx.Done()
  117. // Stop monitoring
  118. monitor.StopMonitoring()
  119. // Verify some metrics were collected
  120. metrics := monitor.GetCurrentMetrics()
  121. if metrics.Timestamp.IsZero() {
  122. t.Error("No metrics were collected during monitoring")
  123. }
  124. t.Logf("Monitoring completed. Final metrics timestamp: %s",
  125. metrics.Timestamp.Format(time.RFC3339))
  126. })
  127. }
  128. // TestThresholds tests the default thresholds configuration
  129. func TestThresholds(t *testing.T) {
  130. thresholds := DefaultThresholds()
  131. // Verify default thresholds are reasonable
  132. if thresholds.ParseStreamOpsPerSec < 100.0 {
  133. t.Error("ParseStream threshold too low")
  134. }
  135. if thresholds.SIMDOpsPerSec < 1000.0 {
  136. t.Error("SIMD threshold too low")
  137. }
  138. if thresholds.MemoryPoolOpsPerSec < 10000.0 {
  139. t.Error("Memory pool threshold too low")
  140. }
  141. if thresholds.RegexCacheOpsPerSec < 100000.0 {
  142. t.Error("Regex cache threshold too low")
  143. }
  144. t.Logf("Default thresholds: ParseStream=%.0f, SIMD=%.0f, MemPool=%.0f, Cache=%.0f",
  145. thresholds.ParseStreamOpsPerSec, thresholds.SIMDOpsPerSec,
  146. thresholds.MemoryPoolOpsPerSec, thresholds.RegexCacheOpsPerSec)
  147. }
  148. // TestOptimizationMonitoringIntegration tests the complete monitoring integration
  149. func TestOptimizationMonitoringIntegration(t *testing.T) {
  150. if testing.Short() {
  151. t.Skip("Skipping optimization monitoring integration test in short mode")
  152. }
  153. // Test the high-level monitoring function
  154. ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
  155. defer cancel()
  156. monitor := StartMonitoring(ctx)
  157. // Wait for some monitoring cycles
  158. time.Sleep(1 * time.Second)
  159. // Check that monitoring is working
  160. metrics := monitor.GetCurrentMetrics()
  161. if metrics.Timestamp.IsZero() {
  162. t.Error("Monitoring did not collect metrics")
  163. }
  164. // Get performance report
  165. report := GetReport(monitor)
  166. if len(report) == 0 {
  167. t.Error("Performance report generation failed")
  168. }
  169. // Check health status
  170. health := monitor.GetHealthStatus()
  171. if health == "" {
  172. t.Error("Health status not determined")
  173. }
  174. t.Logf("Integration test completed successfully")
  175. t.Logf("Health: %s", health)
  176. t.Logf("Latest metrics: ParseStream=%.2f, SIMD=%.2f ops/sec",
  177. metrics.ParseStreamRate, metrics.SIMDRate)
  178. // Stop monitoring
  179. monitor.StopMonitoring()
  180. }
  181. // BenchmarkPerformanceMonitoring benchmarks the monitoring overhead
  182. func BenchmarkPerformanceMonitoring(b *testing.B) {
  183. monitor := NewMonitor(DefaultThresholds())
  184. b.ResetTimer()
  185. for i := 0; i < b.N; i++ {
  186. monitor.collectMetrics()
  187. monitor.checkThresholds()
  188. }
  189. }