2019-11-14 03:59:41 -06:00
|
|
|
package cloudwatch
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-01-17 06:22:43 -06:00
|
|
|
"fmt"
|
2019-11-14 03:59:41 -06:00
|
|
|
|
2021-03-23 10:32:12 -05:00
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
2019-11-14 03:59:41 -06:00
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
|
|
"golang.org/x/sync/errgroup"
|
|
|
|
)
|
|
|
|
|
2021-03-23 10:32:12 -05:00
|
|
|
func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
2020-10-06 06:45:58 -05:00
|
|
|
plog.Debug("Executing time series query")
|
2020-01-17 06:22:43 -06:00
|
|
|
|
2021-03-23 10:32:12 -05:00
|
|
|
resp := backend.NewQueryDataResponse()
|
2020-05-18 05:25:58 -05:00
|
|
|
|
2021-03-23 10:32:12 -05:00
|
|
|
for _, q := range req.Queries {
|
|
|
|
startTime := q.TimeRange.From
|
|
|
|
endTime := q.TimeRange.To
|
|
|
|
if !startTime.Before(endTime) {
|
|
|
|
return nil, fmt.Errorf("invalid time range: start time must be before end time")
|
|
|
|
}
|
|
|
|
|
|
|
|
requestQueriesByRegion, err := e.parseQueries(req, startTime, endTime)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(requestQueriesByRegion) == 0 {
|
|
|
|
return backend.NewQueryDataResponse(), nil
|
|
|
|
}
|
2020-05-18 05:25:58 -05:00
|
|
|
|
2021-03-23 10:32:12 -05:00
|
|
|
resultChan := make(chan *backend.DataResponse, len(req.Queries))
|
|
|
|
eg, ectx := errgroup.WithContext(ctx)
|
|
|
|
for r, q := range requestQueriesByRegion {
|
|
|
|
requestQueries := q
|
|
|
|
region := r
|
|
|
|
eg.Go(func() error {
|
|
|
|
defer func() {
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
plog.Error("Execute Get Metric Data Query Panic", "error", err, "stack", log.Stack(1))
|
|
|
|
if theErr, ok := err.(error); ok {
|
|
|
|
resultChan <- &backend.DataResponse{
|
|
|
|
Error: theErr,
|
|
|
|
}
|
2019-11-14 03:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
2021-03-23 10:32:12 -05:00
|
|
|
}()
|
|
|
|
|
|
|
|
client, err := e.getCWClient(region, req.PluginContext)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2019-11-14 03:59:41 -06:00
|
|
|
}
|
2021-03-23 10:32:12 -05:00
|
|
|
|
|
|
|
queries, err := e.transformRequestQueriesToCloudWatchQueries(requestQueries)
|
|
|
|
if err != nil {
|
|
|
|
for _, query := range requestQueries {
|
|
|
|
resultChan <- &backend.DataResponse{
|
|
|
|
Frames: data.Frames{data.NewFrame(query.RefId)},
|
|
|
|
Error: err,
|
|
|
|
}
|
2019-11-14 03:59:41 -06:00
|
|
|
}
|
2021-03-23 10:32:12 -05:00
|
|
|
return nil
|
2019-11-14 03:59:41 -06:00
|
|
|
}
|
2021-03-23 10:32:12 -05:00
|
|
|
|
|
|
|
metricDataInput, err := e.buildMetricDataInput(startTime, endTime, queries)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
cloudwatchResponses := make([]*cloudwatchResponse, 0)
|
|
|
|
mdo, err := e.executeRequest(ectx, client, metricDataInput)
|
|
|
|
if err != nil {
|
|
|
|
for _, query := range requestQueries {
|
|
|
|
resultChan <- &backend.DataResponse{
|
|
|
|
Frames: data.Frames{data.NewFrame(query.RefId)},
|
|
|
|
Error: err,
|
|
|
|
}
|
2019-11-14 03:59:41 -06:00
|
|
|
}
|
2021-03-23 10:32:12 -05:00
|
|
|
return nil
|
2019-11-14 03:59:41 -06:00
|
|
|
}
|
2021-03-23 10:32:12 -05:00
|
|
|
|
|
|
|
responses, err := e.parseResponse(mdo, queries)
|
|
|
|
if err != nil {
|
|
|
|
for _, query := range requestQueries {
|
|
|
|
resultChan <- &backend.DataResponse{
|
|
|
|
Frames: data.Frames{data.NewFrame(query.RefId)},
|
|
|
|
Error: err,
|
|
|
|
}
|
2019-11-14 03:59:41 -06:00
|
|
|
}
|
2021-03-23 10:32:12 -05:00
|
|
|
return nil
|
2019-11-14 03:59:41 -06:00
|
|
|
}
|
2021-03-23 10:32:12 -05:00
|
|
|
|
|
|
|
cloudwatchResponses = append(cloudwatchResponses, responses...)
|
|
|
|
res, err := e.transformQueryResponsesToQueryResult(cloudwatchResponses, requestQueries, startTime, endTime)
|
|
|
|
if err != nil {
|
|
|
|
for _, query := range requestQueries {
|
|
|
|
resultChan <- &backend.DataResponse{
|
|
|
|
Frames: data.Frames{data.NewFrame(query.RefId)},
|
|
|
|
Error: err,
|
|
|
|
}
|
2021-01-13 08:30:09 -06:00
|
|
|
}
|
2021-03-23 10:32:12 -05:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, queryRes := range res {
|
|
|
|
resultChan <- queryRes
|
2021-01-13 08:30:09 -06:00
|
|
|
}
|
|
|
|
return nil
|
2021-03-23 10:32:12 -05:00
|
|
|
})
|
|
|
|
}
|
2021-01-13 08:30:09 -06:00
|
|
|
|
2021-03-23 10:32:12 -05:00
|
|
|
if err := eg.Wait(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
close(resultChan)
|
2020-05-18 05:25:58 -05:00
|
|
|
|
2021-03-23 10:32:12 -05:00
|
|
|
for result := range resultChan {
|
|
|
|
resp.Responses[q.RefID] = *result
|
|
|
|
}
|
2019-11-14 03:59:41 -06:00
|
|
|
}
|
2021-03-23 10:32:12 -05:00
|
|
|
|
|
|
|
return resp, nil
|
2019-11-14 03:59:41 -06:00
|
|
|
}
|