(t *testing.T)
| 3590 | } |
| 3591 | |
| 3592 | func TestHistogramAggregator_LatencySpike(t *testing.T) { |
| 3593 | // Simulate a latency spike: normal traffic, then a spike, then normal again |
| 3594 | // Use fixed timestamps to ensure deterministic behavior |
| 3595 | baseTime := time.Unix(1640995200, 0) // Fixed timestamp: 2022-01-01 00:00:00 UTC |
| 3596 | start := baseTime |
| 3597 | req := &tempopb.QueryRangeRequest{ |
| 3598 | Start: uint64(start.UnixNano()), |
| 3599 | End: uint64(start.Add(45 * time.Minute).UnixNano()), |
| 3600 | Step: uint64(15 * time.Minute), // 3 intervals: normal, spike, normal |
| 3601 | } |
| 3602 | quantiles := []float64{0.5, 0.9, 0.99} |
| 3603 | |
| 3604 | agg := NewHistogramAggregator(req, quantiles, 20) |
| 3605 | |
| 3606 | // Interval 1: Normal latency (0-15min) - p50=100ms, p90=200ms, p99=500ms |
| 3607 | normal1Time := start.Add(7 * time.Minute) |
| 3608 | normalSeries1 := []*tempopb.TimeSeries{ |
| 3609 | createBucketSeries("0.125", 70, normal1Time.UnixMilli()), // 70 fast requests |
| 3610 | createBucketSeries("0.25", 20, normal1Time.UnixMilli()), // 20 medium requests |
| 3611 | createBucketSeries("0.5", 8, normal1Time.UnixMilli()), // 8 slow requests |
| 3612 | createBucketSeries("1.0", 2, normal1Time.UnixMilli()), // 2 very slow requests |
| 3613 | } |
| 3614 | |
| 3615 | // Add exemplars for normal period |
| 3616 | normalSeries1[0].Exemplars = []tempopb.Exemplar{ |
| 3617 | {Value: 0.08, TimestampMs: normal1Time.UnixMilli()}, // Fast - should go to p50 |
| 3618 | {Value: 0.12, TimestampMs: normal1Time.UnixMilli()}, // Fast - should go to p50 |
| 3619 | } |
| 3620 | normalSeries1[1].Exemplars = []tempopb.Exemplar{ |
| 3621 | {Value: 0.18, TimestampMs: normal1Time.UnixMilli()}, // Medium - should go to p90 |
| 3622 | } |
| 3623 | normalSeries1[2].Exemplars = []tempopb.Exemplar{ |
| 3624 | {Value: 0.35, TimestampMs: normal1Time.UnixMilli()}, // Slow - should go to p99 |
| 3625 | } |
| 3626 | |
| 3627 | // Interval 2: Latency spike (15-30min) - p50=800ms, p90=2000ms, p99=4000ms |
| 3628 | spikeTime := start.Add(22 * time.Minute) |
| 3629 | spikeSeries := []*tempopb.TimeSeries{ |
| 3630 | createBucketSeries("1.0", 50, spikeTime.UnixMilli()), // 50 slow requests (now "fast" for spike) |
| 3631 | createBucketSeries("2.0", 30, spikeTime.UnixMilli()), // 30 very slow requests |
| 3632 | createBucketSeries("4.0", 15, spikeTime.UnixMilli()), // 15 extremely slow requests |
| 3633 | createBucketSeries("8.0", 5, spikeTime.UnixMilli()), // 5 timeout requests |
| 3634 | } |
| 3635 | |
| 3636 | // Add exemplars during spike - these should be assigned contextually |
| 3637 | spikeSeries[0].Exemplars = []tempopb.Exemplar{ |
| 3638 | {Value: 0.9, TimestampMs: spikeTime.UnixMilli()}, // During spike, this is p50! |
| 3639 | {Value: 1.1, TimestampMs: spikeTime.UnixMilli()}, // During spike, this is p50! |
| 3640 | } |
| 3641 | spikeSeries[1].Exemplars = []tempopb.Exemplar{ |
| 3642 | {Value: 1.8, TimestampMs: spikeTime.UnixMilli()}, // During spike, this is p90! |
| 3643 | } |
| 3644 | spikeSeries[2].Exemplars = []tempopb.Exemplar{ |
| 3645 | {Value: 3.5, TimestampMs: spikeTime.UnixMilli()}, // During spike, this is p99! |
| 3646 | } |
| 3647 | |
| 3648 | // Interval 3: Back to normal (30-45min) - p50=100ms, p90=200ms, p99=500ms |
| 3649 | normal2Time := start.Add(37 * time.Minute) |
nothing calls this directly
no test coverage detected