2019-11-14 03:59:41 -06:00
package cloudwatch
import (
"fmt"
"sort"
"strings"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/tsdb"
)
// returns a map of queries with query id as key. In the case a q request query
// has more than one statistic defined, one cloudwatchQuery will be created for each statistic.
// If the query doesn't have an Id defined by the user, we'll give it an with format `query[RefId]`. In the case
// the incoming query had more than one stat, it will ge an id like `query[RefId]_[StatName]`, eg queryC_Average
2020-09-08 08:06:58 -05:00
func ( e * cloudWatchExecutor ) transformRequestQueriesToCloudWatchQueries ( requestQueries [ ] * requestQuery ) ( map [ string ] * cloudWatchQuery , error ) {
2019-11-14 03:59:41 -06:00
cloudwatchQueries := make ( map [ string ] * cloudWatchQuery )
for _ , requestQuery := range requestQueries {
for _ , stat := range requestQuery . Statistics {
id := requestQuery . Id
if id == "" {
id = fmt . Sprintf ( "query%s" , requestQuery . RefId )
}
if len ( requestQuery . Statistics ) > 1 {
id = fmt . Sprintf ( "%s_%v" , id , strings . ReplaceAll ( * stat , "." , "_" ) )
}
2020-05-18 05:25:58 -05:00
if _ , ok := cloudwatchQueries [ id ] ; ok {
return nil , fmt . Errorf ( "error in query %q - query ID %q is not unique" , requestQuery . RefId , id )
}
2019-11-14 03:59:41 -06:00
query := & cloudWatchQuery {
2019-11-20 06:34:44 -06:00
Id : id ,
RefId : requestQuery . RefId ,
Region : requestQuery . Region ,
Namespace : requestQuery . Namespace ,
MetricName : requestQuery . MetricName ,
Dimensions : requestQuery . Dimensions ,
Stats : * stat ,
Period : requestQuery . Period ,
Alias : requestQuery . Alias ,
Expression : requestQuery . Expression ,
ReturnData : requestQuery . ReturnData ,
MatchExact : requestQuery . MatchExact ,
2019-11-14 03:59:41 -06:00
}
cloudwatchQueries [ id ] = query
}
}
return cloudwatchQueries , nil
}
2020-07-14 01:23:23 -05:00
func ( e * cloudWatchExecutor ) transformQueryResponseToQueryResult ( cloudwatchResponses [ ] * cloudwatchResponse ) map [ string ] * tsdb . QueryResult {
2019-11-14 03:59:41 -06:00
responsesByRefID := make ( map [ string ] [ ] * cloudwatchResponse )
for _ , res := range cloudwatchResponses {
2020-03-23 07:37:53 -05:00
responsesByRefID [ res . RefId ] = append ( responsesByRefID [ res . RefId ] , res )
2019-11-14 03:59:41 -06:00
}
2020-05-18 05:25:58 -05:00
results := make ( map [ string ] * tsdb . QueryResult )
2020-09-08 08:06:58 -05:00
for refID , responses := range responsesByRefID {
2019-11-14 03:59:41 -06:00
queryResult := tsdb . NewQueryResult ( )
queryResult . RefId = refID
queryResult . Meta = simplejson . New ( )
queryResult . Series = tsdb . TimeSeriesSlice { }
2020-09-08 08:06:58 -05:00
timeSeries := make ( tsdb . TimeSeriesSlice , 0 )
2019-11-14 03:59:41 -06:00
requestExceededMaxLimit := false
2020-01-17 04:18:28 -06:00
partialData := false
2019-11-14 03:59:41 -06:00
queryMeta := [ ] struct {
Expression , ID string
2020-01-17 06:22:43 -06:00
Period int
2019-11-14 03:59:41 -06:00
} { }
for _ , response := range responses {
2020-09-08 08:06:58 -05:00
timeSeries = append ( timeSeries , * response . series ... )
2019-11-14 03:59:41 -06:00
requestExceededMaxLimit = requestExceededMaxLimit || response . RequestExceededMaxLimit
2020-01-17 04:18:28 -06:00
partialData = partialData || response . PartialData
2019-11-14 03:59:41 -06:00
queryMeta = append ( queryMeta , struct {
Expression , ID string
2020-01-17 06:22:43 -06:00
Period int
2019-11-14 03:59:41 -06:00
} {
Expression : response . Expression ,
ID : response . Id ,
2020-01-17 06:22:43 -06:00
Period : response . Period ,
2019-11-14 03:59:41 -06:00
} )
}
2020-09-08 08:06:58 -05:00
sort . Slice ( timeSeries , func ( i , j int ) bool {
return timeSeries [ i ] . Name < timeSeries [ j ] . Name
2019-11-14 03:59:41 -06:00
} )
if requestExceededMaxLimit {
queryResult . ErrorString = "Cloudwatch GetMetricData error: Maximum number of allowed metrics exceeded. Your search may have been limited."
}
2020-01-17 04:18:28 -06:00
if partialData {
2020-01-20 11:51:32 -06:00
queryResult . ErrorString = "Cloudwatch GetMetricData error: Too many datapoints requested - your search has been limited. Please try to reduce the time range"
2020-01-17 04:18:28 -06:00
}
2020-09-08 08:06:58 -05:00
queryResult . Series = append ( queryResult . Series , timeSeries ... )
2019-11-14 03:59:41 -06:00
queryResult . Meta . Set ( "gmdMeta" , queryMeta )
results [ refID ] = queryResult
}
return results
}