Beispiel #1
0
func query(
	request *tsdbjson.QueryRequest,
	endpoints *datastructs.ApplicationStatuses,
	minDownSampleTime time.Duration) (
	result []tsdbjson.TimeSeries, err error) {
	parsedQueries, err := tsdbjson.ParseQueryRequest(request)
	if err != nil {
		return
	}
	var allSeries []tsdbjson.TimeSeries
	for i := range parsedQueries {
		var options tsdbimpl.QueryOptions
		options.HostNameFilter, err = newTagFilter(
			parsedQueries[i].Options.HostNameFilter)
		if err != nil {
			return
		}
		options.AppNameFilter, err = newTagFilter(
			parsedQueries[i].Options.AppNameFilter)
		if err != nil {
			return
		}
		options.GroupByAppName = parsedQueries[i].Options.GroupByAppName
		options.GroupByHostName = parsedQueries[i].Options.GroupByHostName
		if parsedQueries[i].Aggregator.DownSample == nil {
			return nil, tsdbjson.ErrUnsupportedAggregator
		}
		ensureDurationAtLeast(
			duration.ToFloat(minDownSampleTime),
			&parsedQueries[i].Aggregator.DownSample)
		var aggregatorGen tsdb.AggregatorGenerator
		aggregatorGen, err = tsdbjson.NewAggregatorGenerator(
			parsedQueries[i].Aggregator.Type,
			parsedQueries[i].Aggregator.DownSample,
			parsedQueries[i].Aggregator.RateOptions,
		)
		if err != nil {
			return
		}
		var series *tsdb.TaggedTimeSeriesSet
		series, err = tsdbimpl.Query(
			endpoints,
			parsedQueries[i].Metric,
			aggregatorGen,
			parsedQueries[i].Start,
			parsedQueries[i].End,
			&options)
		if err != nil {
			return
		}
		allSeries = append(allSeries, tsdbjson.NewTimeSeriesSlice(series)...)
	}
	if allSeries == nil {
		return make([]tsdbjson.TimeSeries, 0), nil
	}
	return allSeries, nil
}
Beispiel #2
0
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")
	}
}