influxdb
influxdb copied to clipboard
Inconsistent Mode aggregation on all unique values
Running influx v1.8.10 I have noticed an inconsistency in the behavior of the Mode aggregation:
- When aggregating over all unique values, the Mode aggregation returns the smallest value
- When aggregating over values that are not all unique, but there are ties, the Mode aggregation returns the earliest value (this is the documented behaviour: https://docs.influxdata.com/influxdb/v1/query_language/functions/#mode)
Expected behavior is that in all cases the mode aggregation returns the earliest value in case of a tie
These unit tests showcase the two cases:
func TestCallIterator_Mode_Float_All_Equal_Occurrences_All_Unique(t *testing.T) {
itr, _ := query.NewModeIterator(&FloatIterator{Points: []query.FloatPoint{
{Time: 0, Value: 2, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 1, Value: 1, Tags: ParseTags("region=us-west,host=hostA")},
{Time: 2, Value: 4, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 3, Value: 6, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 4, Value: 0, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 6, Value: 9, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 7, Value: 3, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 8, Value: 5, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 9, Value: 7, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 10, Value: 8, Tags: ParseTags("region=us-east,host=hostA")},
}},
query.IteratorOptions{
Expr: MustParseExpr(`mode("value")`),
Dimensions: []string{"host"},
Interval: query.Interval{Duration: 11 * time.Nanosecond},
Ordered: true,
Ascending: true,
},
)
if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil {
t.Fatalf("unexpected error: %s", err)
} else if diff := cmp.Diff(a, [][]query.Point{
// The smallest value is returned
{&query.FloatPoint{Time: 0, Value: 0, Tags: ParseTags("host=hostA"), Aggregated: 0}},
}); diff != "" {
t.Fatalf("unexpected points:\n%s", diff)
}
}
func TestCallIterator_Mode_Float_All_Equal_Occurrences_Not_Unique(t *testing.T) {
itr, _ := query.NewModeIterator(&FloatIterator{Points: []query.FloatPoint{
{Time: 0, Value: 2, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 1, Value: 2, Tags: ParseTags("region=us-west,host=hostA")},
{Time: 2, Value: 4, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 3, Value: 4, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 4, Value: 0, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 6, Value: 0, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 7, Value: 3, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 8, Value: 3, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 9, Value: 7, Tags: ParseTags("region=us-east,host=hostA")},
{Time: 10, Value: 7, Tags: ParseTags("region=us-east,host=hostA")},
}},
query.IteratorOptions{
Expr: MustParseExpr(`mode("value")`),
Dimensions: []string{"host"},
Interval: query.Interval{Duration: 11 * time.Nanosecond},
Ordered: true,
Ascending: true,
},
)
if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil {
t.Fatalf("unexpected error: %s", err)
} else if diff := cmp.Diff(a, [][]query.Point{
// The earliest value is returned
{&query.FloatPoint{Time: 0, Value: 2, Tags: ParseTags("host=hostA"), Aggregated: 0}},
}); diff != "" {
t.Fatalf("unexpected points:\n%s", diff)
}
}