Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## main / unreleased
* [BUGFIX] Correct avg_over_time calculation [#6252](https://github.com/grafana/tempo/pull/6252) (@ruslan-mikhailov)

# v2.10.0-rc.0

Expand Down
1 change: 1 addition & 0 deletions pkg/traceql/engine_metrics_average.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ func (k *averageSeries) addWeigthedMean(interval int, mean float64, weight float
meanDelta -= currentMean.compensation

currentMean.add(meanDelta)
currentMean.weight = sumWeights
k.values[interval] = currentMean
}

Expand Down
37 changes: 37 additions & 0 deletions pkg/traceql/engine_metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,43 @@ func TestAvgOverTimeForDurationWithoutAggregation(t *testing.T) {
assert.Equal(t, 200., avg.Values[2]*float64(time.Second))
}

func TestAvgOverTimeCombine(t *testing.T) {
req := &tempopb.QueryRangeRequest{
Start: 1,
End: uint64(3 * time.Second),
Step: uint64(1 * time.Second),
Query: "{ } | avg_over_time(duration)",
}

// Three set of spans with different data for a single time interval
// Each set will be passed to level 2 independently
in1 := []Span{
newMockSpan(nil).WithStartTime(uint64(1 * time.Second)).WithDuration(uint64(100 * time.Second)),
}

in2 := []Span{
newMockSpan(nil).WithStartTime(uint64(1 * time.Second)).WithDuration(uint64(200 * time.Second)),
newMockSpan(nil).WithStartTime(uint64(1 * time.Second)).WithDuration(uint64(400 * time.Second)),
}

in3 := []Span{
newMockSpan(nil).WithStartTime(uint64(1 * time.Second)).WithDuration(uint64(500 * time.Second)),
newMockSpan(nil).WithStartTime(uint64(1 * time.Second)).WithDuration(uint64(600 * time.Second)),
newMockSpan(nil).WithStartTime(uint64(1 * time.Second)).WithDuration(uint64(700 * time.Second)),
}

result, seriesCount, err := runTraceQLMetric(req, in1, in2, in3)
require.NoError(t, err)
require.Equal(t, len(result), seriesCount)

avg := result[LabelsFromArgs("__name__", "avg_over_time").MapKey()]

expectedResult := (100 + 200 + 400 + 500 + 600 + 700) / 6.
assert.Equal(t, expectedResult, avg.Values[0])
assert.True(t, math.IsNaN(avg.Values[1]), "expected NaN, got %f", avg.Values[1])
assert.True(t, math.IsNaN(avg.Values[2]), "expected NaN, got %f", avg.Values[2])
}

func TestAvgOverTimeForSpanAttribute(t *testing.T) {
req := &tempopb.QueryRangeRequest{
Start: 1,
Expand Down
26 changes: 24 additions & 2 deletions tempodb/tempodb_metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,7 @@ var queryRangeTestCases = []struct {
},
},
},
expectedL2: nil,
expectedL3: []*tempopb.TimeSeries{
expectedL2: []*tempopb.TimeSeries{
{
Labels: []common_v1.KeyValue{tempopb.MakeKeyValueString("__name__", "avg_over_time")},
Samples: []tempopb.Sample{
Expand All @@ -255,6 +254,29 @@ var queryRangeTestCases = []struct {
{TimestampMs: 60_000, Value: 240 / 5.0}, // sum from 46 to 50 is 240
},
},
{
Labels: []common_v1.KeyValue{
tempopb.MakeKeyValueString("__name__", "avg_over_time"),
tempopb.MakeKeyValueString("__meta_type", "__count"),
},
Samples: []tempopb.Sample{
{TimestampMs: 15_000, Value: 2 * 15},
{TimestampMs: 30_000, Value: 2 * 15},
{TimestampMs: 45_000, Value: 2 * 15},
{TimestampMs: 60_000, Value: 2 * 5},
},
},
},
expectedL3: []*tempopb.TimeSeries{
{
Labels: []common_v1.KeyValue{tempopb.MakeKeyValueString("__name__", "avg_over_time")},
Samples: []tempopb.Sample{
{TimestampMs: 15_000, Value: 120 / 15.0},
{TimestampMs: 30_000, Value: 345 / 15.0},
{TimestampMs: 45_000, Value: 570 / 15.0},
{TimestampMs: 60_000, Value: 240 / 5.0},
},
},
},
},
{
Expand Down
Loading