Commit e234cf5b by bergquist

prom: removes limitation of one query per tsdb call

parent cd92d219
...@@ -83,41 +83,48 @@ func (e *PrometheusExecutor) getClient(dsInfo *models.DataSource) (apiv1.API, er ...@@ -83,41 +83,48 @@ func (e *PrometheusExecutor) getClient(dsInfo *models.DataSource) (apiv1.API, er
} }
func (e *PrometheusExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) { func (e *PrometheusExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
result := &tsdb.Response{} result := &tsdb.Response{
Results: map[string]*tsdb.QueryResult{},
}
client, err := e.getClient(dsInfo) client, err := e.getClient(dsInfo)
if err != nil { if err != nil {
return nil, err return nil, err
} }
query, err := parseQuery(dsInfo, tsdbQuery.Queries, tsdbQuery) querys, err := parseQuery(dsInfo, tsdbQuery.Queries, tsdbQuery)
if err != nil { if err != nil {
return nil, err return nil, err
} }
timeRange := apiv1.Range{ for _, query := range querys {
Start: query.Start, timeRange := apiv1.Range{
End: query.End, Start: query.Start,
Step: query.Step, End: query.End,
} Step: query.Step,
}
span, ctx := opentracing.StartSpanFromContext(ctx, "alerting.prometheus") plog.Debug("Sending query", "start", timeRange.Start, "end", timeRange.End, "step", timeRange.Step, "query", query.Expr)
span.SetTag("expr", query.Expr)
span.SetTag("start_unixnano", int64(query.Start.UnixNano()))
span.SetTag("stop_unixnano", int64(query.End.UnixNano()))
defer span.Finish()
value, err := client.QueryRange(ctx, query.Expr, timeRange) span, ctx := opentracing.StartSpanFromContext(ctx, "alerting.prometheus")
span.SetTag("expr", query.Expr)
span.SetTag("start_unixnano", int64(query.Start.UnixNano()))
span.SetTag("stop_unixnano", int64(query.End.UnixNano()))
defer span.Finish()
if err != nil { value, err := client.QueryRange(ctx, query.Expr, timeRange)
return nil, err
}
queryResult, err := parseResponse(value, query) if err != nil {
if err != nil { return nil, err
return nil, err }
queryResult, err := parseResponse(value, query)
if err != nil {
return nil, err
}
result.Results[query.RefId] = queryResult
} }
result.Results = queryResult
return result, nil return result, nil
} }
...@@ -140,51 +147,54 @@ func formatLegend(metric model.Metric, query *PrometheusQuery) string { ...@@ -140,51 +147,54 @@ func formatLegend(metric model.Metric, query *PrometheusQuery) string {
return string(result) return string(result)
} }
func parseQuery(dsInfo *models.DataSource, queries []*tsdb.Query, queryContext *tsdb.TsdbQuery) (*PrometheusQuery, error) { func parseQuery(dsInfo *models.DataSource, queries []*tsdb.Query, queryContext *tsdb.TsdbQuery) ([]*PrometheusQuery, error) {
queryModel := queries[0] qs := []*PrometheusQuery{}
for _, queryModel := range queries {
expr, err := queryModel.Model.Get("expr").String()
if err != nil {
return nil, err
}
expr, err := queryModel.Model.Get("expr").String() format := queryModel.Model.Get("legendFormat").MustString("")
if err != nil {
return nil, err
}
format := queryModel.Model.Get("legendFormat").MustString("") start, err := queryContext.TimeRange.ParseFrom()
if err != nil {
return nil, err
}
start, err := queryContext.TimeRange.ParseFrom() end, err := queryContext.TimeRange.ParseTo()
if err != nil { if err != nil {
return nil, err return nil, err
} }
end, err := queryContext.TimeRange.ParseTo() dsInterval, err := tsdb.GetIntervalFrom(dsInfo, queryModel.Model, time.Second*15)
if err != nil { if err != nil {
return nil, err return nil, err
} }
dsInterval, err := tsdb.GetIntervalFrom(dsInfo, queryModel.Model, time.Second*15) intervalFactor := queryModel.Model.Get("intervalFactor").MustInt64(1)
if err != nil { interval := intervalCalculator.Calculate(queryContext.TimeRange, dsInterval)
return nil, err step := time.Duration(int64(interval.Value) * intervalFactor)
}
intervalFactor := queryModel.Model.Get("intervalFactor").MustInt64(1) qs = append(qs, &PrometheusQuery{
interval := intervalCalculator.Calculate(queryContext.TimeRange, dsInterval) Expr: expr,
step := time.Duration(int64(interval.Value) * intervalFactor) Step: step,
LegendFormat: format,
Start: start,
End: end,
RefId: queryModel.RefId,
})
}
return &PrometheusQuery{ return qs, nil
Expr: expr,
Step: step,
LegendFormat: format,
Start: start,
End: end,
}, nil
} }
func parseResponse(value model.Value, query *PrometheusQuery) (map[string]*tsdb.QueryResult, error) { func parseResponse(value model.Value, query *PrometheusQuery) (*tsdb.QueryResult, error) {
queryResults := make(map[string]*tsdb.QueryResult)
queryRes := tsdb.NewQueryResult() queryRes := tsdb.NewQueryResult()
data, ok := value.(model.Matrix) data, ok := value.(model.Matrix)
if !ok { if !ok {
return queryResults, fmt.Errorf("Unsupported result format: %s", value.Type().String()) return queryRes, fmt.Errorf("Unsupported result format: %s", value.Type().String())
} }
for _, v := range data { for _, v := range data {
...@@ -204,6 +214,5 @@ func parseResponse(value model.Value, query *PrometheusQuery) (map[string]*tsdb. ...@@ -204,6 +214,5 @@ func parseResponse(value model.Value, query *PrometheusQuery) (map[string]*tsdb.
queryRes.Series = append(queryRes.Series, &series) queryRes.Series = append(queryRes.Series, &series)
} }
queryResults["A"] = queryRes return queryRes, nil
return queryResults, nil
} }
...@@ -60,9 +60,10 @@ func TestPrometheus(t *testing.T) { ...@@ -60,9 +60,10 @@ func TestPrometheus(t *testing.T) {
Convey("with 48h time range", func() { Convey("with 48h time range", func() {
queryContext.TimeRange = tsdb.NewTimeRange("12h", "now") queryContext.TimeRange = tsdb.NewTimeRange("12h", "now")
model, err := parseQuery(dsInfo, queryModels, queryContext) models, err := parseQuery(dsInfo, queryModels, queryContext)
So(err, ShouldBeNil) So(err, ShouldBeNil)
model := models[0]
So(model.Step, ShouldEqual, time.Second*30) So(model.Step, ShouldEqual, time.Second*30)
}) })
}) })
...@@ -83,18 +84,22 @@ func TestPrometheus(t *testing.T) { ...@@ -83,18 +84,22 @@ func TestPrometheus(t *testing.T) {
Convey("with 48h time range", func() { Convey("with 48h time range", func() {
queryContext.TimeRange = tsdb.NewTimeRange("48h", "now") queryContext.TimeRange = tsdb.NewTimeRange("48h", "now")
model, err := parseQuery(dsInfo, queryModels, queryContext) models, err := parseQuery(dsInfo, queryModels, queryContext)
So(err, ShouldBeNil) So(err, ShouldBeNil)
model := models[0]
So(model.Step, ShouldEqual, time.Minute*2) So(model.Step, ShouldEqual, time.Minute*2)
}) })
Convey("with 1h time range", func() { Convey("with 1h time range", func() {
queryContext.TimeRange = tsdb.NewTimeRange("1h", "now") queryContext.TimeRange = tsdb.NewTimeRange("1h", "now")
model, err := parseQuery(dsInfo, queryModels, queryContext) models, err := parseQuery(dsInfo, queryModels, queryContext)
So(err, ShouldBeNil) So(err, ShouldBeNil)
model := models[0]
So(model.Step, ShouldEqual, time.Second*15) So(model.Step, ShouldEqual, time.Second*15)
}) })
}) })
...@@ -116,9 +121,11 @@ func TestPrometheus(t *testing.T) { ...@@ -116,9 +121,11 @@ func TestPrometheus(t *testing.T) {
Convey("with 48h time range", func() { Convey("with 48h time range", func() {
queryContext.TimeRange = tsdb.NewTimeRange("48h", "now") queryContext.TimeRange = tsdb.NewTimeRange("48h", "now")
model, err := parseQuery(dsInfo, queryModels, queryContext) models, err := parseQuery(dsInfo, queryModels, queryContext)
So(err, ShouldBeNil) So(err, ShouldBeNil)
model := models[0]
So(model.Step, ShouldEqual, time.Minute*20) So(model.Step, ShouldEqual, time.Minute*20)
}) })
}) })
...@@ -139,9 +146,11 @@ func TestPrometheus(t *testing.T) { ...@@ -139,9 +146,11 @@ func TestPrometheus(t *testing.T) {
Convey("with 48h time range", func() { Convey("with 48h time range", func() {
queryContext.TimeRange = tsdb.NewTimeRange("48h", "now") queryContext.TimeRange = tsdb.NewTimeRange("48h", "now")
model, err := parseQuery(dsInfo, queryModels, queryContext) models, err := parseQuery(dsInfo, queryModels, queryContext)
So(err, ShouldBeNil) So(err, ShouldBeNil)
model := models[0]
So(model.Step, ShouldEqual, time.Minute*2) So(model.Step, ShouldEqual, time.Minute*2)
}) })
}) })
......
...@@ -8,4 +8,5 @@ type PrometheusQuery struct { ...@@ -8,4 +8,5 @@ type PrometheusQuery struct {
LegendFormat string LegendFormat string
Start time.Time Start time.Time
End time.Time End time.Time
RefId string
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment