mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
78 lines
2.0 KiB
Go
78 lines
2.0 KiB
Go
package observability
|
|
|
|
import (
|
|
"math"
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
type SLOWindow struct {
|
|
RegionalRTT []time.Duration
|
|
Assignment []time.Duration
|
|
Connection []time.Duration
|
|
APILatency []time.Duration
|
|
Matches []bool
|
|
TickBacklog bool
|
|
Headroom float64
|
|
}
|
|
|
|
type SLOViolation struct {
|
|
Metric string
|
|
Reason string
|
|
}
|
|
|
|
func EvaluateSLO(window SLOWindow) []SLOViolation {
|
|
violations := make([]SLOViolation, 0)
|
|
if percentile(window.RegionalRTT, .95) > 80*time.Millisecond {
|
|
violations = append(violations, SLOViolation{"regional_rtt_p95", "exceeds 80ms"})
|
|
}
|
|
if percentile(window.Assignment, .95) > 5*time.Second || percentile(window.Assignment, .99) > 10*time.Second {
|
|
violations = append(violations, SLOViolation{"assignment_latency", "p95/p99 threshold exceeded"})
|
|
}
|
|
if percentile(window.Connection, .95) > 5*time.Second {
|
|
violations = append(violations, SLOViolation{"connection_latency_p95", "exceeds 5s"})
|
|
}
|
|
if ratio(window.Matches) < .999 {
|
|
violations = append(violations, SLOViolation{"allocation_result_success", "below 99.9%"})
|
|
}
|
|
if percentile(window.APILatency, .95) > 250*time.Millisecond {
|
|
violations = append(violations, SLOViolation{"api_latency_p95", "exceeds 250ms"})
|
|
}
|
|
if window.TickBacklog {
|
|
violations = append(violations, SLOViolation{"tick_health", "physics backlog detected"})
|
|
}
|
|
if window.Headroom > 0 && window.Headroom < .30 {
|
|
violations = append(violations, SLOViolation{"resource_headroom", "below 30%"})
|
|
}
|
|
return violations
|
|
}
|
|
|
|
func percentile(values []time.Duration, p float64) time.Duration {
|
|
if len(values) == 0 {
|
|
return 0
|
|
}
|
|
ordered := append([]time.Duration(nil), values...)
|
|
sort.Slice(ordered, func(i, j int) bool { return ordered[i] < ordered[j] })
|
|
index := int(math.Ceil(p*float64(len(ordered)))) - 1
|
|
if index < 0 {
|
|
index = 0
|
|
}
|
|
if index >= len(ordered) {
|
|
index = len(ordered) - 1
|
|
}
|
|
return ordered[index]
|
|
}
|
|
|
|
func ratio(values []bool) float64 {
|
|
if len(values) == 0 {
|
|
return 1
|
|
}
|
|
success := 0
|
|
for _, value := range values {
|
|
if value {
|
|
success++
|
|
}
|
|
}
|
|
return float64(success) / float64(len(values))
|
|
}
|