test: report exact ACK latency percentiles
This commit is contained in:
@@ -87,7 +87,7 @@ func runMerge(aPath, bPath, output string) error {
|
||||
if report.PublishAttempted > 0 {
|
||||
report.PublishSuccessRate = float64(report.PublishAccepted) / float64(report.PublishAttempted)
|
||||
}
|
||||
report.AckP95MS = mergedHistogramP95(report.Agents, func(summary AgentSummary) HistogramSnapshot { return summary.AckLatency })
|
||||
report.AckP95MS = mergedAckP95(report.Agents)
|
||||
report.DeliveryP95MS = mergedHistogramP95(report.Agents, func(summary AgentSummary) HistogramSnapshot { return summary.DeliveryLatency })
|
||||
if report.ExpectedDeliveries > 0 {
|
||||
report.ArrivalRate = float64(report.ReceivedDeliveries) / float64(report.ExpectedDeliveries)
|
||||
@@ -102,7 +102,7 @@ func runMerge(aPath, bPath, output string) error {
|
||||
fmt.Sprintf("publish success rate=%.6f expected>=0.999900", report.PublishSuccessRate))
|
||||
}
|
||||
if report.AckP95MS > 500 {
|
||||
report.FailureReasons = append(report.FailureReasons, fmt.Sprintf("ack p95=%.0fms expected<=500ms", report.AckP95MS))
|
||||
report.FailureReasons = append(report.FailureReasons, fmt.Sprintf("ack p95=%.3fms expected<=500ms", report.AckP95MS))
|
||||
}
|
||||
if report.DeliveryP95MS > 1000 {
|
||||
report.FailureReasons = append(report.FailureReasons,
|
||||
@@ -121,6 +121,26 @@ func runMerge(aPath, bPath, output string) error {
|
||||
return writeJSONFile(output, report)
|
||||
}
|
||||
|
||||
func mergedAckP95(agents []AgentSummary) float64 {
|
||||
var expected int64
|
||||
latencies := make([]float64, 0)
|
||||
for _, agent := range agents {
|
||||
expected += agent.AckLatency.Count
|
||||
for _, message := range agent.AcceptedLocal {
|
||||
if message.SentAt.IsZero() || message.AckAt.Before(message.SentAt) {
|
||||
continue
|
||||
}
|
||||
latencies = append(latencies, float64(message.AckAt.Sub(message.SentAt))/float64(time.Millisecond))
|
||||
}
|
||||
}
|
||||
if expected == 0 || int64(len(latencies)) != expected {
|
||||
return mergedHistogramP95(agents, func(summary AgentSummary) HistogramSnapshot { return summary.AckLatency })
|
||||
}
|
||||
sort.Float64s(latencies)
|
||||
index := (len(latencies)*95 + 99) / 100
|
||||
return latencies[index-1]
|
||||
}
|
||||
|
||||
func mergedHistogramP95(agents []AgentSummary, selectHistogram func(AgentSummary) HistogramSnapshot) float64 {
|
||||
var count int64
|
||||
buckets := make([]int64, len(latencyBounds)+1)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRunMergeComputesArrivalAndPersistenceGate(t *testing.T) {
|
||||
@@ -53,6 +54,32 @@ func TestMergedHistogramP95(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergedAckP95UsesExactAcceptedTimestamps(t *testing.T) {
|
||||
base := time.Date(2026, 9, 27, 8, 0, 0, 0, time.UTC)
|
||||
agents := []AgentSummary{{
|
||||
AckLatency: HistogramSnapshot{Count: 4, MaxMS: 900, Buckets: map[string]int64{"1s": 4}},
|
||||
AcceptedLocal: []AcceptedMessage{
|
||||
{SentAt: base, AckAt: base.Add(100 * time.Millisecond)},
|
||||
{SentAt: base, AckAt: base.Add(200 * time.Millisecond)},
|
||||
{SentAt: base, AckAt: base.Add(300 * time.Millisecond)},
|
||||
{SentAt: base, AckAt: base.Add(400 * time.Millisecond)},
|
||||
},
|
||||
}}
|
||||
if got := mergedAckP95(agents); got != 400 {
|
||||
t.Fatalf("exact p95=%v want=400", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergedAckP95FallsBackWhenRawSamplesAreIncomplete(t *testing.T) {
|
||||
agents := []AgentSummary{{
|
||||
AckLatency: HistogramSnapshot{Count: 2, MaxMS: 900, Buckets: map[string]int64{"1s": 2}},
|
||||
AcceptedLocal: []AcceptedMessage{{SentAt: time.Now(), AckAt: time.Now().Add(100 * time.Millisecond)}},
|
||||
}}
|
||||
if got := mergedAckP95(agents); got != 1000 {
|
||||
t.Fatalf("fallback p95=%v want=1000", got)
|
||||
}
|
||||
}
|
||||
|
||||
func writeSummaryForTest(t *testing.T, path string, summary AgentSummary) {
|
||||
t.Helper()
|
||||
raw, err := json.Marshal(summary)
|
||||
|
||||
Reference in New Issue
Block a user