mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 19:41:17 +00:00
84 lines
2.1 KiB
Go
84 lines
2.1 KiB
Go
package memory
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"runtime/debug"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/alerts"
|
|
)
|
|
|
|
func TestIncidentStoreMemoryStability(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping memory regression in short mode")
|
|
}
|
|
|
|
store := NewIncidentStore(IncidentStoreConfig{
|
|
MaxIncidents: 50,
|
|
MaxEventsPerIncident: 8,
|
|
MaxAgeDays: 1,
|
|
})
|
|
|
|
alertsPerCycle := 150
|
|
warmupCycles := 5
|
|
measureCycles := 15
|
|
|
|
makeAlert := func(i int) *alerts.Alert {
|
|
resourceID := fmt.Sprintf("vm-%02d", i%20)
|
|
return &alerts.Alert{
|
|
ID: fmt.Sprintf("alert-%d", i),
|
|
Type: "memory",
|
|
Level: alerts.AlertLevelWarning,
|
|
ResourceID: resourceID,
|
|
ResourceName: resourceID,
|
|
StartTime: time.Now().Add(-2 * time.Minute),
|
|
Value: 90,
|
|
Threshold: 80,
|
|
}
|
|
}
|
|
|
|
runCycle := func(offset int) {
|
|
now := time.Now()
|
|
for i := 0; i < alertsPerCycle; i++ {
|
|
idx := offset + i
|
|
alert := makeAlert(idx)
|
|
store.RecordAlertFired(alert)
|
|
store.RecordAlertAcknowledged(alert, "admin")
|
|
store.RecordAnalysis(alert.ID, "analysis complete", map[string]interface{}{
|
|
"iteration": idx,
|
|
})
|
|
store.RecordCommand(alert.ID, "systemctl restart app", true, "ok", nil)
|
|
store.RecordRunbook(alert.ID, fmt.Sprintf("rb-%d", idx%5), "Restart service", "resolved", true, "ok")
|
|
store.RecordNote(alert.ID, "", "note", "admin")
|
|
store.RecordAlertResolved(alert, now)
|
|
}
|
|
}
|
|
|
|
for i := 0; i < warmupCycles; i++ {
|
|
runCycle(i * alertsPerCycle)
|
|
}
|
|
|
|
runtime.GC()
|
|
debug.FreeOSMemory()
|
|
var baseline runtime.MemStats
|
|
runtime.ReadMemStats(&baseline)
|
|
|
|
for i := 0; i < measureCycles; i++ {
|
|
runCycle(100000 + i*alertsPerCycle)
|
|
}
|
|
|
|
runtime.GC()
|
|
debug.FreeOSMemory()
|
|
var after runtime.MemStats
|
|
runtime.ReadMemStats(&after)
|
|
|
|
if baseline.HeapAlloc > 0 {
|
|
allowed := baseline.HeapAlloc + 5*1024*1024
|
|
growthRatio := float64(after.HeapAlloc) / float64(baseline.HeapAlloc)
|
|
if after.HeapAlloc > allowed && growthRatio > 1.25 {
|
|
t.Fatalf("heap allocation grew too much: baseline=%d final=%d ratio=%.2f", baseline.HeapAlloc, after.HeapAlloc, growthRatio)
|
|
}
|
|
}
|
|
}
|