func TestSumAverage(t *testing.T) { aggregator := aggregators.New( 1000.0, 2000.0, aggregators.Sum, 200.0, aggregators.Avg, aggregators.NaN, nil) aggregator.Add(tsdb.TimeSeries{ {1000.0, 42.0}, {1030.0, 54.0}, {1199.999, 49.5}, {1401.0, 20.0}, {1599.0, 30.0}, {1836.0, 98.0}}) aggregator.Add(tsdb.TimeSeries{ {1500.0, 1025.0}, {1600.0, 99.0}, {1800.0, 198.0}, {1801.0, 202.0}, {1999.1, 200.0}}) aggregator.Add(tsdb.TimeSeries{ {1400.0, 1975.0}, {1450.0, 2000.0}, {1599.0, 2025.0}, {1599.1, 2050.0}, {1599.2, 2075.0}}) aggregator.Add(nil) aggregated := aggregator.Aggregate() expected := tsdb.TimeSeries{ {1000.0, 48.5}, {1400.0, 3075.0}, {1600.0, 99.0}, {1800.0, 298.0}} assertValueDeepEqual(t, expected, aggregated) }
func TestLinearInterpolation(t *testing.T) { aggregator := aggregators.New( 1000.0, 2000.0, aggregators.Avg, 200.0, aggregators.Avg, aggregators.None, nil) aggregator.Add(tsdb.TimeSeries{ {1000.0, 31.0}, {1030.0, 31.5}, {1199.999, 31.25}, {1401.0, 20.0}, {1599.0, 30.0}, {1836.0, 75.0}}) aggregator.Add(nil) aggregated := aggregator.Aggregate() expected := tsdb.TimeSeries{ {1000.0, 31.25}, {1200.0, 28.125}, {1400.0, 25.0}, {1600.0, 50.0}, {1800.0, 75.0}} assertValueDeepEqual(t, expected, aggregated) aggregator.Add(tsdb.TimeSeries{ {1200.0, 40.0}, {1600.0, 46.0}}) aggregated = aggregator.Aggregate() expected = tsdb.TimeSeries{ {1000.0, 31.25}, {1200.0, 34.0625}, {1400.0, 34.0}, {1600.0, 48.0}, {1800.0, 75.0}} assertValueDeepEqual(t, expected, aggregated) }
func TestAverageZero(t *testing.T) { aggregator := aggregators.New( 1000.0, 2000.0, aggregators.Avg, 200.0, aggregators.Avg, aggregators.Zero, nil) aggregator.Add(tsdb.TimeSeries{ {1000.0, 42.0}, {1030.0, 54.0}, {1199.999, 49.5}, {1401.0, 20.0}, {1599.0, 30.0}, {1836.0, 98.0}}) aggregator.Add(tsdb.TimeSeries{ {1500.0, 1025.0}, {1600.0, 99.0}, {1800.0, 198.0}, {1801.0, 202.0}, {1999.1, 200.0}}) aggregator.Add(tsdb.TimeSeries{ {1400.0, 1975.0}, {1450.0, 2000.0}, {1599.0, 2025.0}, {1599.1, 2050.0}, {1599.2, 2075.0}}) // Counts as all zeros aggregator.Add(nil) aggregated := aggregator.Aggregate() expected := tsdb.TimeSeries{ {1000.0, 12.125}, {1200.0, 0.0}, {1400.0, 768.75}, {1600.0, 24.75}, {1800.0, 74.5}} assertValueDeepEqual(t, expected, aggregated) }
func TestCount(t *testing.T) { aggregator := aggregators.New( 1043.0, 2021.0, aggregators.Count, 200.0, aggregators.Avg, aggregators.NaN, nil) aggregator.Add(tsdb.TimeSeries{ {1043.0, 42.0}, {1044.0, 54.0}, {1199.999, 49.5}, {1200.0, 35.0}, {1401.0, 20.0}, {1599.0, 30.0}, {1836.0, 98.0}, {2019.0, 1.3}}) aggregator.Add(nil) aggregator.Add(tsdb.TimeSeries{ {1043.0, 42.0}, {1044.0, 54.0}, {1199.999, 49.5}, {1200.0, 53.0}, {1401.0, 20.0}, {1599.0, 30.0}, {1836.0, 98.0}, {2019.0, 1.3}}) aggregated := aggregator.Aggregate() expected := tsdb.TimeSeries{ {1200.0, 2.0}, {1400.0, 2.0}, {1600.0, 0.0}, {1800.0, 2.0}} assertValueDeepEqual(t, expected, aggregated) }
func TestStartEqualsEnd(t *testing.T) { aggregators.New( 1057.0, 1057.0, aggregators.Avg, 200.0, aggregators.Avg, aggregators.NaN, nil) aggregators.New( 1000.0, 1000.0, aggregators.Avg, 200.0, aggregators.Avg, aggregators.NaN, nil) }
func TestAverageNone(t *testing.T) { aggregator := aggregators.New( 1000.0, 2000.0, aggregators.Avg, 200.0, aggregators.Avg, aggregators.NaN, nil) aggregated := aggregator.Aggregate() if len(aggregated) != 0 { t.Error("Expected no aggregation") } }
func TestRateMissingValues(t *testing.T) { aggregator := aggregators.New( 1000.0, 2000.0, aggregators.Avg, 200.0, aggregators.Avg, aggregators.NaN, &aggregators.RateSpec{}) aggregator.Add(tsdb.TimeSeries{ {1000.0, 10000.0}, {1600.0, 49000.0}, {1800.0, 52000.0}}) aggregated := aggregator.Aggregate() expected := tsdb.TimeSeries{ {1000.0, 65.0}, {1200.0, 65.0}, {1400.0, 65.0}, {1600.0, 15.0}} assertValueDeepEqual(t, expected, aggregated) aggregator = aggregators.New( 1000.0, 2000.0, aggregators.Avg, 200.0, aggregators.Avg, aggregators.NaN, &aggregators.RateSpec{}) aggregator.Add(tsdb.TimeSeries{ {1400.0, 10000.0}, {1600.0, 49000.0}}) aggregated = aggregator.Aggregate() expected = tsdb.TimeSeries{ {1400.0, 195.0}} assertValueDeepEqual(t, expected, aggregated) }
func TestAverageStrangeStartAndEnd(t *testing.T) { aggregator := aggregators.New( 1057.0, 1938.0, aggregators.Avg, 200.0, aggregators.Avg, aggregators.NaN, nil) aggregator.Add(tsdb.TimeSeries{ {1057.0, 30.0}, {1199.0, 40.0}, {1401.0, 20.0}, {1599.0, 30.0}, {1836.0, 98.0}}) aggregated := aggregator.Aggregate() expected := tsdb.TimeSeries{{1400.0, 25.0}} assertValueDeepEqual(t, expected, aggregated) }
func TestNegativeStart(t *testing.T) { aggregator := aggregators.New( -29028.0, 29028.0, aggregators.Avg, 10000.0, aggregators.Avg, aggregators.NaN, nil) aggregator.Add(tsdb.TimeSeries{ {-29028.0, -60.0}, {-21000.0, -50.0}, {-3000.0, -5.0}, {3000.0, 5.0}, {29027.0, 43.0}}) aggregated := aggregator.Aggregate() expected := tsdb.TimeSeries{ {-10000.0, -5.0}, {0, 5.0}} assertValueDeepEqual(t, expected, aggregated) }
func (a *aggregatorTesterType) Verify(t *testing.T) { length := len(a.expected) agg := aggregators.New( 0, float64(length)*kMaxSampleSize, aggregators.Sum, kMaxSampleSize, a.aggregator, a.fillPolicy, nil) var timeSeries tsdb.TimeSeries for i := range a.expected { for j, val := range a.expected[i].Values { timeSeries = append( timeSeries, tsdb.TsValue{ float64(i)*kMaxSampleSize + float64(j), val}) } } agg.Add(timeSeries) aggregatedTimeSeries := agg.Aggregate() aggIdx := 0 for i := range a.expected { if !a.expected[i].Valid { continue } if aggIdx >= len(aggregatedTimeSeries) || aggregatedTimeSeries[aggIdx].Ts != float64(i)*kMaxSampleSize { t.Error( "Timestamps don't match. No value was emitted when one was expected or the other way around. Or maybe the Len() function is wrong.") return } if a.expected[i].Answer != aggregatedTimeSeries[aggIdx].Value { t.Errorf( "Expected %g for %v, got %g", a.expected[i].Answer, a.expected[i].Values, aggregatedTimeSeries[aggIdx].Value) } aggIdx++ } }
func newAggregatorGenerator( aggregatorStr string, downSample *DownSampleSpec, rateOptions *RateSpec) ( tsdb.AggregatorGenerator, error) { if downSample == nil { return nil, ErrUnsupportedAggregator } aggregator, ok := aggregators.ByName(aggregatorStr) if !ok { return nil, ErrUnsupportedAggregator } downSampleAggregator, ok := aggregators.ByName(downSample.Type) if !ok { return nil, ErrUnsupportedAggregator } fill, _ := aggregators.ByFillPolicyName(downSample.Fill) duration := downSample.DurationInSeconds var rateSpec *aggregators.RateSpec if rateOptions != nil { rateSpec = &aggregators.RateSpec{ Counter: rateOptions.Counter, CounterMax: rateOptions.CounterMax, ResetValue: rateOptions.ResetValue, } } return func(start, end float64) (tsdb.Aggregator, error) { if (end-start)/duration > kMaxDownSampleBuckets { return nil, kErrTimeRangeTooBig } return aggregators.New( start, end, aggregator, duration, downSampleAggregator, fill, rateSpec), nil }, nil }
func TestRateNoResetOrMax(t *testing.T) { aggregator := aggregators.New( 1000.0, 2000.0, aggregators.Avg, 200.0, aggregators.Avg, aggregators.NaN, &aggregators.RateSpec{Counter: true}) aggregator.Add(tsdb.TimeSeries{ {1000.0, 10000.0}, {1200.0, 49000.0}, {1400.0, 3000.0}, {1600.0, 53000.0}, {1800.0, 52000.0}}) aggregated := aggregator.Aggregate() expected := tsdb.TimeSeries{ {1000.0, 195.0}, {1200.0, 0.0}, {1400.0, 250.0}, {1600.0, 0.0}} assertValueDeepEqual(t, expected, aggregated) }
func TestAPI(t *testing.T) { alBuilder := datastructs.NewApplicationListBuilder() alBuilder.Add( 37, "AnApp", sources.ConnectorList{trisource.GetConnector()}) alBuilder.Add( 97, "AnotherApp", sources.ConnectorList{trisource.GetConnector()}) appList := alBuilder.Build() appStatus := datastructs.NewApplicationStatuses( appList, newStore( t, "TestAPI", 2, 100, 1.0, 10)) appStatus.MarkHostsActiveExclusively( 100.0, []string{"host1", "host2", "host3", "host4", "host5"}) endpointId, aStore := appStatus.EndpointIdByHostAndName( "host1", "AnApp") addValues(t, aStore, endpointId, "/foo", 500.0, 30.0, 510.0, 31.0, 520.0, 32.0, 530.0, 33.0, 540.0, 34.0) endpointId, aStore = appStatus.EndpointIdByHostAndName( "host1", "AnotherApp") addValues(t, aStore, endpointId, "/foo", 500.0, 40.0, 510.0, 41.0, 520.0, 42.0, 530.0, 43.0, 540.0, 44.0) endpointId, aStore = appStatus.EndpointIdByHostAndName( "host2", "AnApp") addValues(t, aStore, endpointId, "/foo", 500.0, 50.0, 510.0, 51.0, 520.0, 52.0, 530.0, 53.0, 540.0, 54.0) endpointId, aStore = appStatus.EndpointIdByHostAndName( "host2", "AnotherApp") addValues(t, aStore, endpointId, "/foo", 500.0, 60.0, 510.0, 61.0, 520.0, 62.0, 530.0, 63.0, 540.0, 64.0) endpointId, aStore = appStatus.EndpointIdByHostAndName( "host3", "AnApp") addValues(t, aStore, endpointId, "/foo", 500.0, 70.0, 510.0, 71.0, 520.0, 72.0, 530.0, 73.0, 540.0, 74.0) endpointId, aStore = appStatus.EndpointIdByHostAndName( "host3", "AnotherApp") addValues(t, aStore, endpointId, "/foo", 500.0, 80.0, 510.0, 81.0, 520.0, 82.0, 530.0, 83.0, 540.0, 84.0) endpointId, aStore = appStatus.EndpointIdByHostAndName( "host5", "AnApp") addValues(t, aStore, endpointId, "/bar", 700.0, 80.0, 800.0, 100.0) var taggedTimeSeriesSet *tsdb.TaggedTimeSeriesSet var err error if taggedTimeSeriesSet, err = tsdbimpl.Query( appStatus, "/foo", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 500.0, 600.0, nil); err != nil { t.Fatal(err) } expected := &tsdb.TaggedTimeSeriesSet{ MetricName: "/foo", Data: []tsdb.TaggedTimeSeries{ { Values: tsdb.TimeSeries{ {500.0, 55.5}, {520.0, 57.5}, {540.0, 59.0}, }, }, }, } assertTaggedTimeSeriesSetEquals( t, expected, taggedTimeSeriesSet, ) if _, err = tsdbimpl.Query( appStatus, "/not there", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 500.0, 600.0, nil); err != tsdbimpl.ErrNoSuchMetric { t.Error("Expected ErrNoSuchName") } if taggedTimeSeriesSet, err = tsdbimpl.Query( appStatus, "/bar", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 500.0, 1000.0, nil); err != nil { t.Fatal(err) } expected = &tsdb.TaggedTimeSeriesSet{ MetricName: "/bar", Data: []tsdb.TaggedTimeSeries{ { Values: tsdb.TimeSeries{ {700.0, 80.0}, {800.0, 100.0}, }, }, }, } assertTaggedTimeSeriesSetEquals( t, expected, taggedTimeSeriesSet, ) if taggedTimeSeriesSet, err = tsdbimpl.Query( appStatus, "/foo", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 501.0, 539.0, nil); err != nil { t.Fatal(err) } expected = &tsdb.TaggedTimeSeriesSet{ MetricName: "/foo", } assertTaggedTimeSeriesSetEquals( t, expected, taggedTimeSeriesSet, ) options := &tsdbimpl.QueryOptions{ GroupByHostName: true, } if taggedTimeSeriesSet, err = tsdbimpl.Query( appStatus, "/foo", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 400.0, 700.0, options); err != nil { t.Fatal(err) } expected = &tsdb.TaggedTimeSeriesSet{ MetricName: "/foo", Data: []tsdb.TaggedTimeSeries{ { Tags: tsdb.TagSet{ HostName: "host1", }, Values: tsdb.TimeSeries{ {500.0, 35.5}, {520.0, 37.5}, {540.0, 39.0}, }, }, { Tags: tsdb.TagSet{ HostName: "host2", }, Values: tsdb.TimeSeries{ {500.0, 55.5}, {520.0, 57.5}, {540.0, 59.0}, }, }, { Tags: tsdb.TagSet{ HostName: "host3", }, Values: tsdb.TimeSeries{ {500.0, 75.5}, {520.0, 77.5}, {540.0, 79.0}, }, }, }, GroupedByHostName: true, } assertTaggedTimeSeriesSetEquals( t, expected, taggedTimeSeriesSet, ) options = &tsdbimpl.QueryOptions{ GroupByHostName: true, } if taggedTimeSeriesSet, err = tsdbimpl.Query( appStatus, "/foo", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 700.0, 900.0, options); err != nil { t.Fatal(err) } expected = &tsdb.TaggedTimeSeriesSet{ MetricName: "/foo", GroupedByHostName: true, } assertTaggedTimeSeriesSetEquals( t, expected, taggedTimeSeriesSet, ) options = &tsdbimpl.QueryOptions{ GroupByAppName: true, } if taggedTimeSeriesSet, err = tsdbimpl.Query( appStatus, "/foo", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 400.0, 700.0, options); err != nil { t.Fatal(err) } expected = &tsdb.TaggedTimeSeriesSet{ MetricName: "/foo", Data: []tsdb.TaggedTimeSeries{ { Tags: tsdb.TagSet{ AppName: "AnApp", }, Values: tsdb.TimeSeries{ {500.0, 50.5}, {520.0, 52.5}, {540.0, 54.0}, }, }, { Tags: tsdb.TagSet{ AppName: "AnotherApp", }, Values: tsdb.TimeSeries{ {500.0, 60.5}, {520.0, 62.5}, {540.0, 64}, }, }, }, GroupedByAppName: true, } assertTaggedTimeSeriesSetEquals( t, expected, taggedTimeSeriesSet, ) options = &tsdbimpl.QueryOptions{ GroupByHostName: true, GroupByAppName: true, } if taggedTimeSeriesSet, err = tsdbimpl.Query( appStatus, "/foo", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 400.0, 700.0, options); err != nil { t.Fatal(err) } expected = &tsdb.TaggedTimeSeriesSet{ MetricName: "/foo", Data: []tsdb.TaggedTimeSeries{ { Tags: tsdb.TagSet{ HostName: "host1", AppName: "AnApp", }, Values: tsdb.TimeSeries{ {500.0, 30.5}, {520.0, 32.5}, {540.0, 34.0}, }, }, { Tags: tsdb.TagSet{ HostName: "host1", AppName: "AnotherApp", }, Values: tsdb.TimeSeries{ {500.0, 40.5}, {520.0, 42.5}, {540.0, 44.0}, }, }, { Tags: tsdb.TagSet{ HostName: "host2", AppName: "AnApp", }, Values: tsdb.TimeSeries{ {500.0, 50.5}, {520.0, 52.5}, {540.0, 54.0}, }, }, { Tags: tsdb.TagSet{ HostName: "host2", AppName: "AnotherApp", }, Values: tsdb.TimeSeries{ {500.0, 60.5}, {520.0, 62.5}, {540.0, 64.0}, }, }, { Tags: tsdb.TagSet{ HostName: "host3", AppName: "AnApp", }, Values: tsdb.TimeSeries{ {500.0, 70.5}, {520.0, 72.5}, {540.0, 74.0}, }, }, { Tags: tsdb.TagSet{ HostName: "host3", AppName: "AnotherApp", }, Values: tsdb.TimeSeries{ {500.0, 80.5}, {520.0, 82.5}, {540.0, 84.0}, }, }, }, GroupedByHostName: true, GroupedByAppName: true, } assertTaggedTimeSeriesSetEquals( t, expected, taggedTimeSeriesSet, ) options = &tsdbimpl.QueryOptions{ GroupByHostName: true, GroupByAppName: true, } if taggedTimeSeriesSet, err = tsdbimpl.Query( appStatus, "/foo", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 700.0, 900.0, options); err != nil { t.Fatal(err) } expected = &tsdb.TaggedTimeSeriesSet{ MetricName: "/foo", GroupedByHostName: true, GroupedByAppName: true, } assertTaggedTimeSeriesSetEquals( t, expected, taggedTimeSeriesSet, ) options = &tsdbimpl.QueryOptions{ HostNameFilter: tagFilter(func(s string) bool { return s == "host2" || s == "host3" }), AppNameFilter: tagFilter(func(s string) bool { return s == "AnApp" }), GroupByHostName: true, GroupByAppName: true, } if taggedTimeSeriesSet, err = tsdbimpl.Query( appStatus, "/foo", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 400.0, 700.0, options); err != nil { t.Fatal(err) } expected = &tsdb.TaggedTimeSeriesSet{ MetricName: "/foo", Data: []tsdb.TaggedTimeSeries{ { Tags: tsdb.TagSet{ HostName: "host2", AppName: "AnApp", }, Values: tsdb.TimeSeries{ {500.0, 50.5}, {520.0, 52.5}, {540.0, 54.0}, }, }, { Tags: tsdb.TagSet{ HostName: "host3", AppName: "AnApp", }, Values: tsdb.TimeSeries{ {500.0, 70.5}, {520.0, 72.5}, {540.0, 74.0}, }, }, }, GroupedByHostName: true, GroupedByAppName: true, } assertTaggedTimeSeriesSetEquals( t, expected, taggedTimeSeriesSet, ) options = &tsdbimpl.QueryOptions{ HostNameFilter: tagFilter(func(s string) bool { return s == "host2" || s == "host3" }), AppNameFilter: tagFilter(func(s string) bool { return s == "AnApp" }), } if taggedTimeSeriesSet, err = tsdbimpl.Query( appStatus, "/foo", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 400.0, 700.0, options); err != nil { t.Fatal(err) } expected = &tsdb.TaggedTimeSeriesSet{ MetricName: "/foo", Data: []tsdb.TaggedTimeSeries{ { Values: tsdb.TimeSeries{ {500.0, 60.5}, {520.0, 62.5}, {540.0, 64.0}, }, }, }, } assertTaggedTimeSeriesSetEquals( t, expected, taggedTimeSeriesSet, ) options = &tsdbimpl.QueryOptions{ HostNameFilter: tagFilter(func(s string) bool { return s == "host2" || s == "host3" }), AppNameFilter: tagFilter(func(s string) bool { return s == "No app" }), } if _, err = tsdbimpl.Query( appStatus, "/foo", func(start, end float64) (tsdb.Aggregator, error) { return aggregators.New( start, end, aggregators.Avg, 20.0, aggregators.Avg, aggregators.NaN, nil), nil }, 400.0, 700.0, options); err != tsdbimpl.ErrNoSuchMetric { t.Error("Expected ErrNoSuchMetric") } }