// TestServerQueryStarvation tests a very specific scenario, wherein a single // query request has more queries than the server's MaxWorkers count. func TestServerQueryStarvation(t *testing.T) { defer leaktest.AfterTest(t)() workerCount := 20 s, _, _ := serverutils.StartServer(t, base.TestServerArgs{ TimeSeriesQueryWorkerMax: workerCount, }) defer s.Stopper().Stop() tsrv := s.(*server.TestServer) seriesCount := workerCount * 2 if err := populateSeries(seriesCount, 10, tsrv.TsDB()); err != nil { t.Fatal(err) } conn, err := tsrv.RPCContext().GRPCDial(tsrv.Cfg.Addr) if err != nil { t.Fatal(err) } client := tspb.NewTimeSeriesClient(conn) queries := make([]tspb.Query, 0, seriesCount) for i := 0; i < seriesCount; i++ { queries = append(queries, tspb.Query{ Name: seriesName(i), }) } if _, err := client.Query(context.Background(), &tspb.TimeSeriesQueryRequest{ StartNanos: 0 * 1e9, EndNanos: 500 * 1e9, Queries: queries, }); err != nil { t.Fatal(err) } }
func BenchmarkServerQuery(b *testing.B) { s, _, _ := serverutils.StartServer(b, base.TestServerArgs{}) defer s.Stopper().Stop() tsrv := s.(*server.TestServer) // Populate data for large number of time series. seriesCount := 50 sourceCount := 10 if err := populateSeries(seriesCount, sourceCount, tsrv.TsDB()); err != nil { b.Fatal(err) } conn, err := tsrv.RPCContext().GRPCDial(tsrv.Cfg.Addr) if err != nil { b.Fatal(err) } client := tspb.NewTimeSeriesClient(conn) queries := make([]tspb.Query, 0, seriesCount) for i := 0; i < seriesCount; i++ { queries = append(queries, tspb.Query{ Name: fmt.Sprintf("metric.%d", i), }) } b.ResetTimer() for i := 0; i < b.N; i++ { if _, err := client.Query(context.Background(), &tspb.TimeSeriesQueryRequest{ StartNanos: 0 * 1e9, EndNanos: 500 * 1e9, Queries: queries, }); err != nil { b.Fatal(err) } } }
func TestServerQuery(t *testing.T) { defer leaktest.AfterTest(t)() s, _, _ := serverutils.StartServer(t, base.TestServerArgs{}) defer s.Stopper().Stop() tsrv := s.(*server.TestServer) // Populate data directly. tsdb := tsrv.TsDB() if err := tsdb.StoreData(context.TODO(), ts.Resolution10s, []tspb.TimeSeriesData{ { Name: "test.metric", Source: "source1", Datapoints: []tspb.TimeSeriesDatapoint{ { TimestampNanos: 400 * 1e9, Value: 100.0, }, { TimestampNanos: 500 * 1e9, Value: 200.0, }, { TimestampNanos: 520 * 1e9, Value: 300.0, }, }, }, { Name: "test.metric", Source: "source2", Datapoints: []tspb.TimeSeriesDatapoint{ { TimestampNanos: 400 * 1e9, Value: 100.0, }, { TimestampNanos: 500 * 1e9, Value: 200.0, }, { TimestampNanos: 510 * 1e9, Value: 250.0, }, { TimestampNanos: 530 * 1e9, Value: 350.0, }, }, }, { Name: "other.metric", Datapoints: []tspb.TimeSeriesDatapoint{ { TimestampNanos: 400 * 1e9, Value: 100.0, }, { TimestampNanos: 500 * 1e9, Value: 200.0, }, { TimestampNanos: 510 * 1e9, Value: 250.0, }, }, }, }); err != nil { t.Fatal(err) } expectedResult := &tspb.TimeSeriesQueryResponse{ Results: []tspb.TimeSeriesQueryResponse_Result{ { Query: tspb.Query{ Name: "test.metric", Sources: []string{"source1", "source2"}, }, Datapoints: []tspb.TimeSeriesDatapoint{ { TimestampNanos: 505 * 1e9, Value: 400.0, }, { TimestampNanos: 515 * 1e9, Value: 500.0, }, { TimestampNanos: 525 * 1e9, Value: 600.0, }, }, }, { Query: tspb.Query{ Name: "other.metric", Sources: []string{""}, }, Datapoints: []tspb.TimeSeriesDatapoint{ { TimestampNanos: 505 * 1e9, Value: 200.0, }, { TimestampNanos: 515 * 1e9, Value: 250.0, }, }, }, { Query: tspb.Query{ Name: "test.metric", Sources: []string{"source1", "source2"}, Downsampler: tspb.TimeSeriesQueryAggregator_MAX.Enum(), SourceAggregator: tspb.TimeSeriesQueryAggregator_MAX.Enum(), Derivative: tspb.TimeSeriesQueryDerivative_DERIVATIVE.Enum(), }, Datapoints: []tspb.TimeSeriesDatapoint{ { TimestampNanos: 505 * 1e9, Value: 1.0, }, { TimestampNanos: 515 * 1e9, Value: 5.0, }, { TimestampNanos: 525 * 1e9, Value: 5.0, }, }, }, }, } conn, err := tsrv.RPCContext().GRPCDial(tsrv.Cfg.Addr) if err != nil { t.Fatal(err) } client := tspb.NewTimeSeriesClient(conn) response, err := client.Query(context.Background(), &tspb.TimeSeriesQueryRequest{ StartNanos: 500 * 1e9, EndNanos: 526 * 1e9, Queries: []tspb.Query{ { Name: "test.metric", }, { Name: "other.metric", }, { Name: "test.metric", Downsampler: tspb.TimeSeriesQueryAggregator_MAX.Enum(), SourceAggregator: tspb.TimeSeriesQueryAggregator_MAX.Enum(), Derivative: tspb.TimeSeriesQueryDerivative_DERIVATIVE.Enum(), }, }, }) if err != nil { t.Fatal(err) } for _, r := range response.Results { sort.Strings(r.Sources) } if !proto.Equal(response, expectedResult) { t.Fatalf("actual response \n%v\n did not match expected response \n%v", response, expectedResult) } // Test a query with downsampling enabled. The query is a sum of maximums. expectedResult = &tspb.TimeSeriesQueryResponse{ Results: []tspb.TimeSeriesQueryResponse_Result{ { Query: tspb.Query{ Name: "test.metric", Sources: []string{"source1", "source2"}, Downsampler: tspb.TimeSeriesQueryAggregator_MAX.Enum(), }, Datapoints: []tspb.TimeSeriesDatapoint{ { TimestampNanos: 250 * 1e9, Value: 200.0, }, { TimestampNanos: 750 * 1e9, Value: 650.0, }, }, }, }, } response, err = client.Query(context.Background(), &tspb.TimeSeriesQueryRequest{ StartNanos: 0, EndNanos: 1000 * 1e9, SampleNanos: 500 * 1e9, Queries: []tspb.Query{ { Name: "test.metric", Downsampler: tspb.TimeSeriesQueryAggregator_MAX.Enum(), }, }, }) if err != nil { t.Fatal(err) } for _, r := range response.Results { sort.Strings(r.Sources) } if !proto.Equal(response, expectedResult) { t.Fatalf("actual response \n%v\n did not match expected response \n%v", response, expectedResult) } }