mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-22 03:00:12 +00:00
test(agentcompat): add exact stress scenario
Co-authored-by: naiba/CloudCode <hi+cloudcode@nai.ba>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
//go:build linux
|
||||
|
||||
package scenario
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/nezhahq/nezha/integration/agentcompat/internal/contract"
|
||||
)
|
||||
|
||||
var ErrStressSoakTrend = errors.New("stress soak RSS increases strictly across all iterations")
|
||||
|
||||
type StressRSSSeries struct {
|
||||
Process StressProcessIdentity `json:"process"`
|
||||
EndRSSBytes [3]uint64 `json:"end_rss_bytes"`
|
||||
}
|
||||
|
||||
type StressSoakTrendEvidence struct {
|
||||
Series []StressRSSSeries `json:"series"`
|
||||
}
|
||||
|
||||
func ValidateStressSoakTrend(evidence StressSoakTrendEvidence) error {
|
||||
if len(evidence.Series) == 0 {
|
||||
return errors.New("stress soak RSS series are empty")
|
||||
}
|
||||
seen := make(map[string]struct{}, len(evidence.Series))
|
||||
for _, series := range evidence.Series {
|
||||
key := series.Process.key()
|
||||
if series.Process.PID < 1 || key == ":0" || (series.Process.Kind == StressProcessAgent && series.Process.Agent.Int() < 1) {
|
||||
return fmt.Errorf("process=%s: %w", key, ErrStressIdentity)
|
||||
}
|
||||
if _, duplicate := seen[key]; duplicate {
|
||||
return fmt.Errorf("duplicate process=%s: %w", key, ErrStressIdentity)
|
||||
}
|
||||
seen[key] = struct{}{}
|
||||
values := series.EndRSSBytes
|
||||
if values[0] < values[1] && values[1] < values[2] {
|
||||
return fmt.Errorf("process=%s RSS=%v: %w", key, values, ErrStressSoakTrend)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateStressSoakTrendForProfile(profile contract.Profile, evidence StressSoakTrendEvidence) error {
|
||||
want := profile.AgentCount() + 1
|
||||
if len(evidence.Series) != want {
|
||||
return fmt.Errorf("soak series=%d want=%d: %w", len(evidence.Series), want, ErrStressIdentity)
|
||||
}
|
||||
seenDashboard := 0
|
||||
seenAgents := make(map[int]struct{}, profile.AgentCount())
|
||||
for _, series := range evidence.Series {
|
||||
if err := validateStressSoakSeries(series); err != nil {
|
||||
return err
|
||||
}
|
||||
switch series.Process.Kind {
|
||||
case StressProcessDashboard:
|
||||
seenDashboard++
|
||||
case StressProcessAgent:
|
||||
ordinal := series.Process.Agent.Int()
|
||||
if ordinal < 1 || ordinal > profile.AgentCount() {
|
||||
return fmt.Errorf("unknown agent ordinal=%d: %w", ordinal, ErrStressIdentity)
|
||||
}
|
||||
if _, duplicate := seenAgents[ordinal]; duplicate {
|
||||
return fmt.Errorf("duplicate agent ordinal=%d: %w", ordinal, ErrStressIdentity)
|
||||
}
|
||||
seenAgents[ordinal] = struct{}{}
|
||||
default:
|
||||
return fmt.Errorf("unknown process kind=%q: %w", series.Process.Kind, ErrStressIdentity)
|
||||
}
|
||||
}
|
||||
if seenDashboard != 1 || len(seenAgents) != profile.AgentCount() {
|
||||
return fmt.Errorf("dashboard=%d agents=%d: %w", seenDashboard, len(seenAgents), ErrStressIdentity)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateStressSoakSeries(series StressRSSSeries) error {
|
||||
key := series.Process.key()
|
||||
if series.Process.PID < 1 || key == ":0" || (series.Process.Kind == StressProcessAgent && series.Process.Agent.Int() < 1) {
|
||||
return fmt.Errorf("process=%s: %w", key, ErrStressIdentity)
|
||||
}
|
||||
values := series.EndRSSBytes
|
||||
if values[0] < values[1] && values[1] < values[2] {
|
||||
return fmt.Errorf("process=%s RSS=%v: %w", key, values, ErrStressSoakTrend)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user