Introduce TSDB service (#31520)
* Introduce TSDB service Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> Co-authored-by: Erik Sundell <erik.sundell87@gmail.com> Co-authored-by: Will Browne <will.browne@grafana.com> Co-authored-by: Torkel Ödegaard <torkel@grafana.org> Co-authored-by: Will Browne <wbrowne@users.noreply.github.com> Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>
This commit is contained in:
co-authored by
Erik Sundell
Will Browne
Torkel Ödegaard
Will Browne
Zoltán Bedi
parent
c899bf3592
commit
b79e61656a
@@ -8,16 +8,17 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatch"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
)
|
||||
|
||||
func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryContext *tsdb.TsdbQuery) (*tsdb.Response, error) {
|
||||
result := &tsdb.Response{
|
||||
Results: make(map[string]*tsdb.QueryResult),
|
||||
func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryContext plugins.DataQuery) (
|
||||
plugins.DataResponse, error) {
|
||||
result := plugins.DataResponse{
|
||||
Results: make(map[string]plugins.DataQueryResult),
|
||||
}
|
||||
firstQuery := queryContext.Queries[0]
|
||||
queryResult := &tsdb.QueryResult{Meta: simplejson.New(), RefId: firstQuery.RefId}
|
||||
queryResult := plugins.DataQueryResult{Meta: simplejson.New(), RefID: firstQuery.RefID}
|
||||
|
||||
parameters := firstQuery.Model
|
||||
usePrefixMatch := parameters.Get("prefixMatching").MustBool(false)
|
||||
@@ -27,7 +28,7 @@ func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryCo
|
||||
dimensions := parameters.Get("dimensions").MustMap()
|
||||
statistics, err := parseStatistics(parameters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
period := int64(parameters.Get("period").MustInt(0))
|
||||
if period == 0 && !usePrefixMatch {
|
||||
@@ -38,7 +39,7 @@ func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryCo
|
||||
|
||||
cli, err := e.getCWClient(region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
|
||||
var alarmNames []*string
|
||||
@@ -50,7 +51,7 @@ func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryCo
|
||||
}
|
||||
resp, err := cli.DescribeAlarms(params)
|
||||
if err != nil {
|
||||
return nil, errutil.Wrap("failed to call cloudwatch:DescribeAlarms", err)
|
||||
return plugins.DataResponse{}, errutil.Wrap("failed to call cloudwatch:DescribeAlarms", err)
|
||||
}
|
||||
alarmNames = filterAlarms(resp, namespace, metricName, dimensions, statistics, period)
|
||||
} else {
|
||||
@@ -81,7 +82,7 @@ func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryCo
|
||||
}
|
||||
resp, err := cli.DescribeAlarmsForMetric(params)
|
||||
if err != nil {
|
||||
return nil, errutil.Wrap("failed to call cloudwatch:DescribeAlarmsForMetric", err)
|
||||
return plugins.DataResponse{}, errutil.Wrap("failed to call cloudwatch:DescribeAlarmsForMetric", err)
|
||||
}
|
||||
for _, alarm := range resp.MetricAlarms {
|
||||
alarmNames = append(alarmNames, alarm.AlarmName)
|
||||
@@ -91,11 +92,11 @@ func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryCo
|
||||
|
||||
startTime, err := queryContext.TimeRange.ParseFrom()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
endTime, err := queryContext.TimeRange.ParseTo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
|
||||
annotations := make([]map[string]string, 0)
|
||||
@@ -108,7 +109,7 @@ func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryCo
|
||||
}
|
||||
resp, err := cli.DescribeAlarmHistory(params)
|
||||
if err != nil {
|
||||
return nil, errutil.Wrap("failed to call cloudwatch:DescribeAlarmHistory", err)
|
||||
return plugins.DataResponse{}, errutil.Wrap("failed to call cloudwatch:DescribeAlarmHistory", err)
|
||||
}
|
||||
for _, history := range resp.AlarmHistoryItems {
|
||||
annotation := make(map[string]string)
|
||||
@@ -120,15 +121,15 @@ func (e *cloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryCo
|
||||
}
|
||||
}
|
||||
|
||||
transformAnnotationToTable(annotations, queryResult)
|
||||
result.Results[firstQuery.RefId] = queryResult
|
||||
return result, err
|
||||
transformAnnotationToTable(annotations, &queryResult)
|
||||
result.Results[firstQuery.RefID] = queryResult
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func transformAnnotationToTable(data []map[string]string, result *tsdb.QueryResult) {
|
||||
table := &tsdb.Table{
|
||||
Columns: make([]tsdb.TableColumn, 4),
|
||||
Rows: make([]tsdb.RowValues, 0),
|
||||
func transformAnnotationToTable(data []map[string]string, result *plugins.DataQueryResult) {
|
||||
table := plugins.DataTable{
|
||||
Columns: make([]plugins.DataTableColumn, 4),
|
||||
Rows: make([]plugins.DataRowValues, 0),
|
||||
}
|
||||
table.Columns[0].Text = "time"
|
||||
table.Columns[1].Text = "title"
|
||||
@@ -147,7 +148,8 @@ func transformAnnotationToTable(data []map[string]string, result *tsdb.QueryResu
|
||||
result.Meta.Set("rowCount", len(data))
|
||||
}
|
||||
|
||||
func filterAlarms(alarms *cloudwatch.DescribeAlarmsOutput, namespace string, metricName string, dimensions map[string]interface{}, statistics []string, period int64) []*string {
|
||||
func filterAlarms(alarms *cloudwatch.DescribeAlarmsOutput, namespace string, metricName string,
|
||||
dimensions map[string]interface{}, statistics []string, period int64) []*string {
|
||||
alarmNames := make([]*string, 0)
|
||||
|
||||
for _, alarm := range alarms.MetricAlarms {
|
||||
|
||||
@@ -26,9 +26,9 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
)
|
||||
|
||||
type datasourceInfo struct {
|
||||
@@ -67,15 +67,13 @@ type CloudWatchService struct {
|
||||
}
|
||||
|
||||
func (s *CloudWatchService) Init() error {
|
||||
plog.Debug("initing")
|
||||
|
||||
tsdb.RegisterTsdbQueryEndpoint("cloudwatch", func(ds *models.DataSource) (tsdb.TsdbQueryEndpoint, error) {
|
||||
return newExecutor(s.LogsService), nil
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *CloudWatchService) NewExecutor(*models.DataSource) (plugins.DataPlugin, error) {
|
||||
return newExecutor(s.LogsService), nil
|
||||
}
|
||||
|
||||
func newExecutor(logsService *LogsService) *cloudWatchExecutor {
|
||||
return &cloudWatchExecutor{
|
||||
logsService: logsService,
|
||||
@@ -248,12 +246,12 @@ func (e *cloudWatchExecutor) getRGTAClient(region string) (resourcegroupstagging
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) alertQuery(ctx context.Context, logsClient cloudwatchlogsiface.CloudWatchLogsAPI,
|
||||
queryContext *tsdb.TsdbQuery) (*cloudwatchlogs.GetQueryResultsOutput, error) {
|
||||
queryContext plugins.DataQuery) (*cloudwatchlogs.GetQueryResultsOutput, error) {
|
||||
const maxAttempts = 8
|
||||
const pollPeriod = 1000 * time.Millisecond
|
||||
|
||||
queryParams := queryContext.Queries[0].Model
|
||||
startQueryOutput, err := e.executeStartQuery(ctx, logsClient, queryParams, queryContext.TimeRange)
|
||||
startQueryOutput, err := e.executeStartQuery(ctx, logsClient, queryParams, *queryContext.TimeRange)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -285,15 +283,17 @@ func (e *cloudWatchExecutor) alertQuery(ctx context.Context, logsClient cloudwat
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Query executes a CloudWatch query.
|
||||
func (e *cloudWatchExecutor) Query(ctx context.Context, dsInfo *models.DataSource, queryContext *tsdb.TsdbQuery) (*tsdb.Response, error) {
|
||||
// DataQuery executes a CloudWatch query.
|
||||
func (e *cloudWatchExecutor) DataQuery(ctx context.Context, dsInfo *models.DataSource,
|
||||
queryContext plugins.DataQuery) (plugins.DataResponse, error) {
|
||||
e.DataSource = dsInfo
|
||||
|
||||
/*
|
||||
Unlike many other data sources, with Cloudwatch Logs query requests don't receive the results as the response to the query, but rather
|
||||
an ID is first returned. Following this, a client is expected to send requests along with the ID until the status of the query is complete,
|
||||
receiving (possibly partial) results each time. For queries made via dashboards and Explore, the logic of making these repeated queries is handled on
|
||||
the frontend, but because alerts are executed on the backend the logic needs to be reimplemented here.
|
||||
Unlike many other data sources, with Cloudwatch Logs query requests don't receive the results as the response
|
||||
to the query, but rather an ID is first returned. Following this, a client is expected to send requests along
|
||||
with the ID until the status of the query is complete, receiving (possibly partial) results each time. For
|
||||
queries made via dashboards and Explore, the logic of making these repeated queries is handled on the
|
||||
frontend, but because alerts are executed on the backend the logic needs to be reimplemented here.
|
||||
*/
|
||||
queryParams := queryContext.Queries[0].Model
|
||||
_, fromAlert := queryContext.Headers["FromAlert"]
|
||||
@@ -306,7 +306,7 @@ func (e *cloudWatchExecutor) Query(ctx context.Context, dsInfo *models.DataSourc
|
||||
queryType := queryParams.Get("type").MustString("")
|
||||
|
||||
var err error
|
||||
var result *tsdb.Response
|
||||
var result plugins.DataResponse
|
||||
switch queryType {
|
||||
case "metricFindQuery":
|
||||
result, err = e.executeMetricFindQuery(ctx, queryContext)
|
||||
@@ -325,7 +325,8 @@ func (e *cloudWatchExecutor) Query(ctx context.Context, dsInfo *models.DataSourc
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) executeLogAlertQuery(ctx context.Context, queryContext *tsdb.TsdbQuery) (*tsdb.Response, error) {
|
||||
func (e *cloudWatchExecutor) executeLogAlertQuery(ctx context.Context, queryContext plugins.DataQuery) (
|
||||
plugins.DataResponse, error) {
|
||||
queryParams := queryContext.Queries[0].Model
|
||||
queryParams.Set("subtype", "StartQuery")
|
||||
queryParams.Set("queryString", queryParams.Get("expression").MustString(""))
|
||||
@@ -338,12 +339,12 @@ func (e *cloudWatchExecutor) executeLogAlertQuery(ctx context.Context, queryCont
|
||||
|
||||
logsClient, err := e.getCWLogsClient(region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
|
||||
result, err := e.executeStartQuery(ctx, logsClient, queryParams, queryContext.TimeRange)
|
||||
result, err := e.executeStartQuery(ctx, logsClient, queryParams, *queryContext.TimeRange)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
|
||||
queryParams.Set("queryId", *result.QueryId)
|
||||
@@ -351,38 +352,38 @@ func (e *cloudWatchExecutor) executeLogAlertQuery(ctx context.Context, queryCont
|
||||
// Get query results
|
||||
getQueryResultsOutput, err := e.alertQuery(ctx, logsClient, queryContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
|
||||
dataframe, err := logsResultsToDataframes(getQueryResultsOutput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
|
||||
statsGroups := queryParams.Get("statsGroups").MustStringArray()
|
||||
if len(statsGroups) > 0 && len(dataframe.Fields) > 0 {
|
||||
groupedFrames, err := groupResults(dataframe, statsGroups)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
|
||||
response := &tsdb.Response{
|
||||
Results: make(map[string]*tsdb.QueryResult),
|
||||
response := plugins.DataResponse{
|
||||
Results: make(map[string]plugins.DataQueryResult),
|
||||
}
|
||||
|
||||
response.Results["A"] = &tsdb.QueryResult{
|
||||
RefId: "A",
|
||||
Dataframes: tsdb.NewDecodedDataFrames(groupedFrames),
|
||||
response.Results["A"] = plugins.DataQueryResult{
|
||||
RefID: "A",
|
||||
Dataframes: plugins.NewDecodedDataFrames(groupedFrames),
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
response := &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
response := plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
"A": {
|
||||
RefId: "A",
|
||||
Dataframes: tsdb.NewDecodedDataFrames(data.Frames{dataframe}),
|
||||
RefID: "A",
|
||||
Dataframes: plugins.NewDecodedDataFrames(data.Frames{dataframe}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
+22
-18
@@ -18,8 +18,8 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/util/retryer"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
@@ -108,20 +108,21 @@ func (r *logQueryRunner) publishResults(channelName string) error {
|
||||
|
||||
// executeLiveLogQuery executes a CloudWatch Logs query with live updates over WebSocket.
|
||||
// A WebSocket channel is created, which goroutines send responses over.
|
||||
func (e *cloudWatchExecutor) executeLiveLogQuery(ctx context.Context, queryContext *tsdb.TsdbQuery) (*tsdb.Response, error) {
|
||||
func (e *cloudWatchExecutor) executeLiveLogQuery(ctx context.Context, queryContext plugins.DataQuery) (
|
||||
plugins.DataResponse, error) {
|
||||
responseChannelName := uuid.New().String()
|
||||
responseChannel := make(chan *tsdb.Response)
|
||||
responseChannel := make(chan plugins.DataResponse)
|
||||
if err := e.logsService.AddResponseChannel("plugin/cloudwatch/"+responseChannelName, responseChannel); err != nil {
|
||||
close(responseChannel)
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
|
||||
go e.sendLiveQueriesToChannel(queryContext, responseChannel)
|
||||
|
||||
response := &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
response := plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
"A": {
|
||||
RefId: "A",
|
||||
RefID: "A",
|
||||
Meta: simplejson.NewFromAny(map[string]interface{}{
|
||||
"channelName": responseChannelName,
|
||||
}),
|
||||
@@ -132,7 +133,8 @@ func (e *cloudWatchExecutor) executeLiveLogQuery(ctx context.Context, queryConte
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) sendLiveQueriesToChannel(queryContext *tsdb.TsdbQuery, responseChannel chan *tsdb.Response) {
|
||||
func (e *cloudWatchExecutor) sendLiveQueriesToChannel(queryContext plugins.DataQuery,
|
||||
responseChannel chan plugins.DataResponse) {
|
||||
defer close(responseChannel)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
|
||||
@@ -142,7 +144,7 @@ func (e *cloudWatchExecutor) sendLiveQueriesToChannel(queryContext *tsdb.TsdbQue
|
||||
for _, query := range queryContext.Queries {
|
||||
query := query
|
||||
eg.Go(func() error {
|
||||
return e.startLiveQuery(ectx, responseChannel, query, queryContext.TimeRange)
|
||||
return e.startLiveQuery(ectx, responseChannel, query, *queryContext.TimeRange)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -200,7 +202,8 @@ func (e *cloudWatchExecutor) fetchConcurrentQueriesQuota(region string) int {
|
||||
return defaultConcurrentQueries
|
||||
}
|
||||
|
||||
if defaultConcurrentQueriesQuota != nil && defaultConcurrentQueriesQuota.Quota != nil && defaultConcurrentQueriesQuota.Quota.Value != nil {
|
||||
if defaultConcurrentQueriesQuota != nil && defaultConcurrentQueriesQuota.Quota != nil &&
|
||||
defaultConcurrentQueriesQuota.Quota.Value != nil {
|
||||
return int(*defaultConcurrentQueriesQuota.Quota.Value)
|
||||
}
|
||||
|
||||
@@ -208,7 +211,8 @@ func (e *cloudWatchExecutor) fetchConcurrentQueriesQuota(region string) int {
|
||||
return defaultConcurrentQueries
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) startLiveQuery(ctx context.Context, responseChannel chan *tsdb.Response, query *tsdb.Query, timeRange *tsdb.TimeRange) error {
|
||||
func (e *cloudWatchExecutor) startLiveQuery(ctx context.Context, responseChannel chan plugins.DataResponse,
|
||||
query plugins.DataSubQuery, timeRange plugins.DataTimeRange) error {
|
||||
defaultRegion := e.DataSource.JsonData.Get("defaultRegion").MustString()
|
||||
parameters := query.Model
|
||||
region := parameters.Get("region").MustString(defaultRegion)
|
||||
@@ -250,8 +254,8 @@ func (e *cloudWatchExecutor) startLiveQuery(ctx context.Context, responseChannel
|
||||
return retryer.FuncError, err
|
||||
}
|
||||
|
||||
dataFrame.Name = query.RefId
|
||||
dataFrame.RefID = query.RefId
|
||||
dataFrame.Name = query.RefID
|
||||
dataFrame.RefID = query.RefID
|
||||
var dataFrames data.Frames
|
||||
|
||||
// When a query of the form "stats ... by ..." is made, we want to return
|
||||
@@ -281,11 +285,11 @@ func (e *cloudWatchExecutor) startLiveQuery(ctx context.Context, responseChannel
|
||||
dataFrames = data.Frames{dataFrame}
|
||||
}
|
||||
|
||||
responseChannel <- &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
query.RefId: {
|
||||
RefId: query.RefId,
|
||||
Dataframes: tsdb.NewDecodedDataFrames(dataFrames),
|
||||
responseChannel <- plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
query.RefID: {
|
||||
RefID: query.RefID,
|
||||
Dataframes: plugins.NewDecodedDataFrames(dataFrames),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -12,12 +12,13 @@ import (
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func (e *cloudWatchExecutor) executeLogActions(ctx context.Context, queryContext *tsdb.TsdbQuery) (*tsdb.Response, error) {
|
||||
resultChan := make(chan *tsdb.QueryResult, len(queryContext.Queries))
|
||||
func (e *cloudWatchExecutor) executeLogActions(ctx context.Context,
|
||||
queryContext plugins.DataQuery) (plugins.DataResponse, error) {
|
||||
resultChan := make(chan plugins.DataQueryResult, len(queryContext.Queries))
|
||||
eg, ectx := errgroup.WithContext(ctx)
|
||||
|
||||
for _, query := range queryContext.Queries {
|
||||
@@ -42,7 +43,10 @@ func (e *cloudWatchExecutor) executeLogActions(ctx context.Context, queryContext
|
||||
return err
|
||||
}
|
||||
|
||||
resultChan <- &tsdb.QueryResult{RefId: query.RefId, Dataframes: tsdb.NewDecodedDataFrames(groupedFrames)}
|
||||
resultChan <- plugins.DataQueryResult{
|
||||
RefID: query.RefID,
|
||||
Dataframes: plugins.NewDecodedDataFrames(groupedFrames),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -54,30 +58,31 @@ func (e *cloudWatchExecutor) executeLogActions(ctx context.Context, queryContext
|
||||
}
|
||||
}
|
||||
|
||||
resultChan <- &tsdb.QueryResult{
|
||||
RefId: query.RefId,
|
||||
Dataframes: tsdb.NewDecodedDataFrames(data.Frames{dataframe}),
|
||||
resultChan <- plugins.DataQueryResult{
|
||||
RefID: query.RefID,
|
||||
Dataframes: plugins.NewDecodedDataFrames(data.Frames{dataframe}),
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := eg.Wait(); err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
|
||||
close(resultChan)
|
||||
|
||||
response := &tsdb.Response{
|
||||
Results: make(map[string]*tsdb.QueryResult),
|
||||
response := plugins.DataResponse{
|
||||
Results: make(map[string]plugins.DataQueryResult),
|
||||
}
|
||||
for result := range resultChan {
|
||||
response.Results[result.RefId] = result
|
||||
response.Results[result.RefID] = result
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) executeLogAction(ctx context.Context, queryContext *tsdb.TsdbQuery, query *tsdb.Query) (*data.Frame, error) {
|
||||
func (e *cloudWatchExecutor) executeLogAction(ctx context.Context, queryContext plugins.DataQuery,
|
||||
query plugins.DataSubQuery) (*data.Frame, error) {
|
||||
parameters := query.Model
|
||||
subType := query.Model.Get("subtype").MustString()
|
||||
|
||||
@@ -94,13 +99,13 @@ func (e *cloudWatchExecutor) executeLogAction(ctx context.Context, queryContext
|
||||
case "DescribeLogGroups":
|
||||
data, err = e.handleDescribeLogGroups(ctx, logsClient, parameters)
|
||||
case "GetLogGroupFields":
|
||||
data, err = e.handleGetLogGroupFields(ctx, logsClient, parameters, query.RefId)
|
||||
data, err = e.handleGetLogGroupFields(ctx, logsClient, parameters, query.RefID)
|
||||
case "StartQuery":
|
||||
data, err = e.handleStartQuery(ctx, logsClient, parameters, queryContext.TimeRange, query.RefId)
|
||||
data, err = e.handleStartQuery(ctx, logsClient, parameters, *queryContext.TimeRange, query.RefID)
|
||||
case "StopQuery":
|
||||
data, err = e.handleStopQuery(ctx, logsClient, parameters)
|
||||
case "GetQueryResults":
|
||||
data, err = e.handleGetQueryResults(ctx, logsClient, parameters, query.RefId)
|
||||
data, err = e.handleGetQueryResults(ctx, logsClient, parameters, query.RefID)
|
||||
case "GetLogEvents":
|
||||
data, err = e.handleGetLogEvents(ctx, logsClient, parameters)
|
||||
}
|
||||
@@ -195,7 +200,7 @@ func (e *cloudWatchExecutor) handleDescribeLogGroups(ctx context.Context,
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) executeStartQuery(ctx context.Context, logsClient cloudwatchlogsiface.CloudWatchLogsAPI,
|
||||
parameters *simplejson.Json, timeRange *tsdb.TimeRange) (*cloudwatchlogs.StartQueryOutput, error) {
|
||||
parameters *simplejson.Json, timeRange plugins.DataTimeRange) (*cloudwatchlogs.StartQueryOutput, error) {
|
||||
startTime, err := timeRange.ParseFrom()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -214,7 +219,8 @@ func (e *cloudWatchExecutor) executeStartQuery(ctx context.Context, logsClient c
|
||||
// so that a row's context can be retrieved later if necessary.
|
||||
// The usage of ltrim around the @log/@logStream fields is a necessary workaround, as without it,
|
||||
// CloudWatch wouldn't consider a query using a non-alised @log/@logStream valid.
|
||||
modifiedQueryString := "fields @timestamp,ltrim(@log) as " + logIdentifierInternal + ",ltrim(@logStream) as " + logStreamIdentifierInternal + "|" + parameters.Get("queryString").MustString("")
|
||||
modifiedQueryString := "fields @timestamp,ltrim(@log) as " + logIdentifierInternal + ",ltrim(@logStream) as " +
|
||||
logStreamIdentifierInternal + "|" + parameters.Get("queryString").MustString("")
|
||||
|
||||
startQueryInput := &cloudwatchlogs.StartQueryInput{
|
||||
StartTime: aws.Int64(startTime.Unix()),
|
||||
@@ -231,7 +237,7 @@ func (e *cloudWatchExecutor) executeStartQuery(ctx context.Context, logsClient c
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) handleStartQuery(ctx context.Context, logsClient cloudwatchlogsiface.CloudWatchLogsAPI,
|
||||
parameters *simplejson.Json, timeRange *tsdb.TimeRange, refID string) (*data.Frame, error) {
|
||||
parameters *simplejson.Json, timeRange plugins.DataTimeRange, refID string) (*data.Frame, error) {
|
||||
startQueryResponse, err := e.executeStartQuery(ctx, logsClient, parameters, timeRange)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -48,8 +48,8 @@ func TestQuery_DescribeLogGroups(t *testing.T) {
|
||||
}
|
||||
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "logAction",
|
||||
@@ -62,10 +62,10 @@ func TestQuery_DescribeLogGroups(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
"": {
|
||||
Dataframes: tsdb.NewDecodedDataFrames(data.Frames{
|
||||
Dataframes: plugins.NewDecodedDataFrames(data.Frames{
|
||||
&data.Frame{
|
||||
Name: "logGroups",
|
||||
Fields: []*data.Field{
|
||||
@@ -101,8 +101,8 @@ func TestQuery_DescribeLogGroups(t *testing.T) {
|
||||
}
|
||||
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "logAction",
|
||||
@@ -115,10 +115,10 @@ func TestQuery_DescribeLogGroups(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
"": {
|
||||
Dataframes: tsdb.NewDecodedDataFrames(data.Frames{
|
||||
Dataframes: plugins.NewDecodedDataFrames(data.Frames{
|
||||
&data.Frame{
|
||||
Name: "logGroups",
|
||||
Fields: []*data.Field{
|
||||
@@ -171,10 +171,10 @@ func TestQuery_GetLogGroupFields(t *testing.T) {
|
||||
const refID = "A"
|
||||
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
RefId: refID,
|
||||
RefID: refID,
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "logAction",
|
||||
"subtype": "GetLogGroupFields",
|
||||
@@ -202,11 +202,11 @@ func TestQuery_GetLogGroupFields(t *testing.T) {
|
||||
},
|
||||
}
|
||||
expFrame.RefID = refID
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
refID: {
|
||||
Dataframes: tsdb.NewDecodedDataFrames(data.Frames{expFrame}),
|
||||
RefId: refID,
|
||||
Dataframes: plugins.NewDecodedDataFrames(data.Frames{expFrame}),
|
||||
RefID: refID,
|
||||
},
|
||||
},
|
||||
}, resp)
|
||||
@@ -244,15 +244,15 @@ func TestQuery_StartQuery(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
timeRange := &tsdb.TimeRange{
|
||||
timeRange := plugins.DataTimeRange{
|
||||
From: "1584873443000",
|
||||
To: "1584700643000",
|
||||
}
|
||||
|
||||
executor := newExecutor(nil)
|
||||
_, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
TimeRange: timeRange,
|
||||
Queries: []*tsdb.Query{
|
||||
_, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
TimeRange: &timeRange,
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "logAction",
|
||||
@@ -290,17 +290,17 @@ func TestQuery_StartQuery(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
timeRange := &tsdb.TimeRange{
|
||||
timeRange := plugins.DataTimeRange{
|
||||
From: "1584700643000",
|
||||
To: "1584873443000",
|
||||
}
|
||||
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
TimeRange: timeRange,
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
TimeRange: &timeRange,
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
RefId: refID,
|
||||
RefID: refID,
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "logAction",
|
||||
"subtype": "StartQuery",
|
||||
@@ -324,11 +324,11 @@ func TestQuery_StartQuery(t *testing.T) {
|
||||
},
|
||||
PreferredVisualization: "logs",
|
||||
}
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
refID: {
|
||||
Dataframes: tsdb.NewDecodedDataFrames(data.Frames{expFrame}),
|
||||
RefId: refID,
|
||||
Dataframes: plugins.NewDecodedDataFrames(data.Frames{expFrame}),
|
||||
RefID: refID,
|
||||
},
|
||||
},
|
||||
}, resp)
|
||||
@@ -366,15 +366,15 @@ func TestQuery_StopQuery(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
timeRange := &tsdb.TimeRange{
|
||||
timeRange := plugins.DataTimeRange{
|
||||
From: "1584873443000",
|
||||
To: "1584700643000",
|
||||
}
|
||||
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
TimeRange: timeRange,
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
TimeRange: &timeRange,
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "logAction",
|
||||
@@ -395,10 +395,10 @@ func TestQuery_StopQuery(t *testing.T) {
|
||||
PreferredVisualization: "logs",
|
||||
},
|
||||
}
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
"": {
|
||||
Dataframes: tsdb.NewDecodedDataFrames(data.Frames{expFrame}),
|
||||
Dataframes: plugins.NewDecodedDataFrames(data.Frames{expFrame}),
|
||||
},
|
||||
},
|
||||
}, resp)
|
||||
@@ -459,10 +459,10 @@ func TestQuery_GetQueryResults(t *testing.T) {
|
||||
}
|
||||
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
RefId: refID,
|
||||
RefID: refID,
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "logAction",
|
||||
"subtype": "GetQueryResults",
|
||||
@@ -507,11 +507,11 @@ func TestQuery_GetQueryResults(t *testing.T) {
|
||||
PreferredVisualization: "logs",
|
||||
}
|
||||
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
refID: {
|
||||
RefId: refID,
|
||||
Dataframes: tsdb.NewDecodedDataFrames(data.Frames{expFrame}),
|
||||
RefID: refID,
|
||||
Dataframes: plugins.NewDecodedDataFrames(data.Frames{expFrame}),
|
||||
},
|
||||
},
|
||||
}, resp)
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -15,19 +15,19 @@ func init() {
|
||||
// LogsService provides methods for querying CloudWatch Logs.
|
||||
type LogsService struct {
|
||||
channelMu sync.Mutex
|
||||
responseChannels map[string]chan *tsdb.Response
|
||||
responseChannels map[string]chan plugins.DataResponse
|
||||
queues map[string](chan bool)
|
||||
queueLock sync.Mutex
|
||||
}
|
||||
|
||||
// Init is called by the DI framework to initialize the instance.
|
||||
func (s *LogsService) Init() error {
|
||||
s.responseChannels = make(map[string]chan *tsdb.Response)
|
||||
s.responseChannels = make(map[string]chan plugins.DataResponse)
|
||||
s.queues = make(map[string](chan bool))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *LogsService) AddResponseChannel(name string, channel chan *tsdb.Response) error {
|
||||
func (s *LogsService) AddResponseChannel(name string, channel chan plugins.DataResponse) error {
|
||||
s.channelMu.Lock()
|
||||
defer s.channelMu.Unlock()
|
||||
|
||||
@@ -39,7 +39,7 @@ func (s *LogsService) AddResponseChannel(name string, channel chan *tsdb.Respons
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *LogsService) GetResponseChannel(name string) (chan *tsdb.Response, error) {
|
||||
func (s *LogsService) GetResponseChannel(name string) (chan plugins.DataResponse, error) {
|
||||
s.channelMu.Lock()
|
||||
defer s.channelMu.Unlock()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
)
|
||||
|
||||
@@ -241,7 +241,8 @@ var dimensionsMap = map[string][]string{
|
||||
|
||||
var regionCache sync.Map
|
||||
|
||||
func (e *cloudWatchExecutor) executeMetricFindQuery(ctx context.Context, queryContext *tsdb.TsdbQuery) (*tsdb.Response, error) {
|
||||
func (e *cloudWatchExecutor) executeMetricFindQuery(ctx context.Context, queryContext plugins.DataQuery) (
|
||||
plugins.DataResponse, error) {
|
||||
firstQuery := queryContext.Queries[0]
|
||||
|
||||
parameters := firstQuery.Model
|
||||
@@ -267,22 +268,22 @@ func (e *cloudWatchExecutor) executeMetricFindQuery(ctx context.Context, queryCo
|
||||
data, err = e.handleGetResourceArns(ctx, parameters, queryContext)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
|
||||
queryResult := &tsdb.QueryResult{Meta: simplejson.New(), RefId: firstQuery.RefId}
|
||||
transformToTable(data, queryResult)
|
||||
result := &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
firstQuery.RefId: queryResult,
|
||||
queryResult := plugins.DataQueryResult{Meta: simplejson.New(), RefID: firstQuery.RefID}
|
||||
transformToTable(data, &queryResult)
|
||||
result := plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
firstQuery.RefID: queryResult,
|
||||
},
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func transformToTable(data []suggestData, result *tsdb.QueryResult) {
|
||||
table := &tsdb.Table{
|
||||
Columns: []tsdb.TableColumn{
|
||||
func transformToTable(data []suggestData, result *plugins.DataQueryResult) {
|
||||
table := plugins.DataTable{
|
||||
Columns: []plugins.DataTableColumn{
|
||||
{
|
||||
Text: "text",
|
||||
},
|
||||
@@ -290,7 +291,7 @@ func transformToTable(data []suggestData, result *tsdb.QueryResult) {
|
||||
Text: "value",
|
||||
},
|
||||
},
|
||||
Rows: make([]tsdb.RowValues, 0),
|
||||
Rows: make([]plugins.DataRowValues, 0),
|
||||
}
|
||||
|
||||
for _, r := range data {
|
||||
@@ -321,7 +322,7 @@ func parseMultiSelectValue(input string) []string {
|
||||
// Whenever this list is updated, the frontend list should also be updated.
|
||||
// Please update the region list in public/app/plugins/datasource/cloudwatch/partials/config.html
|
||||
func (e *cloudWatchExecutor) handleGetRegions(ctx context.Context, parameters *simplejson.Json,
|
||||
queryContext *tsdb.TsdbQuery) ([]suggestData, error) {
|
||||
queryContext plugins.DataQuery) ([]suggestData, error) {
|
||||
dsInfo := e.getDSInfo(defaultRegion)
|
||||
profile := dsInfo.Profile
|
||||
if cache, ok := regionCache.Load(profile); ok {
|
||||
@@ -366,7 +367,7 @@ func (e *cloudWatchExecutor) handleGetRegions(ctx context.Context, parameters *s
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) handleGetNamespaces(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) {
|
||||
func (e *cloudWatchExecutor) handleGetNamespaces(ctx context.Context, parameters *simplejson.Json, queryContext plugins.DataQuery) ([]suggestData, error) {
|
||||
keys := []string{}
|
||||
for key := range metricsMap {
|
||||
keys = append(keys, key)
|
||||
@@ -385,7 +386,7 @@ func (e *cloudWatchExecutor) handleGetNamespaces(ctx context.Context, parameters
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) handleGetMetrics(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) {
|
||||
func (e *cloudWatchExecutor) handleGetMetrics(ctx context.Context, parameters *simplejson.Json, queryContext plugins.DataQuery) ([]suggestData, error) {
|
||||
region := parameters.Get("region").MustString()
|
||||
namespace := parameters.Get("namespace").MustString()
|
||||
|
||||
@@ -411,7 +412,7 @@ func (e *cloudWatchExecutor) handleGetMetrics(ctx context.Context, parameters *s
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) handleGetDimensions(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) {
|
||||
func (e *cloudWatchExecutor) handleGetDimensions(ctx context.Context, parameters *simplejson.Json, queryContext plugins.DataQuery) ([]suggestData, error) {
|
||||
region := parameters.Get("region").MustString()
|
||||
namespace := parameters.Get("namespace").MustString()
|
||||
|
||||
@@ -437,7 +438,7 @@ func (e *cloudWatchExecutor) handleGetDimensions(ctx context.Context, parameters
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) handleGetDimensionValues(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) {
|
||||
func (e *cloudWatchExecutor) handleGetDimensionValues(ctx context.Context, parameters *simplejson.Json, queryContext plugins.DataQuery) ([]suggestData, error) {
|
||||
region := parameters.Get("region").MustString()
|
||||
namespace := parameters.Get("namespace").MustString()
|
||||
metricName := parameters.Get("metricName").MustString()
|
||||
@@ -489,7 +490,7 @@ func (e *cloudWatchExecutor) handleGetDimensionValues(ctx context.Context, param
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) handleGetEbsVolumeIds(ctx context.Context, parameters *simplejson.Json,
|
||||
queryContext *tsdb.TsdbQuery) ([]suggestData, error) {
|
||||
queryContext plugins.DataQuery) ([]suggestData, error) {
|
||||
region := parameters.Get("region").MustString()
|
||||
instanceId := parameters.Get("instanceId").MustString()
|
||||
|
||||
@@ -512,7 +513,7 @@ func (e *cloudWatchExecutor) handleGetEbsVolumeIds(ctx context.Context, paramete
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context, parameters *simplejson.Json,
|
||||
queryContext *tsdb.TsdbQuery) ([]suggestData, error) {
|
||||
queryContext plugins.DataQuery) ([]suggestData, error) {
|
||||
region := parameters.Get("region").MustString()
|
||||
attributeName := parameters.Get("attributeName").MustString()
|
||||
filterJson := parameters.Get("filters").MustMap()
|
||||
@@ -592,7 +593,7 @@ func (e *cloudWatchExecutor) handleGetEc2InstanceAttribute(ctx context.Context,
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) handleGetResourceArns(ctx context.Context, parameters *simplejson.Json,
|
||||
queryContext *tsdb.TsdbQuery) ([]suggestData, error) {
|
||||
queryContext plugins.DataQuery) ([]suggestData, error) {
|
||||
region := parameters.Get("region").MustString()
|
||||
resourceType := parameters.Get("resourceType").MustString()
|
||||
filterJson := parameters.Get("tags").MustMap()
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
|
||||
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/resourcegroupstaggingapiiface"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -45,8 +45,8 @@ func TestQuery_Metrics(t *testing.T) {
|
||||
},
|
||||
}
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "metricFindQuery",
|
||||
@@ -59,15 +59,15 @@ func TestQuery_Metrics(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
"": {
|
||||
Meta: simplejson.NewFromAny(map[string]interface{}{
|
||||
"rowCount": 1,
|
||||
}),
|
||||
Tables: []*tsdb.Table{
|
||||
Tables: []plugins.DataTable{
|
||||
{
|
||||
Columns: []tsdb.TableColumn{
|
||||
Columns: []plugins.DataTableColumn{
|
||||
{
|
||||
Text: "text",
|
||||
},
|
||||
@@ -75,7 +75,7 @@ func TestQuery_Metrics(t *testing.T) {
|
||||
Text: "value",
|
||||
},
|
||||
},
|
||||
Rows: []tsdb.RowValues{
|
||||
Rows: []plugins.DataRowValues{
|
||||
{
|
||||
"Test_MetricName",
|
||||
"Test_MetricName",
|
||||
@@ -102,8 +102,8 @@ func TestQuery_Metrics(t *testing.T) {
|
||||
},
|
||||
}
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "metricFindQuery",
|
||||
@@ -116,15 +116,15 @@ func TestQuery_Metrics(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
"": {
|
||||
Meta: simplejson.NewFromAny(map[string]interface{}{
|
||||
"rowCount": 1,
|
||||
}),
|
||||
Tables: []*tsdb.Table{
|
||||
Tables: []plugins.DataTable{
|
||||
{
|
||||
Columns: []tsdb.TableColumn{
|
||||
Columns: []plugins.DataTableColumn{
|
||||
{
|
||||
Text: "text",
|
||||
},
|
||||
@@ -132,7 +132,7 @@ func TestQuery_Metrics(t *testing.T) {
|
||||
Text: "value",
|
||||
},
|
||||
},
|
||||
Rows: []tsdb.RowValues{
|
||||
Rows: []plugins.DataRowValues{
|
||||
{
|
||||
"Test_DimensionName",
|
||||
"Test_DimensionName",
|
||||
@@ -164,8 +164,8 @@ func TestQuery_Regions(t *testing.T) {
|
||||
regions: []string{regionName},
|
||||
}
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "metricFindQuery",
|
||||
@@ -178,7 +178,7 @@ func TestQuery_Regions(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
rows := []tsdb.RowValues{}
|
||||
rows := []plugins.DataRowValues{}
|
||||
for _, region := range knownRegions {
|
||||
rows = append(rows, []interface{}{
|
||||
region,
|
||||
@@ -189,15 +189,15 @@ func TestQuery_Regions(t *testing.T) {
|
||||
regionName,
|
||||
regionName,
|
||||
})
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
"": {
|
||||
Meta: simplejson.NewFromAny(map[string]interface{}{
|
||||
"rowCount": len(knownRegions) + 1,
|
||||
}),
|
||||
Tables: []*tsdb.Table{
|
||||
Tables: []plugins.DataTable{
|
||||
{
|
||||
Columns: []tsdb.TableColumn{
|
||||
Columns: []plugins.DataTableColumn{
|
||||
{
|
||||
Text: "text",
|
||||
},
|
||||
@@ -246,8 +246,8 @@ func TestQuery_InstanceAttributes(t *testing.T) {
|
||||
},
|
||||
}
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "metricFindQuery",
|
||||
@@ -263,15 +263,15 @@ func TestQuery_InstanceAttributes(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
"": {
|
||||
Meta: simplejson.NewFromAny(map[string]interface{}{
|
||||
"rowCount": 1,
|
||||
}),
|
||||
Tables: []*tsdb.Table{
|
||||
Tables: []plugins.DataTable{
|
||||
{
|
||||
Columns: []tsdb.TableColumn{
|
||||
Columns: []plugins.DataTableColumn{
|
||||
{
|
||||
Text: "text",
|
||||
},
|
||||
@@ -279,7 +279,7 @@ func TestQuery_InstanceAttributes(t *testing.T) {
|
||||
Text: "value",
|
||||
},
|
||||
},
|
||||
Rows: []tsdb.RowValues{
|
||||
Rows: []plugins.DataRowValues{
|
||||
{
|
||||
instanceID,
|
||||
instanceID,
|
||||
@@ -349,8 +349,8 @@ func TestQuery_EBSVolumeIDs(t *testing.T) {
|
||||
},
|
||||
}
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "metricFindQuery",
|
||||
@@ -363,15 +363,15 @@ func TestQuery_EBSVolumeIDs(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
"": {
|
||||
Meta: simplejson.NewFromAny(map[string]interface{}{
|
||||
"rowCount": 6,
|
||||
}),
|
||||
Tables: []*tsdb.Table{
|
||||
Tables: []plugins.DataTable{
|
||||
{
|
||||
Columns: []tsdb.TableColumn{
|
||||
Columns: []plugins.DataTableColumn{
|
||||
{
|
||||
Text: "text",
|
||||
},
|
||||
@@ -379,7 +379,7 @@ func TestQuery_EBSVolumeIDs(t *testing.T) {
|
||||
Text: "value",
|
||||
},
|
||||
},
|
||||
Rows: []tsdb.RowValues{
|
||||
Rows: []plugins.DataRowValues{
|
||||
{
|
||||
"vol-1-1",
|
||||
"vol-1-1",
|
||||
@@ -449,8 +449,8 @@ func TestQuery_ResourceARNs(t *testing.T) {
|
||||
},
|
||||
}
|
||||
executor := newExecutor(nil)
|
||||
resp, err := executor.Query(context.Background(), fakeDataSource(), &tsdb.TsdbQuery{
|
||||
Queries: []*tsdb.Query{
|
||||
resp, err := executor.DataQuery(context.Background(), fakeDataSource(), plugins.DataQuery{
|
||||
Queries: []plugins.DataSubQuery{
|
||||
{
|
||||
Model: simplejson.NewFromAny(map[string]interface{}{
|
||||
"type": "metricFindQuery",
|
||||
@@ -466,15 +466,15 @@ func TestQuery_ResourceARNs(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, &tsdb.Response{
|
||||
Results: map[string]*tsdb.QueryResult{
|
||||
assert.Equal(t, plugins.DataResponse{
|
||||
Results: map[string]plugins.DataQueryResult{
|
||||
"": {
|
||||
Meta: simplejson.NewFromAny(map[string]interface{}{
|
||||
"rowCount": 2,
|
||||
}),
|
||||
Tables: []*tsdb.Table{
|
||||
Tables: []plugins.DataTable{
|
||||
{
|
||||
Columns: []tsdb.TableColumn{
|
||||
Columns: []plugins.DataTableColumn{
|
||||
{
|
||||
Text: "text",
|
||||
},
|
||||
@@ -482,7 +482,7 @@ func TestQuery_ResourceARNs(t *testing.T) {
|
||||
Text: "value",
|
||||
},
|
||||
},
|
||||
Rows: []tsdb.RowValues{
|
||||
Rows: []plugins.DataRowValues{
|
||||
{
|
||||
"arn:aws:ec2:us-east-1:123456789012:instance/i-12345678901234567",
|
||||
"arn:aws:ec2:us-east-1:123456789012:instance/i-12345678901234567",
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
)
|
||||
|
||||
// returns a map of queries with query id as key. In the case a q request query
|
||||
@@ -55,7 +55,8 @@ func (e *cloudWatchExecutor) transformRequestQueriesToCloudWatchQueries(requestQ
|
||||
return cloudwatchQueries, nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) transformQueryResponsesToQueryResult(cloudwatchResponses []*cloudwatchResponse, requestQueries []*requestQuery, startTime time.Time, endTime time.Time) (map[string]*tsdb.QueryResult, error) {
|
||||
func (e *cloudWatchExecutor) transformQueryResponsesToQueryResult(cloudwatchResponses []*cloudwatchResponse,
|
||||
requestQueries []*requestQuery, startTime time.Time, endTime time.Time) (map[string]plugins.DataQueryResult, error) {
|
||||
responsesByRefID := make(map[string][]*cloudwatchResponse)
|
||||
refIDs := sort.StringSlice{}
|
||||
for _, res := range cloudwatchResponses {
|
||||
@@ -65,12 +66,13 @@ func (e *cloudWatchExecutor) transformQueryResponsesToQueryResult(cloudwatchResp
|
||||
// Ensure stable results
|
||||
refIDs.Sort()
|
||||
|
||||
results := make(map[string]*tsdb.QueryResult)
|
||||
results := make(map[string]plugins.DataQueryResult)
|
||||
for _, refID := range refIDs {
|
||||
responses := responsesByRefID[refID]
|
||||
queryResult := tsdb.NewQueryResult()
|
||||
queryResult.RefId = refID
|
||||
queryResult.Series = tsdb.TimeSeriesSlice{}
|
||||
queryResult := plugins.DataQueryResult{
|
||||
RefID: refID,
|
||||
Series: plugins.DataTimeSeriesSlice{},
|
||||
}
|
||||
frames := make(data.Frames, 0, len(responses))
|
||||
|
||||
requestExceededMaxLimit := false
|
||||
@@ -133,15 +135,17 @@ func (e *cloudWatchExecutor) transformQueryResponsesToQueryResult(cloudwatchResp
|
||||
frame.Fields[1].Config.Links = createDataLinks(link)
|
||||
}
|
||||
|
||||
queryResult.Dataframes = tsdb.NewDecodedDataFrames(frames)
|
||||
queryResult.Dataframes = plugins.NewDecodedDataFrames(frames)
|
||||
results[refID] = queryResult
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// buildDeepLink generates a deep link from Grafana to the CloudWatch console. The link params are based on metric(s) for a given query row in the Query Editor.
|
||||
func buildDeepLink(refID string, requestQueries []*requestQuery, executedQueries []executedQuery, startTime time.Time, endTime time.Time) (string, error) {
|
||||
// buildDeepLink generates a deep link from Grafana to the CloudWatch console. The link params are based on
|
||||
// metric(s) for a given query row in the Query Editor.
|
||||
func buildDeepLink(refID string, requestQueries []*requestQuery, executedQueries []executedQuery, startTime time.Time,
|
||||
endTime time.Time) (string, error) {
|
||||
if isMathExpression(executedQueries) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -11,11 +11,12 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
)
|
||||
|
||||
// Parses the json queries and returns a requestQuery. The requestQuery has a 1 to 1 mapping to a query editor row
|
||||
func (e *cloudWatchExecutor) parseQueries(queryContext *tsdb.TsdbQuery, startTime time.Time, endTime time.Time) (map[string][]*requestQuery, error) {
|
||||
func (e *cloudWatchExecutor) parseQueries(queryContext plugins.DataQuery, startTime time.Time,
|
||||
endTime time.Time) (map[string][]*requestQuery, error) {
|
||||
requestQueries := make(map[string][]*requestQuery)
|
||||
for i, query := range queryContext.Queries {
|
||||
queryType := query.Model.Get("type").MustString()
|
||||
@@ -23,7 +24,7 @@ func (e *cloudWatchExecutor) parseQueries(queryContext *tsdb.TsdbQuery, startTim
|
||||
continue
|
||||
}
|
||||
|
||||
refID := query.RefId
|
||||
refID := query.RefID
|
||||
query, err := parseRequestQuery(queryContext.Queries[i].Model, refID, startTime, endTime)
|
||||
if err != nil {
|
||||
return nil, &queryError{err: err, RefID: refID}
|
||||
|
||||
@@ -5,13 +5,13 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRequestParser(t *testing.T) {
|
||||
timeRange := tsdb.NewTimeRange("now-1h", "now-2h")
|
||||
timeRange := plugins.NewDataTimeRange("now-1h", "now-2h")
|
||||
from, err := timeRange.ParseFrom()
|
||||
require.NoError(t, err)
|
||||
to, err := timeRange.ParseTo()
|
||||
@@ -102,7 +102,7 @@ func TestRequestParser(t *testing.T) {
|
||||
"hide": false,
|
||||
})
|
||||
query.Set("period", "900")
|
||||
timeRange := tsdb.NewTimeRange("now-1h", "now-2h")
|
||||
timeRange := plugins.NewDataTimeRange("now-1h", "now-2h")
|
||||
from, err := timeRange.ParseFrom()
|
||||
require.NoError(t, err)
|
||||
to, err := timeRange.ParseTo()
|
||||
|
||||
@@ -5,37 +5,38 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, queryContext *tsdb.TsdbQuery) (*tsdb.Response, error) {
|
||||
func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, queryContext plugins.DataQuery) (
|
||||
plugins.DataResponse, error) {
|
||||
plog.Debug("Executing time series query")
|
||||
startTime, err := queryContext.TimeRange.ParseFrom()
|
||||
if err != nil {
|
||||
return nil, errutil.Wrap("failed to parse start time", err)
|
||||
return plugins.DataResponse{}, errutil.Wrap("failed to parse start time", err)
|
||||
}
|
||||
endTime, err := queryContext.TimeRange.ParseTo()
|
||||
if err != nil {
|
||||
return nil, errutil.Wrap("failed to parse end time", err)
|
||||
return plugins.DataResponse{}, errutil.Wrap("failed to parse end time", err)
|
||||
}
|
||||
if !startTime.Before(endTime) {
|
||||
return nil, fmt.Errorf("invalid time range: start time must be before end time")
|
||||
return plugins.DataResponse{}, fmt.Errorf("invalid time range: start time must be before end time")
|
||||
}
|
||||
|
||||
requestQueriesByRegion, err := e.parseQueries(queryContext, startTime, endTime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
|
||||
if len(requestQueriesByRegion) == 0 {
|
||||
return &tsdb.Response{
|
||||
Results: make(map[string]*tsdb.QueryResult),
|
||||
return plugins.DataResponse{
|
||||
Results: make(map[string]plugins.DataQueryResult),
|
||||
}, nil
|
||||
}
|
||||
|
||||
resultChan := make(chan *tsdb.QueryResult, len(queryContext.Queries))
|
||||
resultChan := make(chan plugins.DataQueryResult, len(queryContext.Queries))
|
||||
eg, ectx := errgroup.WithContext(ctx)
|
||||
for r, q := range requestQueriesByRegion {
|
||||
requestQueries := q
|
||||
@@ -45,7 +46,7 @@ func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, queryCo
|
||||
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 <- &tsdb.QueryResult{
|
||||
resultChan <- plugins.DataQueryResult{
|
||||
Error: theErr,
|
||||
}
|
||||
}
|
||||
@@ -60,8 +61,8 @@ func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, queryCo
|
||||
queries, err := e.transformRequestQueriesToCloudWatchQueries(requestQueries)
|
||||
if err != nil {
|
||||
for _, query := range requestQueries {
|
||||
resultChan <- &tsdb.QueryResult{
|
||||
RefId: query.RefId,
|
||||
resultChan <- plugins.DataQueryResult{
|
||||
RefID: query.RefId,
|
||||
Error: err,
|
||||
}
|
||||
}
|
||||
@@ -77,8 +78,8 @@ func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, queryCo
|
||||
mdo, err := e.executeRequest(ectx, client, metricDataInput)
|
||||
if err != nil {
|
||||
for _, query := range requestQueries {
|
||||
resultChan <- &tsdb.QueryResult{
|
||||
RefId: query.RefId,
|
||||
resultChan <- plugins.DataQueryResult{
|
||||
RefID: query.RefId,
|
||||
Error: err,
|
||||
}
|
||||
}
|
||||
@@ -88,8 +89,8 @@ func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, queryCo
|
||||
responses, err := e.parseResponse(mdo, queries)
|
||||
if err != nil {
|
||||
for _, query := range requestQueries {
|
||||
resultChan <- &tsdb.QueryResult{
|
||||
RefId: query.RefId,
|
||||
resultChan <- plugins.DataQueryResult{
|
||||
RefID: query.RefId,
|
||||
Error: err,
|
||||
}
|
||||
}
|
||||
@@ -100,8 +101,8 @@ func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, queryCo
|
||||
res, err := e.transformQueryResponsesToQueryResult(cloudwatchResponses, requestQueries, startTime, endTime)
|
||||
if err != nil {
|
||||
for _, query := range requestQueries {
|
||||
resultChan <- &tsdb.QueryResult{
|
||||
RefId: query.RefId,
|
||||
resultChan <- plugins.DataQueryResult{
|
||||
RefID: query.RefId,
|
||||
Error: err,
|
||||
}
|
||||
}
|
||||
@@ -115,15 +116,15 @@ func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, queryCo
|
||||
})
|
||||
}
|
||||
if err := eg.Wait(); err != nil {
|
||||
return nil, err
|
||||
return plugins.DataResponse{}, err
|
||||
}
|
||||
close(resultChan)
|
||||
|
||||
results := &tsdb.Response{
|
||||
Results: make(map[string]*tsdb.QueryResult),
|
||||
results := plugins.DataResponse{
|
||||
Results: make(map[string]plugins.DataQueryResult),
|
||||
}
|
||||
for result := range resultChan {
|
||||
results.Results[result.RefId] = result
|
||||
results.Results[result.RefID] = result
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -12,12 +12,16 @@ func TestTimeSeriesQuery(t *testing.T) {
|
||||
executor := newExecutor(nil)
|
||||
|
||||
t.Run("End time before start time should result in error", func(t *testing.T) {
|
||||
_, err := executor.executeTimeSeriesQuery(context.TODO(), &tsdb.TsdbQuery{TimeRange: tsdb.NewTimeRange("now-1h", "now-2h")})
|
||||
timeRange := plugins.NewDataTimeRange("now-1h", "now-2h")
|
||||
_, err := executor.executeTimeSeriesQuery(
|
||||
context.TODO(), plugins.DataQuery{TimeRange: &timeRange})
|
||||
assert.EqualError(t, err, "invalid time range: start time must be before end time")
|
||||
})
|
||||
|
||||
t.Run("End time equals start time should result in error", func(t *testing.T) {
|
||||
_, err := executor.executeTimeSeriesQuery(context.TODO(), &tsdb.TsdbQuery{TimeRange: tsdb.NewTimeRange("now-1h", "now-1h")})
|
||||
timeRange := plugins.NewDataTimeRange("now-1h", "now-1h")
|
||||
_, err := executor.executeTimeSeriesQuery(
|
||||
context.TODO(), plugins.DataQuery{TimeRange: &timeRange})
|
||||
assert.EqualError(t, err, "invalid time range: start time must be before end time")
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user