2019-11-14 17:59:41 +08:00
package cloudwatch
import (
2024-04-05 23:57:56 +08:00
"context"
2019-11-14 17:59:41 +08:00
"testing"
2025-09-19 18:46:40 +08:00
"github.com/aws/aws-sdk-go-v2/aws"
2024-04-05 23:57:56 +08:00
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/features"
2022-11-02 22:14:02 +08:00
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
2022-11-28 19:39:12 +08:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2019-11-14 17:59:41 +08:00
)
2021-11-30 17:53:31 +08:00
func TestMetricDataQueryBuilder ( t * testing . T ) {
2025-09-19 18:46:40 +08:00
ds := newTestDatasource ( )
2021-09-23 22:03:58 +08:00
t . Run ( "buildMetricDataQuery" , func ( t * testing . T ) {
2021-11-30 17:53:31 +08:00
t . Run ( "should use metric stat" , func ( t * testing . T ) {
query := getBaseQuery ( )
2022-10-20 17:21:13 +08:00
query . MetricEditorMode = models . MetricEditorModeBuilder
query . MetricQueryType = models . MetricQueryTypeSearch
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( context . Background ( ) , query )
2021-11-30 17:53:31 +08:00
require . NoError ( t , err )
require . Empty ( t , mdq . Expression )
assert . Equal ( t , query . MetricName , * mdq . MetricStat . Metric . MetricName )
assert . Equal ( t , query . Namespace , * mdq . MetricStat . Metric . Namespace )
} )
2022-11-28 19:39:12 +08:00
t . Run ( "should pass AccountId in metric stat query" , func ( t * testing . T ) {
query := getBaseQuery ( )
query . MetricEditorMode = models . MetricEditorModeBuilder
query . MetricQueryType = models . MetricQueryTypeSearch
query . AccountId = aws . String ( "some account id" )
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( context . Background ( ) , query )
2022-11-28 19:39:12 +08:00
require . NoError ( t , err )
assert . Equal ( t , "some account id" , * mdq . AccountId )
} )
t . Run ( "should leave AccountId in metric stat query" , func ( t * testing . T ) {
query := getBaseQuery ( )
query . MetricEditorMode = models . MetricEditorModeBuilder
query . MetricQueryType = models . MetricQueryTypeSearch
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( context . Background ( ) , query )
2022-11-28 19:39:12 +08:00
require . NoError ( t , err )
assert . Nil ( t , mdq . AccountId )
} )
2021-11-30 17:53:31 +08:00
t . Run ( "should use custom built expression" , func ( t * testing . T ) {
query := getBaseQuery ( )
2022-10-20 17:21:13 +08:00
query . MetricEditorMode = models . MetricEditorModeBuilder
query . MetricQueryType = models . MetricQueryTypeSearch
2021-11-30 17:53:31 +08:00
query . MatchExact = false
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( context . Background ( ) , query )
2021-11-30 17:53:31 +08:00
require . NoError ( t , err )
require . Nil ( t , mdq . MetricStat )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH('Namespace="AWS/EC2" MetricName="CPUUtilization" "LoadBalancer"="lb1"', '', 300)) ` , * mdq . Expression )
} )
t . Run ( "should use sql expression" , func ( t * testing . T ) {
query := getBaseQuery ( )
2022-10-20 17:21:13 +08:00
query . MetricEditorMode = models . MetricEditorModeRaw
query . MetricQueryType = models . MetricQueryTypeQuery
2021-11-30 17:53:31 +08:00
query . SqlExpression = ` SELECT SUM(CPUUTilization) FROM "AWS/EC2" `
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( context . Background ( ) , query )
2021-11-30 17:53:31 +08:00
require . NoError ( t , err )
require . Nil ( t , mdq . MetricStat )
assert . Equal ( t , query . SqlExpression , * mdq . Expression )
} )
t . Run ( "should use user defined math expression" , func ( t * testing . T ) {
query := getBaseQuery ( )
2022-10-20 17:21:13 +08:00
query . MetricEditorMode = models . MetricEditorModeRaw
query . MetricQueryType = models . MetricQueryTypeSearch
2021-11-30 17:53:31 +08:00
query . Expression = ` SUM(x+y) `
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( context . Background ( ) , query )
2021-11-30 17:53:31 +08:00
require . NoError ( t , err )
require . Nil ( t , mdq . MetricStat )
assert . Equal ( t , query . Expression , * mdq . Expression )
} )
2021-09-23 22:03:58 +08:00
t . Run ( "should set period in user defined expression" , func ( t * testing . T ) {
2021-11-30 17:53:31 +08:00
query := getBaseQuery ( )
2022-10-20 17:21:13 +08:00
query . MetricEditorMode = models . MetricEditorModeRaw
query . MetricQueryType = models . MetricQueryTypeSearch
2021-09-23 22:03:58 +08:00
query . MatchExact = false
2021-11-30 17:53:31 +08:00
query . Expression = ` SUM([a,b]) `
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( context . Background ( ) , query )
2021-09-23 22:03:58 +08:00
require . NoError ( t , err )
require . Nil ( t , mdq . MetricStat )
2025-09-19 18:46:40 +08:00
assert . Equal ( t , int32 ( 300 ) , * mdq . Period )
2021-09-23 22:03:58 +08:00
assert . Equal ( t , ` SUM([a,b]) ` , * mdq . Expression )
} )
2022-05-05 19:59:23 +08:00
2023-04-27 17:19:45 +08:00
t . Run ( "should set label" , func ( t * testing . T ) {
2022-05-05 19:59:23 +08:00
query := getBaseQuery ( )
query . Label = "some label"
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( context . Background ( ) , query )
2022-05-05 19:59:23 +08:00
assert . NoError ( t , err )
require . NotNil ( t , mdq . Label )
assert . Equal ( t , "some label" , * mdq . Label )
} )
2023-04-27 17:19:45 +08:00
t . Run ( "should not set label for empty string query label" , func ( t * testing . T ) {
query := getBaseQuery ( )
query . Label = ""
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( context . Background ( ) , query )
2023-04-27 17:19:45 +08:00
assert . NoError ( t , err )
assert . Nil ( t , mdq . Label )
} )
2022-11-28 19:39:12 +08:00
t . Run ( ` should not specify accountId when it is "all" ` , func ( t * testing . T ) {
query := & models . CloudWatchQuery {
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Statistic : "Average" ,
Period : 60 ,
MatchExact : false ,
AccountId : aws . String ( "all" ) ,
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( context . Background ( ) , query )
2022-11-28 19:39:12 +08:00
assert . NoError ( t , err )
require . Nil ( t , mdq . MetricStat )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH('Namespace="AWS/EC2" MetricName="CPUUtilization"', 'Average', 60)) ` , * mdq . Expression )
} )
t . Run ( "should set accountId when it is specified" , func ( t * testing . T ) {
query := & models . CloudWatchQuery {
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Statistic : "Average" ,
Period : 60 ,
MatchExact : false ,
AccountId : aws . String ( "12345" ) ,
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( context . Background ( ) , query )
2022-11-28 19:39:12 +08:00
assert . NoError ( t , err )
require . Nil ( t , mdq . MetricStat )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH('Namespace="AWS/EC2" MetricName="CPUUtilization" :aws.AccountId="12345"', 'Average', 60)) ` , * mdq . Expression )
} )
2021-09-23 22:03:58 +08:00
} )
2020-10-03 01:40:15 +08:00
t . Run ( "Query should be matched exact" , func ( t * testing . T ) {
const matchExact = true
t . Run ( "Query has three dimension values for a given dimension key" , func ( t * testing . T ) {
2022-10-20 17:21:13 +08:00
query := & models . CloudWatchQuery {
2020-10-03 01:40:15 +08:00
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "lb1" , "lb2" , "lb3" } ,
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2020-10-03 01:40:15 +08:00
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH(' { "AWS/EC2","LoadBalancer"} MetricName="CPUUtilization" "LoadBalancer"=("lb1" OR "lb2" OR "lb3")', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.LoadBalancer')}" , * mdq . Label )
2019-11-14 17:59:41 +08:00
} )
2020-10-03 01:40:15 +08:00
t . Run ( "Query has three dimension values for two given dimension keys" , func ( t * testing . T ) {
2022-10-20 17:21:13 +08:00
query := & models . CloudWatchQuery {
2019-11-14 17:59:41 +08:00
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
2020-10-03 01:40:15 +08:00
"LoadBalancer" : { "lb1" , "lb2" , "lb3" } ,
"InstanceId" : { "i-123" , "i-456" , "i-789" } ,
2019-11-14 17:59:41 +08:00
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2019-11-14 17:59:41 +08:00
}
2020-10-03 01:40:15 +08:00
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH(' { "AWS/EC2","InstanceId","LoadBalancer"} MetricName="CPUUtilization" "InstanceId"=("i-123" OR "i-456" OR "i-789") "LoadBalancer"=("lb1" OR "lb2" OR "lb3")', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.InstanceId')}|&|${PROP('Dim.LoadBalancer')}" , * mdq . Label )
2019-11-14 17:59:41 +08:00
} )
2020-10-03 01:40:15 +08:00
t . Run ( "Query has one dimension key with a * value" , func ( t * testing . T ) {
2022-10-20 17:21:13 +08:00
query := & models . CloudWatchQuery {
2020-10-03 01:40:15 +08:00
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "*" } ,
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2020-10-03 01:40:15 +08:00
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH(' { "AWS/EC2","LoadBalancer"} MetricName="CPUUtilization"', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.LoadBalancer')}" , * mdq . Label )
2020-10-03 01:40:15 +08:00
} )
t . Run ( "Query has three dimension values for two given dimension keys, and one value is a star" , func ( t * testing . T ) {
2022-10-20 17:21:13 +08:00
query := & models . CloudWatchQuery {
2020-10-03 01:40:15 +08:00
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "lb1" , "lb2" , "lb3" } ,
"InstanceId" : { "i-123" , "*" , "i-789" } ,
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2020-10-03 01:40:15 +08:00
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH(' { "AWS/EC2","InstanceId","LoadBalancer"} MetricName="CPUUtilization" "LoadBalancer"=("lb1" OR "lb2" OR "lb3")', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.InstanceId')}|&|${PROP('Dim.LoadBalancer')}" , * mdq . Label )
2020-10-03 01:40:15 +08:00
} )
2022-11-28 19:39:12 +08:00
t . Run ( "Query has multiple dimensions and an account Id" , func ( t * testing . T ) {
query := & models . CloudWatchQuery {
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "lb1" , "lb2" , "lb3" } ,
"InstanceId" : { "i-123" , "*" , "i-789" } ,
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
AccountId : aws . String ( "some account id" ) ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2022-11-28 19:39:12 +08:00
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH(' { "AWS/EC2","InstanceId","LoadBalancer"} MetricName="CPUUtilization" "LoadBalancer"=("lb1" OR "lb2" OR "lb3") :aws.AccountId="some account id"', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.InstanceId')}|&|${PROP('Dim.LoadBalancer')}" , * mdq . Label )
2022-11-28 19:39:12 +08:00
} )
2020-10-03 01:40:15 +08:00
t . Run ( "Query has a dimension key with a space" , func ( t * testing . T ) {
2022-10-20 17:21:13 +08:00
query := & models . CloudWatchQuery {
2020-10-03 01:40:15 +08:00
Namespace : "AWS/Kafka" ,
MetricName : "CpuUser" ,
Dimensions : map [ string ] [ ] string {
2024-04-05 23:57:56 +08:00
"Cluster Name" : { "dev-cluster" , "prod-cluster" } ,
2020-10-03 01:40:15 +08:00
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2020-10-03 01:40:15 +08:00
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH(' { "AWS/Kafka","Cluster Name"} MetricName="CpuUser" "Cluster Name"=("dev-cluster" OR "prod-cluster")', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.Cluster Name')}" , * mdq . Label )
2020-12-08 19:37:07 +08:00
} )
t . Run ( "Query has a custom namespace contains spaces" , func ( t * testing . T ) {
2022-10-20 17:21:13 +08:00
query := & models . CloudWatchQuery {
2020-12-08 19:37:07 +08:00
Namespace : "Test-API Cache by Minute" ,
MetricName : "CpuUser" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "lb1" , "lb2" , "lb3" } ,
"InstanceId" : { "i-123" , "*" , "i-789" } ,
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2020-12-08 19:37:07 +08:00
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH(' { "Test-API Cache by Minute","InstanceId","LoadBalancer"} MetricName="CpuUser" "LoadBalancer"=("lb1" OR "lb2" OR "lb3")', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.InstanceId')}|&|${PROP('Dim.LoadBalancer')}" , * mdq . Label )
} )
t . Run ( "Query has a custom label" , func ( t * testing . T ) {
query := & models . CloudWatchQuery {
Namespace : "CPUUtilization" ,
MetricName : "CpuUser" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "lb1" } ,
"InstanceId" : { "i-123" , "*" , "i-789" } ,
} ,
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
Label : "LB: ${PROP('Dim.LoadBalancer')" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH(' { "CPUUtilization","InstanceId","LoadBalancer"} MetricName="CpuUser" "LoadBalancer"="lb1"', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "LB: ${PROP('Dim.LoadBalancer')|&|${PROP('Dim.InstanceId')}" , * mdq . Label )
2020-10-03 01:40:15 +08:00
} )
} )
t . Run ( "Query should not be matched exact" , func ( t * testing . T ) {
const matchExact = false
t . Run ( "Query has three dimension values for a given dimension key" , func ( t * testing . T ) {
2022-10-20 17:21:13 +08:00
query := & models . CloudWatchQuery {
2020-10-03 01:40:15 +08:00
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "lb1" , "lb2" , "lb3" } ,
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2020-10-03 01:40:15 +08:00
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH('Namespace="AWS/EC2" MetricName="CPUUtilization" "LoadBalancer"=("lb1" OR "lb2" OR "lb3")', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.LoadBalancer')}" , * mdq . Label )
2020-10-03 01:40:15 +08:00
} )
t . Run ( "Query has three dimension values for two given dimension keys" , func ( t * testing . T ) {
2022-10-20 17:21:13 +08:00
query := & models . CloudWatchQuery {
2020-10-03 01:40:15 +08:00
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "lb1" , "lb2" , "lb3" } ,
"InstanceId" : { "i-123" , "i-456" , "i-789" } ,
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2020-10-03 01:40:15 +08:00
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH('Namespace="AWS/EC2" MetricName="CPUUtilization" "InstanceId"=("i-123" OR "i-456" OR "i-789") "LoadBalancer"=("lb1" OR "lb2" OR "lb3")', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.InstanceId')}|&|${PROP('Dim.LoadBalancer')}" , * mdq . Label )
2020-10-03 01:40:15 +08:00
} )
t . Run ( "Query has one dimension key with a * value" , func ( t * testing . T ) {
2022-10-20 17:21:13 +08:00
query := & models . CloudWatchQuery {
2020-10-03 01:40:15 +08:00
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "*" } ,
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2020-10-03 01:40:15 +08:00
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH('Namespace="AWS/EC2" MetricName="CPUUtilization" "LoadBalancer"', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.LoadBalancer')}" , * mdq . Label )
2020-10-03 01:40:15 +08:00
} )
t . Run ( "query has three dimension values for two given dimension keys, and one value is a star" , func ( t * testing . T ) {
2022-10-20 17:21:13 +08:00
query := & models . CloudWatchQuery {
2020-10-03 01:40:15 +08:00
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "lb1" , "lb2" , "lb3" } ,
"InstanceId" : { "i-123" , "*" , "i-789" } ,
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2020-10-03 01:40:15 +08:00
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH('Namespace="AWS/EC2" MetricName="CPUUtilization" "LoadBalancer"=("lb1" OR "lb2" OR "lb3") "InstanceId"', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.InstanceId')}|&|${PROP('Dim.LoadBalancer')}" , * mdq . Label )
2020-10-03 01:40:15 +08:00
} )
2022-11-28 19:39:12 +08:00
t . Run ( "query has multiple dimensions and an account Id" , func ( t * testing . T ) {
query := & models . CloudWatchQuery {
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "lb1" , "lb2" , "lb3" } ,
"InstanceId" : { "i-123" , "*" , "i-789" } ,
} ,
2024-04-05 23:57:56 +08:00
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
AccountId : aws . String ( "some account id" ) ,
Statistic : "Average" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
2022-11-28 19:39:12 +08:00
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH('Namespace="AWS/EC2" MetricName="CPUUtilization" "LoadBalancer"=("lb1" OR "lb2" OR "lb3") "InstanceId" :aws.AccountId="some account id"', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "${LABEL}|&|${PROP('Dim.InstanceId')}|&|${PROP('Dim.LoadBalancer')}" , * mdq . Label )
} )
t . Run ( "Query has a custom label" , func ( t * testing . T ) {
query := & models . CloudWatchQuery {
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "lb1" } ,
"InstanceId" : { "i-123" , "*" , "i-789" } ,
} ,
Period : 300 ,
Expression : "" ,
MatchExact : matchExact ,
Statistic : "Average" ,
Label : "LB: ${PROP('Dim.LoadBalancer')" ,
MetricQueryType : models . MetricQueryTypeSearch ,
MetricEditorMode : models . MetricEditorModeBuilder ,
}
2025-09-19 18:46:40 +08:00
mdq , err := ds . buildMetricDataQuery ( contextWithFeaturesEnabled ( features . FlagCloudWatchNewLabelParsing ) , query )
2024-04-05 23:57:56 +08:00
require . NoError ( t , err )
assert . Equal ( t , ` REMOVE_EMPTY(SEARCH('Namespace="AWS/EC2" MetricName="CPUUtilization" "LoadBalancer"="lb1" "InstanceId"', 'Average', 300)) ` , * mdq . Expression )
assert . Equal ( t , "LB: ${PROP('Dim.LoadBalancer')|&|${PROP('Dim.InstanceId')}" , * mdq . Label )
2022-11-28 19:39:12 +08:00
} )
2020-10-03 01:40:15 +08:00
} )
t . Run ( "Query has invalid characters in dimension values" , func ( t * testing . T ) {
2022-10-20 17:21:13 +08:00
query := & models . CloudWatchQuery {
2020-10-03 01:40:15 +08:00
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
2024-05-02 21:15:11 +08:00
"lb4" : { ` lb4's""' ` } ,
2020-10-03 01:40:15 +08:00
} ,
Period : 300 ,
Expression : "" ,
MatchExact : true ,
}
res := buildSearchExpression ( query , "Average" )
2024-05-02 21:15:11 +08:00
assert . Contains ( t , res , ` lb4\'s\"\"\' ` , "Expected escaped quotes" )
2019-11-14 17:59:41 +08:00
} )
}
2021-11-30 17:53:31 +08:00
2022-10-20 17:21:13 +08:00
func getBaseQuery ( ) * models . CloudWatchQuery {
query := & models . CloudWatchQuery {
2021-11-30 17:53:31 +08:00
Namespace : "AWS/EC2" ,
MetricName : "CPUUtilization" ,
Dimensions : map [ string ] [ ] string {
"LoadBalancer" : { "lb1" } ,
} ,
Period : 300 ,
Expression : "" ,
MatchExact : true ,
}
return query
}