diff --git a/src/main/java/io/prometheus/cloudwatch/BuildInfoCollector.java b/src/main/java/io/prometheus/cloudwatch/BuildInfoCollector.java index 6f68aa2f..1a9f590d 100644 --- a/src/main/java/io/prometheus/cloudwatch/BuildInfoCollector.java +++ b/src/main/java/io/prometheus/cloudwatch/BuildInfoCollector.java @@ -1,7 +1,6 @@ package io.prometheus.cloudwatch; import io.prometheus.client.Collector; - import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -10,40 +9,45 @@ import java.util.logging.Logger; public class BuildInfoCollector extends Collector { - private static final Logger LOGGER = Logger.getLogger(CloudWatchCollector.class.getName()); - - public List collect() { - List mfs = new ArrayList<>(); - List samples; - List labelNames = new ArrayList<>(); - List labelValues = new ArrayList<>(); - - String buildVersion = ""; - String releaseDate = ""; - try { - final Properties properties = new Properties(); - properties.load(CloudWatchCollector.class.getClassLoader().getResourceAsStream(".properties")); - buildVersion = properties.getProperty("BuildVersion"); - releaseDate = properties.getProperty("ReleaseDate"); - - } - catch (IOException e) { - buildVersion = "unknown"; - releaseDate = "unknown"; - LOGGER.log(Level.WARNING, "CloudWatch build info scrape failed", e); - } - - labelNames.add("build_version"); - labelValues.add(buildVersion); - labelNames.add("release_date"); - labelValues.add(releaseDate); - - samples = new ArrayList<>(); - samples.add(new MetricFamilySamples.Sample( - "cloudwatch_exporter_build_info", labelNames, labelValues, 1)); - mfs.add(new MetricFamilySamples("cloudwatch_exporter_build_info", - Type.GAUGE, "Non-zero if build info scrape failed.", samples)); - - return mfs; + private static final Logger LOGGER = Logger.getLogger(CloudWatchCollector.class.getName()); + + public List collect() { + List mfs = new ArrayList<>(); + List samples; + List labelNames = new ArrayList<>(); + List labelValues = new ArrayList<>(); + + String buildVersion = ""; + String releaseDate = ""; + try { + final Properties properties = new Properties(); + properties.load( + CloudWatchCollector.class.getClassLoader().getResourceAsStream(".properties")); + buildVersion = properties.getProperty("BuildVersion"); + releaseDate = properties.getProperty("ReleaseDate"); + + } catch (IOException e) { + buildVersion = "unknown"; + releaseDate = "unknown"; + LOGGER.log(Level.WARNING, "CloudWatch build info scrape failed", e); } + + labelNames.add("build_version"); + labelValues.add(buildVersion); + labelNames.add("release_date"); + labelValues.add(releaseDate); + + samples = new ArrayList<>(); + samples.add( + new MetricFamilySamples.Sample( + "cloudwatch_exporter_build_info", labelNames, labelValues, 1)); + mfs.add( + new MetricFamilySamples( + "cloudwatch_exporter_build_info", + Type.GAUGE, + "Non-zero if build info scrape failed.", + samples)); + + return mfs; + } } diff --git a/src/main/java/io/prometheus/cloudwatch/CloudWatchCollector.java b/src/main/java/io/prometheus/cloudwatch/CloudWatchCollector.java index 641af4fa..8a2d72d0 100644 --- a/src/main/java/io/prometheus/cloudwatch/CloudWatchCollector.java +++ b/src/main/java/io/prometheus/cloudwatch/CloudWatchCollector.java @@ -3,25 +3,22 @@ import io.prometheus.client.Collector; import io.prometheus.client.Collector.Describable; import io.prometheus.client.Counter; - import java.io.FileReader; -import java.io.Reader; import java.io.IOException; +import java.io.Reader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; -import java.util.List; -import java.util.Set; -import java.util.Map; import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Pattern; - import org.yaml.snakeyaml.Yaml; - import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; @@ -47,676 +44,781 @@ import software.amazon.awssdk.services.sts.model.AssumeRoleRequest; public class CloudWatchCollector extends Collector implements Describable { - private static final Logger LOGGER = Logger.getLogger(CloudWatchCollector.class.getName()); - - static class ActiveConfig { - ArrayList rules; - CloudWatchClient cloudWatchClient; - ResourceGroupsTaggingApiClient taggingClient; - - public ActiveConfig(ActiveConfig cfg) { - this.rules = new ArrayList<>(cfg.rules); - this.cloudWatchClient = cfg.cloudWatchClient; - this.taggingClient = cfg.taggingClient; - } - - public ActiveConfig() { - } - } - - static class MetricRule { - String awsNamespace; - String awsMetricName; - int periodSeconds; - int rangeSeconds; - int delaySeconds; - List awsStatistics; - List awsExtendedStatistics; - List awsDimensions; - Map> awsDimensionSelect; - Map> awsDimensionSelectRegex; - AWSTagSelect awsTagSelect; - String help; - boolean cloudwatchTimestamp; - } - - static class AWSTagSelect { - String resourceTypeSelection; - String resourceIdDimension; - Map> tagSelections; - } - - ActiveConfig activeConfig = new ActiveConfig(); - - private static final Counter cloudwatchRequests = Counter.build() - .labelNames("action", "namespace") - .name("cloudwatch_requests_total").help("API requests made to CloudWatch").register(); - - private static final Counter taggingApiRequests = Counter.build() - .labelNames("action", "resource_type") - .name("tagging_api_requests_total").help("API requests made to the Resource Groups Tagging API").register(); - - private static final List brokenDynamoMetrics = Arrays.asList( - "ConsumedReadCapacityUnits", "ConsumedWriteCapacityUnits", - "ProvisionedReadCapacityUnits", "ProvisionedWriteCapacityUnits", - "ReadThrottleEvents", "WriteThrottleEvents"); + private static final Logger LOGGER = Logger.getLogger(CloudWatchCollector.class.getName()); + + static class ActiveConfig { + ArrayList rules; + CloudWatchClient cloudWatchClient; + ResourceGroupsTaggingApiClient taggingClient; + + public ActiveConfig(ActiveConfig cfg) { + this.rules = new ArrayList<>(cfg.rules); + this.cloudWatchClient = cfg.cloudWatchClient; + this.taggingClient = cfg.taggingClient; + } + + public ActiveConfig() {} + } + + static class MetricRule { + String awsNamespace; + String awsMetricName; + int periodSeconds; + int rangeSeconds; + int delaySeconds; + List awsStatistics; + List awsExtendedStatistics; + List awsDimensions; + Map> awsDimensionSelect; + Map> awsDimensionSelectRegex; + AWSTagSelect awsTagSelect; + String help; + boolean cloudwatchTimestamp; + } + + static class AWSTagSelect { + String resourceTypeSelection; + String resourceIdDimension; + Map> tagSelections; + } + + ActiveConfig activeConfig = new ActiveConfig(); + + private static final Counter cloudwatchRequests = + Counter.build() + .labelNames("action", "namespace") + .name("cloudwatch_requests_total") + .help("API requests made to CloudWatch") + .register(); + + private static final Counter taggingApiRequests = + Counter.build() + .labelNames("action", "resource_type") + .name("tagging_api_requests_total") + .help("API requests made to the Resource Groups Tagging API") + .register(); + + private static final List brokenDynamoMetrics = + Arrays.asList( + "ConsumedReadCapacityUnits", "ConsumedWriteCapacityUnits", + "ProvisionedReadCapacityUnits", "ProvisionedWriteCapacityUnits", + "ReadThrottleEvents", "WriteThrottleEvents"); + + public CloudWatchCollector(Reader in) { + loadConfig(in, null, null); + } + + public CloudWatchCollector(String yamlConfig) { + this((Map) new Yaml().load(yamlConfig), null, null); + } + + /* For unittests. */ + protected CloudWatchCollector( + String jsonConfig, + CloudWatchClient cloudWatchClient, + ResourceGroupsTaggingApiClient taggingClient) { + this((Map) new Yaml().load(jsonConfig), cloudWatchClient, taggingClient); + } + + private CloudWatchCollector( + Map config, + CloudWatchClient cloudWatchClient, + ResourceGroupsTaggingApiClient taggingClient) { + loadConfig(config, cloudWatchClient, taggingClient); + } + + @Override + public List describe() { + return Collections.emptyList(); + } + + protected void reloadConfig() throws IOException { + LOGGER.log(Level.INFO, "Reloading configuration"); + try (FileReader reader = new FileReader(WebServer.configFilePath); ) { + loadConfig(reader, activeConfig.cloudWatchClient, activeConfig.taggingClient); + } + } + + protected void loadConfig( + Reader in, CloudWatchClient cloudWatchClient, ResourceGroupsTaggingApiClient taggingClient) { + loadConfig((Map) new Yaml().load(in), cloudWatchClient, taggingClient); + } + + private void loadConfig( + Map config, + CloudWatchClient cloudWatchClient, + ResourceGroupsTaggingApiClient taggingClient) { + if (config == null) { // Yaml config empty, set config to empty map. + config = new HashMap<>(); + } + + int defaultPeriod = 60; + if (config.containsKey("period_seconds")) { + defaultPeriod = ((Number) config.get("period_seconds")).intValue(); + } + int defaultRange = 600; + if (config.containsKey("range_seconds")) { + defaultRange = ((Number) config.get("range_seconds")).intValue(); + } + int defaultDelay = 600; + if (config.containsKey("delay_seconds")) { + defaultDelay = ((Number) config.get("delay_seconds")).intValue(); + } + + boolean defaultCloudwatchTimestamp = true; + if (config.containsKey("set_timestamp")) { + defaultCloudwatchTimestamp = (Boolean) config.get("set_timestamp"); + } + + String region = (String) config.get("region"); + + if (cloudWatchClient == null) { + CloudWatchClientBuilder clientBuilder = CloudWatchClient.builder(); + + if (config.containsKey("role_arn")) { + clientBuilder.credentialsProvider(getRoleCredentialProvider(config)); + } - public CloudWatchCollector(Reader in) { - loadConfig(in, null, null); - } - public CloudWatchCollector(String yamlConfig) { - this((Map)new Yaml().load(yamlConfig), null, null); - } + if (region != null) { + clientBuilder.region(Region.of(region)); + } - /* For unittests. */ - protected CloudWatchCollector(String jsonConfig, CloudWatchClient cloudWatchClient, ResourceGroupsTaggingApiClient taggingClient) { - this((Map)new Yaml().load(jsonConfig), cloudWatchClient, taggingClient); + cloudWatchClient = clientBuilder.build(); } - private CloudWatchCollector(Map config, CloudWatchClient cloudWatchClient, ResourceGroupsTaggingApiClient taggingClient) { - loadConfig(config, cloudWatchClient, taggingClient); - } + if (taggingClient == null) { + ResourceGroupsTaggingApiClientBuilder clientBuilder = + ResourceGroupsTaggingApiClient.builder(); - @Override - public List describe() { - return Collections.emptyList(); - } - - protected void reloadConfig() throws IOException { - LOGGER.log(Level.INFO, "Reloading configuration"); - try ( - FileReader reader = new FileReader(WebServer.configFilePath); - ) { - loadConfig(reader, activeConfig.cloudWatchClient, activeConfig.taggingClient); - } + if (config.containsKey("role_arn")) { + clientBuilder.credentialsProvider(getRoleCredentialProvider(config)); + } + if (region != null) { + clientBuilder.region(Region.of(region)); + } + taggingClient = clientBuilder.build(); } - protected void loadConfig(Reader in, CloudWatchClient cloudWatchClient, ResourceGroupsTaggingApiClient taggingClient) { - loadConfig((Map)new Yaml().load(in), cloudWatchClient, taggingClient); + if (!config.containsKey("metrics")) { + throw new IllegalArgumentException("Must provide metrics"); } - private void loadConfig(Map config, CloudWatchClient cloudWatchClient, ResourceGroupsTaggingApiClient taggingClient) { - if(config == null) { // Yaml config empty, set config to empty map. - config = new HashMap<>(); - } + ArrayList rules = new ArrayList<>(); - int defaultPeriod = 60; - if (config.containsKey("period_seconds")) { - defaultPeriod = ((Number)config.get("period_seconds")).intValue(); - } - int defaultRange = 600; - if (config.containsKey("range_seconds")) { - defaultRange = ((Number)config.get("range_seconds")).intValue(); - } - int defaultDelay = 600; - if (config.containsKey("delay_seconds")) { - defaultDelay = ((Number)config.get("delay_seconds")).intValue(); - } - - boolean defaultCloudwatchTimestamp = true; - if (config.containsKey("set_timestamp")) { - defaultCloudwatchTimestamp = (Boolean)config.get("set_timestamp"); - } - - String region = (String) config.get("region"); - - if (cloudWatchClient == null) { - CloudWatchClientBuilder clientBuilder = CloudWatchClient.builder(); - - if (config.containsKey("role_arn")) { - clientBuilder.credentialsProvider(getRoleCredentialProvider(config)); - } - - if (region != null) { - clientBuilder.region(Region.of(region)); - } - - cloudWatchClient = clientBuilder.build(); - } - - if (taggingClient == null) { - ResourceGroupsTaggingApiClientBuilder clientBuilder = ResourceGroupsTaggingApiClient.builder(); - - if (config.containsKey("role_arn")) { - clientBuilder.credentialsProvider(getRoleCredentialProvider(config)); - } - if (region != null) { - clientBuilder.region(Region.of(region)); - } - taggingClient = clientBuilder.build(); + for (Object ruleObject : (List>) config.get("metrics")) { + Map yamlMetricRule = (Map) ruleObject; + MetricRule rule = new MetricRule(); + rules.add(rule); + if (!yamlMetricRule.containsKey("aws_namespace") + || !yamlMetricRule.containsKey("aws_metric_name")) { + throw new IllegalArgumentException("Must provide aws_namespace and aws_metric_name"); + } + rule.awsNamespace = (String) yamlMetricRule.get("aws_namespace"); + rule.awsMetricName = (String) yamlMetricRule.get("aws_metric_name"); + if (yamlMetricRule.containsKey("help")) { + rule.help = (String) yamlMetricRule.get("help"); + } + if (yamlMetricRule.containsKey("aws_dimensions")) { + rule.awsDimensions = (List) yamlMetricRule.get("aws_dimensions"); + } + if (yamlMetricRule.containsKey("aws_dimension_select") + && yamlMetricRule.containsKey("aws_dimension_select_regex")) { + throw new IllegalArgumentException( + "Must not provide aws_dimension_select and aws_dimension_select_regex at the same time"); + } + if (yamlMetricRule.containsKey("aws_dimension_select")) { + rule.awsDimensionSelect = + (Map>) yamlMetricRule.get("aws_dimension_select"); + } + if (yamlMetricRule.containsKey("aws_dimension_select_regex")) { + rule.awsDimensionSelectRegex = + (Map>) yamlMetricRule.get("aws_dimension_select_regex"); + } + if (yamlMetricRule.containsKey("aws_statistics")) { + rule.awsStatistics = new ArrayList<>(); + for (String statistic : (List) yamlMetricRule.get("aws_statistics")) { + rule.awsStatistics.add(Statistic.fromValue(statistic)); } - - if (!config.containsKey("metrics")) { - throw new IllegalArgumentException("Must provide metrics"); + } else if (!yamlMetricRule.containsKey("aws_extended_statistics")) { + rule.awsStatistics = new ArrayList<>(); + for (String statistic : + Arrays.asList("Sum", "SampleCount", "Minimum", "Maximum", "Average")) { + rule.awsStatistics.add(Statistic.fromValue(statistic)); } + } + if (yamlMetricRule.containsKey("aws_extended_statistics")) { + rule.awsExtendedStatistics = (List) yamlMetricRule.get("aws_extended_statistics"); + } + if (yamlMetricRule.containsKey("period_seconds")) { + rule.periodSeconds = ((Number) yamlMetricRule.get("period_seconds")).intValue(); + } else { + rule.periodSeconds = defaultPeriod; + } + if (yamlMetricRule.containsKey("range_seconds")) { + rule.rangeSeconds = ((Number) yamlMetricRule.get("range_seconds")).intValue(); + } else { + rule.rangeSeconds = defaultRange; + } + if (yamlMetricRule.containsKey("delay_seconds")) { + rule.delaySeconds = ((Number) yamlMetricRule.get("delay_seconds")).intValue(); + } else { + rule.delaySeconds = defaultDelay; + } + if (yamlMetricRule.containsKey("set_timestamp")) { + rule.cloudwatchTimestamp = (Boolean) yamlMetricRule.get("set_timestamp"); + } else { + rule.cloudwatchTimestamp = defaultCloudwatchTimestamp; + } - ArrayList rules = new ArrayList<>(); - - for (Object ruleObject : (List>) config.get("metrics")) { - Map yamlMetricRule = (Map)ruleObject; - MetricRule rule = new MetricRule(); - rules.add(rule); - if (!yamlMetricRule.containsKey("aws_namespace") || !yamlMetricRule.containsKey("aws_metric_name")) { - throw new IllegalArgumentException("Must provide aws_namespace and aws_metric_name"); - } - rule.awsNamespace = (String)yamlMetricRule.get("aws_namespace"); - rule.awsMetricName = (String)yamlMetricRule.get("aws_metric_name"); - if (yamlMetricRule.containsKey("help")) { - rule.help = (String)yamlMetricRule.get("help"); - } - if (yamlMetricRule.containsKey("aws_dimensions")) { - rule.awsDimensions = (List)yamlMetricRule.get("aws_dimensions"); - } - if (yamlMetricRule.containsKey("aws_dimension_select") && yamlMetricRule.containsKey("aws_dimension_select_regex")) { - throw new IllegalArgumentException("Must not provide aws_dimension_select and aws_dimension_select_regex at the same time"); - } - if (yamlMetricRule.containsKey("aws_dimension_select")) { - rule.awsDimensionSelect = (Map>)yamlMetricRule.get("aws_dimension_select"); - } - if (yamlMetricRule.containsKey("aws_dimension_select_regex")) { - rule.awsDimensionSelectRegex = (Map>)yamlMetricRule.get("aws_dimension_select_regex"); - } - if (yamlMetricRule.containsKey("aws_statistics")) { - rule.awsStatistics = new ArrayList<>(); - for (String statistic : (List)yamlMetricRule.get("aws_statistics")) { - rule.awsStatistics.add(Statistic.fromValue(statistic)); - } - } else if (!yamlMetricRule.containsKey("aws_extended_statistics")) { - rule.awsStatistics = new ArrayList<>(); - for (String statistic : Arrays.asList("Sum", "SampleCount", "Minimum", "Maximum", "Average")) { - rule.awsStatistics.add(Statistic.fromValue(statistic)); - } - } - if (yamlMetricRule.containsKey("aws_extended_statistics")) { - rule.awsExtendedStatistics = (List)yamlMetricRule.get("aws_extended_statistics"); - } - if (yamlMetricRule.containsKey("period_seconds")) { - rule.periodSeconds = ((Number)yamlMetricRule.get("period_seconds")).intValue(); - } else { - rule.periodSeconds = defaultPeriod; - } - if (yamlMetricRule.containsKey("range_seconds")) { - rule.rangeSeconds = ((Number)yamlMetricRule.get("range_seconds")).intValue(); - } else { - rule.rangeSeconds = defaultRange; - } - if (yamlMetricRule.containsKey("delay_seconds")) { - rule.delaySeconds = ((Number)yamlMetricRule.get("delay_seconds")).intValue(); - } else { - rule.delaySeconds = defaultDelay; - } - if (yamlMetricRule.containsKey("set_timestamp")) { - rule.cloudwatchTimestamp = (Boolean)yamlMetricRule.get("set_timestamp"); - } else { - rule.cloudwatchTimestamp = defaultCloudwatchTimestamp; - } - - if (yamlMetricRule.containsKey("aws_tag_select")) { - Map yamlAwsTagSelect = (Map) yamlMetricRule.get("aws_tag_select"); - if (!yamlAwsTagSelect.containsKey("resource_type_selection") || !yamlAwsTagSelect.containsKey("resource_id_dimension")) { - throw new IllegalArgumentException("Must provide resource_type_selection and resource_id_dimension"); - } - AWSTagSelect awsTagSelect = new AWSTagSelect(); - rule.awsTagSelect = awsTagSelect; - - awsTagSelect.resourceTypeSelection = (String)yamlAwsTagSelect.get("resource_type_selection"); - awsTagSelect.resourceIdDimension = (String)yamlAwsTagSelect.get("resource_id_dimension"); - - if (yamlAwsTagSelect.containsKey("tag_selections")) { - awsTagSelect.tagSelections = (Map>)yamlAwsTagSelect.get("tag_selections"); - } - } + if (yamlMetricRule.containsKey("aws_tag_select")) { + Map yamlAwsTagSelect = + (Map) yamlMetricRule.get("aws_tag_select"); + if (!yamlAwsTagSelect.containsKey("resource_type_selection") + || !yamlAwsTagSelect.containsKey("resource_id_dimension")) { + throw new IllegalArgumentException( + "Must provide resource_type_selection and resource_id_dimension"); } + AWSTagSelect awsTagSelect = new AWSTagSelect(); + rule.awsTagSelect = awsTagSelect; - loadConfig(rules, cloudWatchClient, taggingClient); - } + awsTagSelect.resourceTypeSelection = + (String) yamlAwsTagSelect.get("resource_type_selection"); + awsTagSelect.resourceIdDimension = (String) yamlAwsTagSelect.get("resource_id_dimension"); - private void loadConfig(ArrayList rules, CloudWatchClient cloudWatchClient, ResourceGroupsTaggingApiClient taggingClient) { - synchronized (activeConfig) { - activeConfig.cloudWatchClient = cloudWatchClient; - activeConfig.taggingClient = taggingClient; - activeConfig.rules = rules; + if (yamlAwsTagSelect.containsKey("tag_selections")) { + awsTagSelect.tagSelections = + (Map>) yamlAwsTagSelect.get("tag_selections"); } + } } - private AwsCredentialsProvider getRoleCredentialProvider(Map config) { - StsClient stsClient = StsClient.builder().region(Region.of((String) config.get("region"))).build(); - AssumeRoleRequest assumeRoleRequest = AssumeRoleRequest.builder() - .roleArn((String) config.get("role_arn")) - .roleSessionName("cloudwatch_exporter").build(); - return StsAssumeRoleCredentialsProvider.builder() - .stsClient(stsClient) - .refreshRequest(assumeRoleRequest).build(); + loadConfig(rules, cloudWatchClient, taggingClient); + } + + private void loadConfig( + ArrayList rules, + CloudWatchClient cloudWatchClient, + ResourceGroupsTaggingApiClient taggingClient) { + synchronized (activeConfig) { + activeConfig.cloudWatchClient = cloudWatchClient; + activeConfig.taggingClient = taggingClient; + activeConfig.rules = rules; + } + } + + private AwsCredentialsProvider getRoleCredentialProvider(Map config) { + StsClient stsClient = + StsClient.builder().region(Region.of((String) config.get("region"))).build(); + AssumeRoleRequest assumeRoleRequest = + AssumeRoleRequest.builder() + .roleArn((String) config.get("role_arn")) + .roleSessionName("cloudwatch_exporter") + .build(); + return StsAssumeRoleCredentialsProvider.builder() + .stsClient(stsClient) + .refreshRequest(assumeRoleRequest) + .build(); + } + + private List getResourceTagMappings( + MetricRule rule, ResourceGroupsTaggingApiClient taggingClient) { + if (rule.awsTagSelect == null) { + return Collections.emptyList(); } - private List getResourceTagMappings(MetricRule rule, ResourceGroupsTaggingApiClient taggingClient) { - if (rule.awsTagSelect == null) { - return Collections.emptyList(); - } - - List tagFilters = new ArrayList<>(); - if (rule.awsTagSelect.tagSelections != null) { - for (Map.Entry> entry : rule.awsTagSelect.tagSelections.entrySet()) { - tagFilters.add(TagFilter.builder().key(entry.getKey()).values(entry.getValue()).build()); - } + List tagFilters = new ArrayList<>(); + if (rule.awsTagSelect.tagSelections != null) { + for (Map.Entry> entry : rule.awsTagSelect.tagSelections.entrySet()) { + tagFilters.add(TagFilter.builder().key(entry.getKey()).values(entry.getValue()).build()); } - - List resourceTagMappings = new ArrayList<>(); - GetResourcesRequest.Builder requestBuilder = GetResourcesRequest.builder().tagFilters(tagFilters).resourceTypeFilters(rule.awsTagSelect.resourceTypeSelection); - String paginationToken = ""; - do { - requestBuilder.paginationToken(paginationToken); - - GetResourcesResponse response = taggingClient.getResources(requestBuilder.build()); - taggingApiRequests.labels("getResources", rule.awsTagSelect.resourceTypeSelection).inc(); - - resourceTagMappings.addAll(response.resourceTagMappingList()); - - paginationToken = response.paginationToken(); - } while (paginationToken != null && !paginationToken.isEmpty()); - - return resourceTagMappings; } - private List extractResourceIds(List resourceTagMappings) { - List resourceIds = new ArrayList<>(); - for (ResourceTagMapping resourceTagMapping : resourceTagMappings) { - resourceIds.add(extractResourceIdFromArn(resourceTagMapping.resourceARN())); - } - return resourceIds; - } - - private String extractResourceIdFromArn(String arn) { - // ARN parsing is based on https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html - String[] arnArray = arn.split(":"); - String resourceId = arnArray[arnArray.length - 1]; - if (resourceId.contains("/")) { - String[] resourceArray = resourceId.split("/", 2); - resourceId = resourceArray[resourceArray.length - 1]; - } - return resourceId; - } - - private List> getDimensions(MetricRule rule, List tagBasedResourceIds, CloudWatchClient cloudWatchClient) { - if ( - rule.awsDimensions != null && - rule.awsDimensionSelect != null && - !rule.awsDimensions.isEmpty() && - rule.awsDimensions.size() == rule.awsDimensionSelect.size() && - rule.awsDimensionSelect.keySet().containsAll(rule.awsDimensions) && - rule.awsTagSelect == null - ) { - // The full list of dimensions is known so no need to request it from cloudwatch. - return permuteDimensions(rule.awsDimensions, rule.awsDimensionSelect); - } else { - return listDimensions(rule, tagBasedResourceIds, cloudWatchClient); + List resourceTagMappings = new ArrayList<>(); + GetResourcesRequest.Builder requestBuilder = + GetResourcesRequest.builder() + .tagFilters(tagFilters) + .resourceTypeFilters(rule.awsTagSelect.resourceTypeSelection); + String paginationToken = ""; + do { + requestBuilder.paginationToken(paginationToken); + + GetResourcesResponse response = taggingClient.getResources(requestBuilder.build()); + taggingApiRequests.labels("getResources", rule.awsTagSelect.resourceTypeSelection).inc(); + + resourceTagMappings.addAll(response.resourceTagMappingList()); + + paginationToken = response.paginationToken(); + } while (paginationToken != null && !paginationToken.isEmpty()); + + return resourceTagMappings; + } + + private List extractResourceIds(List resourceTagMappings) { + List resourceIds = new ArrayList<>(); + for (ResourceTagMapping resourceTagMapping : resourceTagMappings) { + resourceIds.add(extractResourceIdFromArn(resourceTagMapping.resourceARN())); + } + return resourceIds; + } + + private String extractResourceIdFromArn(String arn) { + // ARN parsing is based on + // https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html + String[] arnArray = arn.split(":"); + String resourceId = arnArray[arnArray.length - 1]; + if (resourceId.contains("/")) { + String[] resourceArray = resourceId.split("/", 2); + resourceId = resourceArray[resourceArray.length - 1]; + } + return resourceId; + } + + private List> getDimensions( + MetricRule rule, List tagBasedResourceIds, CloudWatchClient cloudWatchClient) { + if (rule.awsDimensions != null + && rule.awsDimensionSelect != null + && !rule.awsDimensions.isEmpty() + && rule.awsDimensions.size() == rule.awsDimensionSelect.size() + && rule.awsDimensionSelect.keySet().containsAll(rule.awsDimensions) + && rule.awsTagSelect == null) { + // The full list of dimensions is known so no need to request it from cloudwatch. + return permuteDimensions(rule.awsDimensions, rule.awsDimensionSelect); + } else { + return listDimensions(rule, tagBasedResourceIds, cloudWatchClient); + } + } + + private List> permuteDimensions( + List dimensions, Map> dimensionValues) { + ArrayList> result = new ArrayList<>(); + + if (dimensions.isEmpty()) { + result.add(new ArrayList<>()); + } else { + List dimensionsCopy = new ArrayList<>(dimensions); + String dimensionName = dimensionsCopy.remove(dimensionsCopy.size() - 1); + for (List permutation : permuteDimensions(dimensionsCopy, dimensionValues)) { + for (String dimensionValue : dimensionValues.get(dimensionName)) { + Dimension.Builder dimensionBuilder = Dimension.builder(); + dimensionBuilder.value(dimensionValue); + dimensionBuilder.name(dimensionName); + ArrayList permutationCopy = new ArrayList<>(permutation); + permutationCopy.add(dimensionBuilder.build()); + result.add(permutationCopy); } + } } - private List> permuteDimensions(List dimensions, Map> dimensionValues) { - ArrayList> result = new ArrayList<>(); - - if (dimensions.isEmpty()) { - result.add(new ArrayList<>()); - } else { - List dimensionsCopy = new ArrayList<>(dimensions); - String dimensionName = dimensionsCopy.remove(dimensionsCopy.size() - 1); - for (List permutation : permuteDimensions(dimensionsCopy, dimensionValues)) { - for (String dimensionValue : dimensionValues.get(dimensionName)) { - Dimension.Builder dimensionBuilder = Dimension.builder(); - dimensionBuilder.value(dimensionValue); - dimensionBuilder.name(dimensionName); - ArrayList permutationCopy = new ArrayList<>(permutation); - permutationCopy.add(dimensionBuilder.build()); - result.add(permutationCopy); - } - } - } + return result; + } - return result; + private List> listDimensions( + MetricRule rule, List tagBasedResourceIds, CloudWatchClient cloudWatchClient) { + List> dimensions = new ArrayList<>(); + if (rule.awsDimensions == null) { + dimensions.add(new ArrayList<>()); + return dimensions; } - private List> listDimensions(MetricRule rule, List tagBasedResourceIds, CloudWatchClient cloudWatchClient) { - List> dimensions = new ArrayList<>(); - if (rule.awsDimensions == null) { - dimensions.add(new ArrayList<>()); - return dimensions; - } - - ListMetricsRequest.Builder requestBuilder = ListMetricsRequest.builder(); - requestBuilder.namespace(rule.awsNamespace); - requestBuilder.metricName(rule.awsMetricName); - - // 10800 seconds is 3 hours, this setting causes metrics older than 3 hours to not be listed - if (rule.rangeSeconds < 10800) { - requestBuilder.recentlyActive("PT3H"); - } - - List dimensionFilters = new ArrayList<>(); - for (String dimension: rule.awsDimensions) { - dimensionFilters.add(DimensionFilter.builder().name(dimension).build()); - } - requestBuilder.dimensions(dimensionFilters); + ListMetricsRequest.Builder requestBuilder = ListMetricsRequest.builder(); + requestBuilder.namespace(rule.awsNamespace); + requestBuilder.metricName(rule.awsMetricName); - String nextToken = null; - do { - requestBuilder.nextToken(nextToken); - ListMetricsResponse response = cloudWatchClient.listMetrics(requestBuilder.build()); - cloudwatchRequests.labels("listMetrics", rule.awsNamespace).inc(); - for (Metric metric: response.metrics()) { - if (metric.dimensions().size() != dimensionFilters.size()) { - // AWS returns all the metrics with dimensions beyond the ones we ask for, - // so filter them out. - continue; - } - if (useMetric(rule, tagBasedResourceIds, metric)) { - dimensions.add(metric.dimensions()); - } - } - nextToken = response.nextToken(); - } while (nextToken != null); - - return dimensions; + // 10800 seconds is 3 hours, this setting causes metrics older than 3 hours to not be listed + if (rule.rangeSeconds < 10800) { + requestBuilder.recentlyActive("PT3H"); } - /** - * Check if a metric should be used according to `aws_dimension_select`, `aws_dimension_select_regex` and dynamic `aws_tag_select` - */ - private boolean useMetric(MetricRule rule, List tagBasedResourceIds, Metric metric) { - if (rule.awsDimensionSelect != null && !metricsIsInAwsDimensionSelect(rule, metric)) { - return false; - } - if (rule.awsDimensionSelectRegex != null && !metricIsInAwsDimensionSelectRegex(rule, metric)) { - return false; - } - if (rule.awsTagSelect != null && !metricIsInAwsTagSelect(rule, tagBasedResourceIds, metric)) { - return false; - } - return true; + List dimensionFilters = new ArrayList<>(); + for (String dimension : rule.awsDimensions) { + dimensionFilters.add(DimensionFilter.builder().name(dimension).build()); } + requestBuilder.dimensions(dimensionFilters); - /** - * Check if a metric is matched in `aws_dimension_select` - */ - private boolean metricsIsInAwsDimensionSelect(MetricRule rule, Metric metric) { - Set dimensionSelectKeys = rule.awsDimensionSelect.keySet(); - for (Dimension dimension : metric.dimensions()) { - String dimensionName = dimension.name(); - String dimensionValue = dimension.value(); - if (dimensionSelectKeys.contains(dimensionName)) { - List allowedDimensionValues = rule.awsDimensionSelect.get(dimensionName); - if (!allowedDimensionValues.contains(dimensionValue)) { - return false; - } + String nextToken = null; + do { + requestBuilder.nextToken(nextToken); + ListMetricsResponse response = cloudWatchClient.listMetrics(requestBuilder.build()); + cloudwatchRequests.labels("listMetrics", rule.awsNamespace).inc(); + for (Metric metric : response.metrics()) { + if (metric.dimensions().size() != dimensionFilters.size()) { + // AWS returns all the metrics with dimensions beyond the ones we ask for, + // so filter them out. + continue; } - } - return true; - } - - /** - * Check if a metric is matched in `aws_dimension_select_regex` - */ - private boolean metricIsInAwsDimensionSelectRegex(MetricRule rule, Metric metric) { - Set dimensionSelectRegexKeys = rule.awsDimensionSelectRegex.keySet(); - for (Dimension dimension : metric.dimensions()) { - String dimensionName = dimension.name(); - String dimensionValue = dimension.value(); - if (dimensionSelectRegexKeys.contains(dimensionName)) { - List allowedDimensionValues = rule.awsDimensionSelectRegex.get(dimensionName); - if (!regexListMatch(allowedDimensionValues, dimensionValue)) { - return false; - } + if (useMetric(rule, tagBasedResourceIds, metric)) { + dimensions.add(metric.dimensions()); } } - return true; + nextToken = response.nextToken(); + } while (nextToken != null); + + return dimensions; + } + + /** + * Check if a metric should be used according to `aws_dimension_select`, + * `aws_dimension_select_regex` and dynamic `aws_tag_select` + */ + private boolean useMetric(MetricRule rule, List tagBasedResourceIds, Metric metric) { + if (rule.awsDimensionSelect != null && !metricsIsInAwsDimensionSelect(rule, metric)) { + return false; } - - /** - * Check if any regex string in a list matches a given input value - */ - protected static boolean regexListMatch(List regexList, String input) { - for (String regex: regexList) { - if (Pattern.matches(regex, input)) { - return true; - } - } + if (rule.awsDimensionSelectRegex != null && !metricIsInAwsDimensionSelectRegex(rule, metric)) { return false; } - - /** - * Check if a metric is matched in `aws_tag_select` - */ - private boolean metricIsInAwsTagSelect(MetricRule rule, List tagBasedResourceIds, Metric metric) { - if (rule.awsTagSelect.tagSelections == null) { - return true; - } - for (Dimension dimension : metric.dimensions()) { - String dimensionName = dimension.name(); - String dimensionValue = dimension.value(); - if (rule.awsTagSelect.resourceIdDimension.equals(dimensionName) && !tagBasedResourceIds.contains(dimensionValue)) { - return false; + if (rule.awsTagSelect != null && !metricIsInAwsTagSelect(rule, tagBasedResourceIds, metric)) { + return false; + } + return true; + } + + /** Check if a metric is matched in `aws_dimension_select` */ + private boolean metricsIsInAwsDimensionSelect(MetricRule rule, Metric metric) { + Set dimensionSelectKeys = rule.awsDimensionSelect.keySet(); + for (Dimension dimension : metric.dimensions()) { + String dimensionName = dimension.name(); + String dimensionValue = dimension.value(); + if (dimensionSelectKeys.contains(dimensionName)) { + List allowedDimensionValues = rule.awsDimensionSelect.get(dimensionName); + if (!allowedDimensionValues.contains(dimensionValue)) { + return false; } } - return true; } - - private Datapoint getNewestDatapoint(java.util.List datapoints) { - Datapoint newest = null; - for (Datapoint d: datapoints) { - if (newest == null || newest.timestamp().isBefore(d.timestamp())) { - newest = d; + return true; + } + + /** Check if a metric is matched in `aws_dimension_select_regex` */ + private boolean metricIsInAwsDimensionSelectRegex(MetricRule rule, Metric metric) { + Set dimensionSelectRegexKeys = rule.awsDimensionSelectRegex.keySet(); + for (Dimension dimension : metric.dimensions()) { + String dimensionName = dimension.name(); + String dimensionValue = dimension.value(); + if (dimensionSelectRegexKeys.contains(dimensionName)) { + List allowedDimensionValues = rule.awsDimensionSelectRegex.get(dimensionName); + if (!regexListMatch(allowedDimensionValues, dimensionValue)) { + return false; } } - return newest; } + return true; + } - private String toSnakeCase(String str) { - return str.replaceAll("([a-z0-9])([A-Z])", "$1_$2").toLowerCase(); + /** Check if any regex string in a list matches a given input value */ + protected static boolean regexListMatch(List regexList, String input) { + for (String regex : regexList) { + if (Pattern.matches(regex, input)) { + return true; + } } + return false; + } - private String safeName(String s) { - // Change invalid chars to underscore, and merge underscores. - return s.replaceAll("[^a-zA-Z0-9:_]", "_").replaceAll("__+", "_"); + /** Check if a metric is matched in `aws_tag_select` */ + private boolean metricIsInAwsTagSelect( + MetricRule rule, List tagBasedResourceIds, Metric metric) { + if (rule.awsTagSelect.tagSelections == null) { + return true; } - - private String safeLabelName(String s) { - // Change invalid chars to underscore, and merge underscores. - return s.replaceAll("[^a-zA-Z0-9_]", "_").replaceAll("__+", "_"); + for (Dimension dimension : metric.dimensions()) { + String dimensionName = dimension.name(); + String dimensionValue = dimension.value(); + if (rule.awsTagSelect.resourceIdDimension.equals(dimensionName) + && !tagBasedResourceIds.contains(dimensionValue)) { + return false; + } } + return true; + } - private String help(MetricRule rule, String unit, String statistic) { - if (rule.help != null) { - return rule.help; + private Datapoint getNewestDatapoint(java.util.List datapoints) { + Datapoint newest = null; + for (Datapoint d : datapoints) { + if (newest == null || newest.timestamp().isBefore(d.timestamp())) { + newest = d; } - return "CloudWatch metric " + rule.awsNamespace + " " + rule.awsMetricName - + " Dimensions: " + rule.awsDimensions + " Statistic: " + statistic - + " Unit: " + unit; } + return newest; + } + + private String toSnakeCase(String str) { + return str.replaceAll("([a-z0-9])([A-Z])", "$1_$2").toLowerCase(); + } + + private String safeName(String s) { + // Change invalid chars to underscore, and merge underscores. + return s.replaceAll("[^a-zA-Z0-9:_]", "_").replaceAll("__+", "_"); + } + + private String safeLabelName(String s) { + // Change invalid chars to underscore, and merge underscores. + return s.replaceAll("[^a-zA-Z0-9_]", "_").replaceAll("__+", "_"); + } + + private String help(MetricRule rule, String unit, String statistic) { + if (rule.help != null) { + return rule.help; + } + return "CloudWatch metric " + + rule.awsNamespace + + " " + + rule.awsMetricName + + " Dimensions: " + + rule.awsDimensions + + " Statistic: " + + statistic + + " Unit: " + + unit; + } + + private void scrape(List mfs) { + ActiveConfig config = new ActiveConfig(activeConfig); + Set publishedResourceInfo = new HashSet<>(); + + long start = System.currentTimeMillis(); + List infoSamples = new ArrayList<>(); + for (MetricRule rule : config.rules) { + Date startDate = new Date(start - 1000 * rule.delaySeconds); + Date endDate = new Date(start - 1000 * (rule.delaySeconds + rule.rangeSeconds)); + GetMetricStatisticsRequest.Builder requestBuilder = GetMetricStatisticsRequest.builder(); + requestBuilder.namespace(rule.awsNamespace); + requestBuilder.metricName(rule.awsMetricName); + requestBuilder.statistics(rule.awsStatistics); + requestBuilder.extendedStatistics(rule.awsExtendedStatistics); + requestBuilder.endTime(startDate.toInstant()); + requestBuilder.startTime(endDate.toInstant()); + requestBuilder.period(rule.periodSeconds); + + String baseName = + safeName(rule.awsNamespace.toLowerCase() + "_" + toSnakeCase(rule.awsMetricName)); + String jobName = safeName(rule.awsNamespace.toLowerCase()); + List sumSamples = new ArrayList<>(); + List sampleCountSamples = new ArrayList<>(); + List minimumSamples = new ArrayList<>(); + List maximumSamples = new ArrayList<>(); + List averageSamples = new ArrayList<>(); + HashMap> extendedSamples = new HashMap<>(); + + String unit = null; + + if (rule.awsNamespace.equals("AWS/DynamoDB") + && rule.awsDimensions != null + && rule.awsDimensions.contains("GlobalSecondaryIndexName") + && brokenDynamoMetrics.contains(rule.awsMetricName)) { + baseName += "_index"; + } - private void scrape(List mfs) { - ActiveConfig config = new ActiveConfig(activeConfig); - Set publishedResourceInfo = new HashSet<>(); - - long start = System.currentTimeMillis(); - List infoSamples = new ArrayList<>(); - for (MetricRule rule: config.rules) { - Date startDate = new Date(start - 1000 * rule.delaySeconds); - Date endDate = new Date(start - 1000 * (rule.delaySeconds + rule.rangeSeconds)); - GetMetricStatisticsRequest.Builder requestBuilder = GetMetricStatisticsRequest.builder(); - requestBuilder.namespace(rule.awsNamespace); - requestBuilder.metricName(rule.awsMetricName); - requestBuilder.statistics(rule.awsStatistics); - requestBuilder.extendedStatistics(rule.awsExtendedStatistics); - requestBuilder.endTime(startDate.toInstant()); - requestBuilder.startTime(endDate.toInstant()); - requestBuilder.period(rule.periodSeconds); - - String baseName = safeName(rule.awsNamespace.toLowerCase() + "_" + toSnakeCase(rule.awsMetricName)); - String jobName = safeName(rule.awsNamespace.toLowerCase()); - List sumSamples = new ArrayList<>(); - List sampleCountSamples = new ArrayList<>(); - List minimumSamples = new ArrayList<>(); - List maximumSamples = new ArrayList<>(); - List averageSamples = new ArrayList<>(); - HashMap> extendedSamples = new HashMap<>(); + List resourceTagMappings = + getResourceTagMappings(rule, config.taggingClient); + List tagBasedResourceIds = extractResourceIds(resourceTagMappings); - String unit = null; + for (List dimensions : + getDimensions(rule, tagBasedResourceIds, config.cloudWatchClient)) { + requestBuilder.dimensions(dimensions); - if (rule.awsNamespace.equals("AWS/DynamoDB") - && rule.awsDimensions != null - && rule.awsDimensions.contains("GlobalSecondaryIndexName") - && brokenDynamoMetrics.contains(rule.awsMetricName)) { - baseName += "_index"; + GetMetricStatisticsResponse response = + config.cloudWatchClient.getMetricStatistics(requestBuilder.build()); + cloudwatchRequests.labels("getMetricStatistics", rule.awsNamespace).inc(); + Datapoint dp = getNewestDatapoint(response.datapoints()); + if (dp == null) { + continue; } - - List resourceTagMappings = getResourceTagMappings(rule, config.taggingClient); - List tagBasedResourceIds = extractResourceIds(resourceTagMappings); - - for (List dimensions: getDimensions(rule, tagBasedResourceIds, config.cloudWatchClient)) { - requestBuilder.dimensions(dimensions); - - GetMetricStatisticsResponse response = config.cloudWatchClient.getMetricStatistics(requestBuilder.build()); - cloudwatchRequests.labels("getMetricStatistics", rule.awsNamespace).inc(); - Datapoint dp = getNewestDatapoint(response.datapoints()); - if (dp == null) { - continue; - } - unit = dp.unitAsString(); - - List labelNames = new ArrayList<>(); - List labelValues = new ArrayList<>(); - labelNames.add("job"); - labelValues.add(jobName); - labelNames.add("instance"); - labelValues.add(""); - for (Dimension d: dimensions) { - labelNames.add(safeLabelName(toSnakeCase(d.name()))); - labelValues.add(d.value()); - } - - Long timestamp = null; - if (rule.cloudwatchTimestamp) { - timestamp = dp.timestamp().toEpochMilli(); - } - - if (dp.sum() != null) { - sumSamples.add(new MetricFamilySamples.Sample( - baseName + "_sum", labelNames, labelValues, dp.sum(), timestamp)); - } - if (dp.sampleCount() != null) { - sampleCountSamples.add(new MetricFamilySamples.Sample( - baseName + "_sample_count", labelNames, labelValues, dp.sampleCount(), timestamp)); - } - if (dp.minimum() != null) { - minimumSamples.add(new MetricFamilySamples.Sample( - baseName + "_minimum", labelNames, labelValues, dp.minimum(), timestamp)); - } - if (dp.maximum() != null) { - maximumSamples.add(new MetricFamilySamples.Sample( - baseName + "_maximum",labelNames, labelValues, dp.maximum(), timestamp)); - } - if (dp.average() != null) { - averageSamples.add(new MetricFamilySamples.Sample( - baseName + "_average", labelNames, labelValues, dp.average(), timestamp)); - } - if (dp.extendedStatistics() != null) { - for (Map.Entry entry : dp.extendedStatistics().entrySet()) { - ArrayList samples = extendedSamples.get(entry.getKey()); - if (samples == null) { - samples = new ArrayList<>(); - extendedSamples.put(entry.getKey(), samples); - } - samples.add(new MetricFamilySamples.Sample( - baseName + "_" + safeName(toSnakeCase(entry.getKey())), labelNames, labelValues, entry.getValue(), timestamp)); - } - } + unit = dp.unitAsString(); + + List labelNames = new ArrayList<>(); + List labelValues = new ArrayList<>(); + labelNames.add("job"); + labelValues.add(jobName); + labelNames.add("instance"); + labelValues.add(""); + for (Dimension d : dimensions) { + labelNames.add(safeLabelName(toSnakeCase(d.name()))); + labelValues.add(d.value()); } - if (!sumSamples.isEmpty()) { - mfs.add(new MetricFamilySamples(baseName + "_sum", Type.GAUGE, help(rule, unit, "Sum"), sumSamples)); + Long timestamp = null; + if (rule.cloudwatchTimestamp) { + timestamp = dp.timestamp().toEpochMilli(); } - if (!sampleCountSamples.isEmpty()) { - mfs.add(new MetricFamilySamples(baseName + "_sample_count", Type.GAUGE, help(rule, unit, "SampleCount"), sampleCountSamples)); + + if (dp.sum() != null) { + sumSamples.add( + new MetricFamilySamples.Sample( + baseName + "_sum", labelNames, labelValues, dp.sum(), timestamp)); } - if (!minimumSamples.isEmpty()) { - mfs.add(new MetricFamilySamples(baseName + "_minimum", Type.GAUGE, help(rule, unit, "Minimum"), minimumSamples)); + if (dp.sampleCount() != null) { + sampleCountSamples.add( + new MetricFamilySamples.Sample( + baseName + "_sample_count", + labelNames, + labelValues, + dp.sampleCount(), + timestamp)); } - if (!maximumSamples.isEmpty()) { - mfs.add(new MetricFamilySamples(baseName + "_maximum", Type.GAUGE, help(rule, unit, "Maximum"), maximumSamples)); + if (dp.minimum() != null) { + minimumSamples.add( + new MetricFamilySamples.Sample( + baseName + "_minimum", labelNames, labelValues, dp.minimum(), timestamp)); } - if (!averageSamples.isEmpty()) { - mfs.add(new MetricFamilySamples(baseName + "_average", Type.GAUGE, help(rule, unit, "Average"), averageSamples)); + if (dp.maximum() != null) { + maximumSamples.add( + new MetricFamilySamples.Sample( + baseName + "_maximum", labelNames, labelValues, dp.maximum(), timestamp)); } - for (Map.Entry> entry : extendedSamples.entrySet()) { - mfs.add(new MetricFamilySamples(baseName + "_" + safeName(toSnakeCase(entry.getKey())), Type.GAUGE, help(rule, unit, entry.getKey()), entry.getValue())); + if (dp.average() != null) { + averageSamples.add( + new MetricFamilySamples.Sample( + baseName + "_average", labelNames, labelValues, dp.average(), timestamp)); } - - // Add the "aws_resource_info" metric for existing tag mappings - for (ResourceTagMapping resourceTagMapping : resourceTagMappings) { - if (!publishedResourceInfo.contains(resourceTagMapping.resourceARN())) { - List labelNames = new ArrayList<>(); - List labelValues = new ArrayList<>(); - labelNames.add("job"); - labelValues.add(jobName); - labelNames.add("instance"); - labelValues.add(""); - labelNames.add("arn"); - labelValues.add(resourceTagMapping.resourceARN()); - labelNames.add(safeLabelName(toSnakeCase(rule.awsTagSelect.resourceIdDimension))); - labelValues.add(extractResourceIdFromArn(resourceTagMapping.resourceARN())); - for (Tag tag: resourceTagMapping.tags()) { - // Avoid potential collision between resource tags and other metric labels by adding the "tag_" prefix - // The AWS tags are case sensitive, so to avoid loosing information and label collisions, tag keys are not snaked cased - labelNames.add("tag_" + safeLabelName(tag.key())); - labelValues.add(tag.value()); + if (dp.extendedStatistics() != null) { + for (Map.Entry entry : dp.extendedStatistics().entrySet()) { + ArrayList samples = extendedSamples.get(entry.getKey()); + if (samples == null) { + samples = new ArrayList<>(); + extendedSamples.put(entry.getKey(), samples); } - - infoSamples.add(new MetricFamilySamples.Sample("aws_resource_info", labelNames, labelValues, 1)); - - publishedResourceInfo.add(resourceTagMapping.resourceARN()); + samples.add( + new MetricFamilySamples.Sample( + baseName + "_" + safeName(toSnakeCase(entry.getKey())), + labelNames, + labelValues, + entry.getValue(), + timestamp)); } } } - mfs.add(new MetricFamilySamples("aws_resource_info", Type.GAUGE, "AWS information available for resource", infoSamples)); - } - public List collect() { - long start = System.nanoTime(); - double error = 0; - List mfs = new ArrayList<>(); - try { - scrape(mfs); - } catch (Exception e) { - error = 1; - LOGGER.log(Level.WARNING, "CloudWatch scrape failed", e); + if (!sumSamples.isEmpty()) { + mfs.add( + new MetricFamilySamples( + baseName + "_sum", Type.GAUGE, help(rule, unit, "Sum"), sumSamples)); + } + if (!sampleCountSamples.isEmpty()) { + mfs.add( + new MetricFamilySamples( + baseName + "_sample_count", + Type.GAUGE, + help(rule, unit, "SampleCount"), + sampleCountSamples)); + } + if (!minimumSamples.isEmpty()) { + mfs.add( + new MetricFamilySamples( + baseName + "_minimum", Type.GAUGE, help(rule, unit, "Minimum"), minimumSamples)); + } + if (!maximumSamples.isEmpty()) { + mfs.add( + new MetricFamilySamples( + baseName + "_maximum", Type.GAUGE, help(rule, unit, "Maximum"), maximumSamples)); + } + if (!averageSamples.isEmpty()) { + mfs.add( + new MetricFamilySamples( + baseName + "_average", Type.GAUGE, help(rule, unit, "Average"), averageSamples)); + } + for (Map.Entry> entry : + extendedSamples.entrySet()) { + mfs.add( + new MetricFamilySamples( + baseName + "_" + safeName(toSnakeCase(entry.getKey())), + Type.GAUGE, + help(rule, unit, entry.getKey()), + entry.getValue())); } - List samples = new ArrayList<>(); - samples.add(new MetricFamilySamples.Sample( - "cloudwatch_exporter_scrape_duration_seconds", new ArrayList<>(), new ArrayList<>(), (System.nanoTime() - start) / 1.0E9)); - mfs.add(new MetricFamilySamples("cloudwatch_exporter_scrape_duration_seconds", Type.GAUGE, "Time this CloudWatch scrape took, in seconds.", samples)); - samples = new ArrayList<>(); - samples.add(new MetricFamilySamples.Sample( - "cloudwatch_exporter_scrape_error", new ArrayList<>(), new ArrayList<>(), error)); - mfs.add(new MetricFamilySamples("cloudwatch_exporter_scrape_error", Type.GAUGE, "Non-zero if this scrape failed.", samples)); - return mfs; - } + // Add the "aws_resource_info" metric for existing tag mappings + for (ResourceTagMapping resourceTagMapping : resourceTagMappings) { + if (!publishedResourceInfo.contains(resourceTagMapping.resourceARN())) { + List labelNames = new ArrayList<>(); + List labelValues = new ArrayList<>(); + labelNames.add("job"); + labelValues.add(jobName); + labelNames.add("instance"); + labelValues.add(""); + labelNames.add("arn"); + labelValues.add(resourceTagMapping.resourceARN()); + labelNames.add(safeLabelName(toSnakeCase(rule.awsTagSelect.resourceIdDimension))); + labelValues.add(extractResourceIdFromArn(resourceTagMapping.resourceARN())); + for (Tag tag : resourceTagMapping.tags()) { + // Avoid potential collision between resource tags and other metric labels by adding the + // "tag_" prefix + // The AWS tags are case sensitive, so to avoid loosing information and label + // collisions, tag keys are not snaked cased + labelNames.add("tag_" + safeLabelName(tag.key())); + labelValues.add(tag.value()); + } - /** - * Convenience function to run standalone. - */ - public static void main(String[] args) { - String region = "eu-west-1"; - if (args.length > 0) { - region = args[0]; - } - new BuildInfoCollector().register(); - CloudWatchCollector jc = new CloudWatchCollector(("{" - + "`region`: `" + region + "`," - + "`metrics`: [{`aws_namespace`: `AWS/ELB`, `aws_metric_name`: `RequestCount`, `aws_dimensions`: [`AvailabilityZone`, `LoadBalancerName`]}] ," - + "}").replace('`', '"')); - for(MetricFamilySamples mfs : jc.collect()) { - System.out.println(mfs); + infoSamples.add( + new MetricFamilySamples.Sample("aws_resource_info", labelNames, labelValues, 1)); + + publishedResourceInfo.add(resourceTagMapping.resourceARN()); + } } } + mfs.add( + new MetricFamilySamples( + "aws_resource_info", + Type.GAUGE, + "AWS information available for resource", + infoSamples)); + } + + public List collect() { + long start = System.nanoTime(); + double error = 0; + List mfs = new ArrayList<>(); + try { + scrape(mfs); + } catch (Exception e) { + error = 1; + LOGGER.log(Level.WARNING, "CloudWatch scrape failed", e); + } + List samples = new ArrayList<>(); + samples.add( + new MetricFamilySamples.Sample( + "cloudwatch_exporter_scrape_duration_seconds", + new ArrayList<>(), + new ArrayList<>(), + (System.nanoTime() - start) / 1.0E9)); + mfs.add( + new MetricFamilySamples( + "cloudwatch_exporter_scrape_duration_seconds", + Type.GAUGE, + "Time this CloudWatch scrape took, in seconds.", + samples)); + + samples = new ArrayList<>(); + samples.add( + new MetricFamilySamples.Sample( + "cloudwatch_exporter_scrape_error", new ArrayList<>(), new ArrayList<>(), error)); + mfs.add( + new MetricFamilySamples( + "cloudwatch_exporter_scrape_error", + Type.GAUGE, + "Non-zero if this scrape failed.", + samples)); + return mfs; + } + + /** Convenience function to run standalone. */ + public static void main(String[] args) { + String region = "eu-west-1"; + if (args.length > 0) { + region = args[0]; + } + new BuildInfoCollector().register(); + CloudWatchCollector jc = + new CloudWatchCollector( + ("{" + + "`region`: `" + + region + + "`," + + "`metrics`: [{`aws_namespace`: `AWS/ELB`, `aws_metric_name`: `RequestCount`, `aws_dimensions`: [`AvailabilityZone`, `LoadBalancerName`]}] ," + + "}") + .replace('`', '"')); + for (MetricFamilySamples mfs : jc.collect()) { + System.out.println(mfs); + } + } } diff --git a/src/main/java/io/prometheus/cloudwatch/DynamicReloadServlet.java b/src/main/java/io/prometheus/cloudwatch/DynamicReloadServlet.java index f47cf225..54038f4a 100644 --- a/src/main/java/io/prometheus/cloudwatch/DynamicReloadServlet.java +++ b/src/main/java/io/prometheus/cloudwatch/DynamicReloadServlet.java @@ -1,52 +1,54 @@ package io.prometheus.cloudwatch; +import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.IOException; public class DynamicReloadServlet extends HttpServlet { - private static final long serialVersionUID = 9078784531819993933L; - private final CloudWatchCollector collector; + private static final long serialVersionUID = 9078784531819993933L; + private final CloudWatchCollector collector; - public DynamicReloadServlet(CloudWatchCollector collector) { - this.collector = collector; - } + public DynamicReloadServlet(CloudWatchCollector collector) { + this.collector = collector; + } - static final String CONTENT_TYPE = "text/plain"; + static final String CONTENT_TYPE = "text/plain"; - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); - resp.setContentType(CONTENT_TYPE); - try { - resp.getWriter().print("Only POST requests allowed"); - } catch (IOException e) { - // Ignored - } + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); + resp.setContentType(CONTENT_TYPE); + try { + resp.getWriter().print("Only POST requests allowed"); + } catch (IOException e) { + // Ignored } + } - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - try { - collector.reloadConfig(); - } catch (IOException e) { - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - resp.setContentType(CONTENT_TYPE); - try { - resp.getWriter().print("Reloading config failed"); - } catch (IOException ee) { - // Ignored - } - return; - } + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + try { + collector.reloadConfig(); + } catch (IOException e) { + resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + resp.setContentType(CONTENT_TYPE); + try { + resp.getWriter().print("Reloading config failed"); + } catch (IOException ee) { + // Ignored + } + return; + } - resp.setContentType(CONTENT_TYPE); - try { - resp.getWriter().print("OK"); - } catch (IOException e) { - // Ignored - } + resp.setContentType(CONTENT_TYPE); + try { + resp.getWriter().print("OK"); + } catch (IOException e) { + // Ignored } + } } diff --git a/src/main/java/io/prometheus/cloudwatch/HealthServlet.java b/src/main/java/io/prometheus/cloudwatch/HealthServlet.java index 9dafcdef..6b4bb814 100644 --- a/src/main/java/io/prometheus/cloudwatch/HealthServlet.java +++ b/src/main/java/io/prometheus/cloudwatch/HealthServlet.java @@ -1,17 +1,18 @@ package io.prometheus.cloudwatch; +import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.IOException; public class HealthServlet extends HttpServlet { - private static final long serialVersionUID = 5543118274931292897L; + private static final long serialVersionUID = 5543118274931292897L; - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - resp.setContentType("text/plain"); - resp.getWriter().print("ok"); - } + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.setContentType("text/plain"); + resp.getWriter().print("ok"); + } } diff --git a/src/main/java/io/prometheus/cloudwatch/HomePageServlet.java b/src/main/java/io/prometheus/cloudwatch/HomePageServlet.java index 7d71cd36..db34f8c3 100644 --- a/src/main/java/io/prometheus/cloudwatch/HomePageServlet.java +++ b/src/main/java/io/prometheus/cloudwatch/HomePageServlet.java @@ -1,27 +1,30 @@ package io.prometheus.cloudwatch; +import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.IOException; public class HomePageServlet extends HttpServlet { - private static final long serialVersionUID = 3239704246954810347L; + private static final long serialVersionUID = 3239704246954810347L; - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - resp.setContentType("text/html"); - try { - resp.getWriter().print("\n" - + "CloudWatch Exporter\n" - + "\n" - + "

CloudWatch Exporter

\n" - + "

Metrics

\n" - + "\n" - + ""); - } catch (IOException e) { - // Ignored - } + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.setContentType("text/html"); + try { + resp.getWriter() + .print( + "\n" + + "CloudWatch Exporter\n" + + "\n" + + "

CloudWatch Exporter

\n" + + "

Metrics

\n" + + "\n" + + ""); + } catch (IOException e) { + // Ignored } + } } diff --git a/src/main/java/io/prometheus/cloudwatch/ReloadSignalHandler.java b/src/main/java/io/prometheus/cloudwatch/ReloadSignalHandler.java index 988e4601..8aedae3a 100644 --- a/src/main/java/io/prometheus/cloudwatch/ReloadSignalHandler.java +++ b/src/main/java/io/prometheus/cloudwatch/ReloadSignalHandler.java @@ -6,17 +6,19 @@ import sun.misc.SignalHandler; class ReloadSignalHandler { - private static final Logger LOGGER = Logger.getLogger(CloudWatchCollector.class.getName()); + private static final Logger LOGGER = Logger.getLogger(CloudWatchCollector.class.getName()); - protected static void start(final CloudWatchCollector collector) { - Signal.handle(new Signal("HUP"), new SignalHandler() { - public void handle(Signal signal) { - try { - collector.reloadConfig(); - } catch (Exception e) { - LOGGER.log(Level.WARNING, "Configuration reload failed", e); - } + protected static void start(final CloudWatchCollector collector) { + Signal.handle( + new Signal("HUP"), + new SignalHandler() { + public void handle(Signal signal) { + try { + collector.reloadConfig(); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Configuration reload failed", e); } + } }); - } + } } diff --git a/src/main/java/io/prometheus/cloudwatch/WebServer.java b/src/main/java/io/prometheus/cloudwatch/WebServer.java index 02bd5fea..5caf4906 100644 --- a/src/main/java/io/prometheus/cloudwatch/WebServer.java +++ b/src/main/java/io/prometheus/cloudwatch/WebServer.java @@ -1,47 +1,43 @@ package io.prometheus.cloudwatch; +import io.prometheus.client.exporter.MetricsServlet; +import io.prometheus.client.hotspot.DefaultExports; import java.io.FileReader; - import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; -import io.prometheus.client.exporter.MetricsServlet; -import io.prometheus.client.hotspot.DefaultExports; - public class WebServer { - public static String configFilePath; - - public static void main(String[] args) throws Exception { - if (args.length < 2) { - System.err.println("Usage: WebServer "); - System.exit(1); - } + public static String configFilePath; - configFilePath = args[1]; - CloudWatchCollector collector = null; - new BuildInfoCollector().register(); - try ( - FileReader reader = new FileReader(configFilePath); - ) { - collector = new CloudWatchCollector(new FileReader(configFilePath)).register(); - } - DefaultExports.initialize(); - - ReloadSignalHandler.start(collector); + public static void main(String[] args) throws Exception { + if (args.length < 2) { + System.err.println("Usage: WebServer "); + System.exit(1); + } - int port = Integer.parseInt(args[0]); - Server server = new Server(port); - ServletContextHandler context = new ServletContextHandler(); - context.setContextPath("/"); - server.setHandler(context); - context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics"); - context.addServlet(new ServletHolder(new DynamicReloadServlet(collector)), "/-/reload"); - context.addServlet(new ServletHolder(new HealthServlet()), "/-/healthy"); - context.addServlet(new ServletHolder(new HealthServlet()), "/-/ready"); - context.addServlet(new ServletHolder(new HomePageServlet()), "/"); - server.start(); - server.join(); + configFilePath = args[1]; + CloudWatchCollector collector = null; + new BuildInfoCollector().register(); + try (FileReader reader = new FileReader(configFilePath); ) { + collector = new CloudWatchCollector(new FileReader(configFilePath)).register(); } + DefaultExports.initialize(); + + ReloadSignalHandler.start(collector); + + int port = Integer.parseInt(args[0]); + Server server = new Server(port); + ServletContextHandler context = new ServletContextHandler(); + context.setContextPath("/"); + server.setHandler(context); + context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics"); + context.addServlet(new ServletHolder(new DynamicReloadServlet(collector)), "/-/reload"); + context.addServlet(new ServletHolder(new HealthServlet()), "/-/healthy"); + context.addServlet(new ServletHolder(new HealthServlet()), "/-/ready"); + context.addServlet(new ServletHolder(new HomePageServlet()), "/"); + server.start(); + server.join(); + } } diff --git a/src/test/java/io/prometheus/cloudwatch/CloudWatchCollectorTest.java b/src/test/java/io/prometheus/cloudwatch/CloudWatchCollectorTest.java index 6369b95c..ec711106 100644 --- a/src/test/java/io/prometheus/cloudwatch/CloudWatchCollectorTest.java +++ b/src/test/java/io/prometheus/cloudwatch/CloudWatchCollectorTest.java @@ -1,40 +1,35 @@ package io.prometheus.cloudwatch; import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.hamcrest.MockitoHamcrest.argThat; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; - import io.prometheus.client.Collector; import io.prometheus.client.CollectorRegistry; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Enumeration; -import java.util.List; -import java.util.Properties; import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Properties; import java.util.Set; - +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; import software.amazon.awssdk.services.cloudwatch.model.*; import software.amazon.awssdk.services.resourcegroupstaggingapi.ResourceGroupsTaggingApiClient; import software.amazon.awssdk.services.resourcegroupstaggingapi.model.GetResourcesRequest; import software.amazon.awssdk.services.resourcegroupstaggingapi.model.GetResourcesResponse; import software.amazon.awssdk.services.resourcegroupstaggingapi.model.ResourceTagMapping; -import software.amazon.awssdk.services.resourcegroupstaggingapi.model.TagFilter; import software.amazon.awssdk.services.resourcegroupstaggingapi.model.Tag; +import software.amazon.awssdk.services.resourcegroupstaggingapi.model.TagFilter; public class CloudWatchCollectorTest { CloudWatchClient cloudWatchClient; @@ -59,14 +54,17 @@ public ListMetricsRequestMatcher Namespace(String namespace) { this.namespace = namespace; return this; } + public ListMetricsRequestMatcher MetricName(String metricName) { this.metricName = metricName; return this; } + public ListMetricsRequestMatcher NextToken(String nextToken) { this.nextToken = nextToken; return this; } + public ListMetricsRequestMatcher Dimensions(String... dimensions) { this.dimensions = new ArrayList(); for (int i = 0; i < dimensions.length; i++) { @@ -74,37 +72,38 @@ public ListMetricsRequestMatcher Dimensions(String... dimensions) { } return this; } + public ListMetricsRequestMatcher RecentlyActive(String recentlyActive) { this.recentlyActive = recentlyActive; return this; } public boolean matches(Object o) { - ListMetricsRequest request = (ListMetricsRequest) o; - if (request == null) return false; - if (namespace != null && !namespace.equals(request.namespace())){ - return false; - } - if (metricName != null && !metricName.equals(request.metricName())){ - return false; - } - if (nextToken == null ^ request.nextToken() == null) { - return false; - } - if (nextToken != null && !nextToken.equals(request.nextToken())) { - return false; - } - if (!dimensions.equals(request.dimensions())) { - return false; - } - if (recentlyActive != null && !recentlyActive.equals(request.recentlyActive())) { - return false; - } - return true; + ListMetricsRequest request = (ListMetricsRequest) o; + if (request == null) return false; + if (namespace != null && !namespace.equals(request.namespace())) { + return false; + } + if (metricName != null && !metricName.equals(request.metricName())) { + return false; + } + if (nextToken == null ^ request.nextToken() == null) { + return false; + } + if (nextToken != null && !nextToken.equals(request.nextToken())) { + return false; + } + if (!dimensions.equals(request.dimensions())) { + return false; + } + if (recentlyActive != null && !recentlyActive.equals(request.recentlyActive())) { + return false; + } + return true; } public void describeTo(Description description) { - description.appendText("list metrics request"); + description.appendText("list metrics request"); } } @@ -118,35 +117,38 @@ public GetMetricStatisticsRequestMatcher Namespace(String namespace) { this.namespace = namespace; return this; } + public GetMetricStatisticsRequestMatcher MetricName(String metricName) { this.metricName = metricName; return this; } + public GetMetricStatisticsRequestMatcher Dimension(String name, String value) { dimensions.add(Dimension.builder().name(name).value(value).build()); return this; } + public GetMetricStatisticsRequestMatcher Period(int period) { this.period = period; return this; } public boolean matches(Object o) { - GetMetricStatisticsRequest request = (GetMetricStatisticsRequest) o; - if (request == null) return false; - if (namespace != null && !namespace.equals(request.namespace())){ - return false; - } - if (metricName != null && !metricName.equals(request.metricName())){ - return false; - } - if (!dimensions.equals(request.dimensions())) { - return false; - } - if (period != null && !period.equals(request.period())) { - return false; - } - return true; + GetMetricStatisticsRequest request = (GetMetricStatisticsRequest) o; + if (request == null) return false; + if (namespace != null && !namespace.equals(request.namespace())) { + return false; + } + if (metricName != null && !metricName.equals(request.metricName())) { + return false; + } + if (!dimensions.equals(request.dimensions())) { + return false; + } + if (period != null && !period.equals(request.period())) { + return false; + } + return true; } public void describeTo(Description description) { @@ -163,31 +165,33 @@ public GetResourcesRequestMatcher PaginationToken(String paginationToken) { this.paginationToken = paginationToken; return this; } + public GetResourcesRequestMatcher ResourceTypeFilter(String resourceTypeFilter) { resourceTypeFilters.add(resourceTypeFilter); return this; } - public GetResourcesRequestMatcher TagFilter(String key, List values ) { + + public GetResourcesRequestMatcher TagFilter(String key, List values) { tagFilters.add(TagFilter.builder().key(key).values(values).build()); return this; } public boolean matches(Object o) { - GetResourcesRequest request = (GetResourcesRequest) o; - if (request == null) return false; - if (paginationToken == "" ^ request.paginationToken() == "") { - return false; - } - if (paginationToken != "" && !paginationToken.equals(request.paginationToken())) { - return false; - } - if (!resourceTypeFilters.equals(request.resourceTypeFilters())) { - return false; - } - if (!tagFilters.equals(request.tagFilters())) { - return false; - } - return true; + GetResourcesRequest request = (GetResourcesRequest) o; + if (request == null) return false; + if (paginationToken == "" ^ request.paginationToken() == "") { + return false; + } + if (paginationToken != "" && !paginationToken.equals(request.paginationToken())) { + return false; + } + if (!resourceTypeFilters.equals(request.resourceTypeFilters())) { + return false; + } + if (!tagFilters.equals(request.tagFilters())) { + return false; + } + return true; } public void describeTo(Description description) { @@ -198,90 +202,162 @@ public void describeTo(Description description) { @Test public void testMetricPeriod() { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n period_seconds: 100\n range_seconds: 200\n delay_seconds: 300", cloudWatchClient, taggingClient).register(registry); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n period_seconds: 100\n range_seconds: 200\n delay_seconds: 300", + cloudWatchClient, + taggingClient) + .register(registry); Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest) any())) - .thenReturn(GetMetricStatisticsResponse.builder().build()); - - registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance"}, new String[]{"aws_elb", ""}); - - - Mockito.verify(cloudWatchClient).getMetricStatistics(argThat( - new GetMetricStatisticsRequestMatcher() - .Namespace("AWS/ELB") - .MetricName("RequestCount") - .Period(100) - )); + .thenReturn(GetMetricStatisticsResponse.builder().build()); + + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance"}, + new String[] {"aws_elb", ""}); + + Mockito.verify(cloudWatchClient) + .getMetricStatistics( + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB").MetricName("RequestCount").Period(100))); } @Test public void testDefaultPeriod() { new CloudWatchCollector( - "---\nregion: reg\nperiod_seconds: 100\nrange_seconds: 200\ndelay_seconds: 300\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount", cloudWatchClient, taggingClient).register(registry); + "---\nregion: reg\nperiod_seconds: 100\nrange_seconds: 200\ndelay_seconds: 300\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount", + cloudWatchClient, + taggingClient) + .register(registry); Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest) any())) - .thenReturn(GetMetricStatisticsResponse.builder().build()); - - registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance"}, new String[]{"aws_elb", ""}); - - - Mockito.verify(cloudWatchClient).getMetricStatistics((GetMetricStatisticsRequest) argThat( - new GetMetricStatisticsRequestMatcher() - .Namespace("AWS/ELB") - .MetricName("RequestCount") - .Period(100) - )); + .thenReturn(GetMetricStatisticsResponse.builder().build()); + + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance"}, + new String[] {"aws_elb", ""}); + + Mockito.verify(cloudWatchClient) + .getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB").MetricName("RequestCount").Period(100))); } @Test public void testAllStatistics() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount", cloudWatchClient, taggingClient).register(registry); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(1.0) - .maximum(2.0).minimum(3.0).sampleCount(4.0).sum(5.0).build()).build()); - - assertEquals(1.0, registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance"}, new String[]{"aws_elb", ""}), .01); - assertEquals(2.0, registry.getSampleValue("aws_elb_request_count_maximum", new String[]{"job", "instance"}, new String[]{"aws_elb", ""}), .01); - assertEquals(3.0, registry.getSampleValue("aws_elb_request_count_minimum", new String[]{"job", "instance"}, new String[]{"aws_elb", ""}), .01); - assertEquals(4.0, registry.getSampleValue("aws_elb_request_count_sample_count", new String[]{"job", "instance"}, new String[]{"aws_elb", ""}), .01); - assertEquals(5.0, registry.getSampleValue("aws_elb_request_count_sum", new String[]{"job", "instance"}, new String[]{"aws_elb", ""}), .01); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB").MetricName("RequestCount")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder() + .timestamp(new Date().toInstant()) + .average(1.0) + .maximum(2.0) + .minimum(3.0) + .sampleCount(4.0) + .sum(5.0) + .build()) + .build()); + + assertEquals( + 1.0, + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance"}, + new String[] {"aws_elb", ""}), + .01); + assertEquals( + 2.0, + registry.getSampleValue( + "aws_elb_request_count_maximum", + new String[] {"job", "instance"}, + new String[] {"aws_elb", ""}), + .01); + assertEquals( + 3.0, + registry.getSampleValue( + "aws_elb_request_count_minimum", + new String[] {"job", "instance"}, + new String[] {"aws_elb", ""}), + .01); + assertEquals( + 4.0, + registry.getSampleValue( + "aws_elb_request_count_sample_count", + new String[] {"job", "instance"}, + new String[] {"aws_elb", ""}), + .01); + assertEquals( + 5.0, + registry.getSampleValue( + "aws_elb_request_count_sum", + new String[] {"job", "instance"}, + new String[] {"aws_elb", ""}), + .01); } @Test public void testCloudwatchTimestamps() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n set_timestamp: true\n- aws_namespace: AWS/ELB\n aws_metric_name: HTTPCode_Backend_2XX\n set_timestamp: false" - , cloudWatchClient, taggingClient).register(registry); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n set_timestamp: true\n- aws_namespace: AWS/ELB\n aws_metric_name: HTTPCode_Backend_2XX\n set_timestamp: false", + cloudWatchClient, + taggingClient) + .register(registry); Date timestamp = new Date(); - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(timestamp.toInstant()).average(1.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("HTTPCode_Backend_2XX")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(timestamp.toInstant()).average(1.0).build()).build()); + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB").MetricName("RequestCount")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(timestamp.toInstant()).average(1.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB").MetricName("HTTPCode_Backend_2XX")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(timestamp.toInstant()).average(1.0).build()) + .build()); assertMetricTimestampEquals(registry, "aws_elb_request_count_average", timestamp.getTime()); assertMetricTimestampEquals(registry, "aws_elb_httpcode_backend_2_xx_average", null); - } - void assertMetricTimestampEquals(CollectorRegistry registry, String name, Long expectedTimestamp) { - Enumeration metricFamilySamplesEnumeration = registry.metricFamilySamples(); + void assertMetricTimestampEquals( + CollectorRegistry registry, String name, Long expectedTimestamp) { + Enumeration metricFamilySamplesEnumeration = + registry.metricFamilySamples(); Set metricNames = new HashSet(); - while(metricFamilySamplesEnumeration.hasMoreElements()) { + while (metricFamilySamplesEnumeration.hasMoreElements()) { Collector.MetricFamilySamples samples = metricFamilySamplesEnumeration.nextElement(); - for(Collector.MetricFamilySamples.Sample s: samples.samples) { + for (Collector.MetricFamilySamples.Sample s : samples.samples) { metricNames.add(s.name); - if(s.name.equals(name)) { - assertEquals(expectedTimestamp, (Long)s.timestampMs); + if (s.name.equals(name)) { + assertEquals(expectedTimestamp, (Long) s.timestampMs); return; } } @@ -292,460 +368,1377 @@ void assertMetricTimestampEquals(CollectorRegistry registry, String name, Long e @Test public void testUsesNewestDatapoint() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount", cloudWatchClient, taggingClient).register(registry); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date(1).toInstant()).average(1.0).build(), - Datapoint.builder().timestamp(new Date(3).toInstant()).average(3.0).build(), - Datapoint.builder().timestamp(new Date(2).toInstant()).average(2.0).build()).build()); - - assertEquals(3.0, registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance"}, new String[]{"aws_elb", ""}), .01); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB").MetricName("RequestCount")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date(1).toInstant()).average(1.0).build(), + Datapoint.builder().timestamp(new Date(3).toInstant()).average(3.0).build(), + Datapoint.builder().timestamp(new Date(2).toInstant()).average(2.0).build()) + .build()); + + assertEquals( + 3.0, + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance"}, + new String[] {"aws_elb", ""}), + .01); } @Test public void testDimensions() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName", cloudWatchClient, taggingClient).register(registry); - - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancerName")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("a").build(), Dimension.builder().name("LoadBalancerName").value("myLB").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("a").build(), Dimension.builder().name("LoadBalancerName").value("myLB").build(), Dimension.builder().name("ThisExtraDimensionIsIgnored").value("dummy").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("b").build(), Dimension.builder().name("LoadBalancerName").value("myOtherLB").build()).build() - ).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancerName", "myLB")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "b").Dimension("LoadBalancerName", "myOtherLB")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()).build()); - - assertEquals(2.0, registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "a", "myLB"}), .01); - assertEquals(3.0, registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "b", "myOtherLB"}), .01); - assertNull(registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name", "this_extra_dimension_is_ignored"}, new String[]{"aws_elb", "", "a", "myLB", "dummy"})); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimensions("AvailabilityZone", "LoadBalancerName")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("a").build(), + Dimension.builder().name("LoadBalancerName").value("myLB").build()) + .build(), + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("a").build(), + Dimension.builder().name("LoadBalancerName").value("myLB").build(), + Dimension.builder() + .name("ThisExtraDimensionIsIgnored") + .value("dummy") + .build()) + .build(), + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("b").build(), + Dimension.builder().name("LoadBalancerName").value("myOtherLB").build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "a") + .Dimension("LoadBalancerName", "myLB")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "b") + .Dimension("LoadBalancerName", "myOtherLB")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()) + .build()); + + assertEquals( + 2.0, + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "a", "myLB"}), + .01); + assertEquals( + 3.0, + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "b", "myOtherLB"}), + .01); + assertNull( + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] { + "job", + "instance", + "availability_zone", + "load_balancer_name", + "this_extra_dimension_is_ignored" + }, + new String[] {"aws_elb", "", "a", "myLB", "dummy"})); } @Test public void testDimensionSelect() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName\n aws_dimension_select:\n LoadBalancerName:\n - myLB", cloudWatchClient, taggingClient).register(registry); - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancerName")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("a").build(), Dimension.builder().name("LoadBalancerName").value("myLB").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("b").build(), Dimension.builder().name("LoadBalancerName").value("myLB").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("a").build(), Dimension.builder().name("LoadBalancerName").value("myOtherLB").build()).build() - ).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancerName", "myLB")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "b").Dimension("LoadBalancerName", "myLB")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - assertEquals(2.0, registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "a", "myLB"}), .01); - assertEquals(2.0, registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "b", "myLB"}), .01); - assertNull(registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "a", "myOtherLB"})); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName\n aws_dimension_select:\n LoadBalancerName:\n - myLB", + cloudWatchClient, + taggingClient) + .register(registry); + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimensions("AvailabilityZone", "LoadBalancerName")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("a").build(), + Dimension.builder().name("LoadBalancerName").value("myLB").build()) + .build(), + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("b").build(), + Dimension.builder().name("LoadBalancerName").value("myLB").build()) + .build(), + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("a").build(), + Dimension.builder().name("LoadBalancerName").value("myOtherLB").build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "a") + .Dimension("LoadBalancerName", "myLB")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "b") + .Dimension("LoadBalancerName", "myLB")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + assertEquals( + 2.0, + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "a", "myLB"}), + .01); + assertEquals( + 2.0, + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "b", "myLB"}), + .01); + assertNull( + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "a", "myOtherLB"})); } @Test public void testAllSelectDimensionsKnown() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName\n aws_dimension_select:\n LoadBalancerName:\n - myLB\n AvailabilityZone:\n - a\n - b", cloudWatchClient, taggingClient).register(registry); - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancerName", "myLB")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "b").Dimension("LoadBalancerName", "myLB")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - assertEquals(2.0, registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "a", "myLB"}), .01); - assertEquals(2.0, registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "b", "myLB"}), .01); - assertNull(registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "a", "myOtherLB"})); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName\n aws_dimension_select:\n LoadBalancerName:\n - myLB\n AvailabilityZone:\n - a\n - b", + cloudWatchClient, + taggingClient) + .register(registry); + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "a") + .Dimension("LoadBalancerName", "myLB")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "b") + .Dimension("LoadBalancerName", "myLB")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + assertEquals( + 2.0, + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "a", "myLB"}), + .01); + assertEquals( + 2.0, + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "b", "myLB"}), + .01); + assertNull( + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "a", "myOtherLB"})); } @Test public void testDimensionSelectRegex() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName\n aws_dimension_select_regex:\n LoadBalancerName:\n - myLB(.*)", cloudWatchClient, taggingClient).register(registry); - - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest) argThat( - new ListMetricsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancerName")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("a").build(), Dimension.builder().name("LoadBalancerName").value("myLB1").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("b").build(), Dimension.builder().name("LoadBalancerName").value("myLB2").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("a").build(), Dimension.builder().name("LoadBalancerName").value("myOtherLB").build()).build() - ).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest) argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancerName", "myLB1")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest) argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "b").Dimension("LoadBalancerName", "myLB2")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - assertEquals(2.0, registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "a", "myLB1"}), .01); - assertEquals(2.0, registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "b", "myLB2"}), .01); - assertNull(registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "a", "myOtherLB"})); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName\n aws_dimension_select_regex:\n LoadBalancerName:\n - myLB(.*)", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimensions("AvailabilityZone", "LoadBalancerName")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("a").build(), + Dimension.builder().name("LoadBalancerName").value("myLB1").build()) + .build(), + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("b").build(), + Dimension.builder().name("LoadBalancerName").value("myLB2").build()) + .build(), + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("a").build(), + Dimension.builder().name("LoadBalancerName").value("myOtherLB").build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "a") + .Dimension("LoadBalancerName", "myLB1")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "b") + .Dimension("LoadBalancerName", "myLB2")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + assertEquals( + 2.0, + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "a", "myLB1"}), + .01); + assertEquals( + 2.0, + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "b", "myLB2"}), + .01); + assertNull( + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "a", "myOtherLB"})); } @Test public void testGetDimensionsUsesNextToken() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName\n aws_dimension_select:\n LoadBalancerName:\n - myLB", cloudWatchClient, taggingClient).register(registry); - - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancerName")))) + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName\n aws_dimension_select:\n LoadBalancerName:\n - myLB", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimensions("AvailabilityZone", "LoadBalancerName")))) .thenReturn(ListMetricsResponse.builder().nextToken("ABC").build()); - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancerName").NextToken("ABC")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("a").build(), Dimension.builder().name("LoadBalancerName").value("myLB").build()).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancerName", "myLB")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - assertEquals(2.0, registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer_name"}, new String[]{"aws_elb", "", "a", "myLB"}), .01); + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimensions("AvailabilityZone", "LoadBalancerName") + .NextToken("ABC")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("a").build(), + Dimension.builder().name("LoadBalancerName").value("myLB").build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "a") + .Dimension("LoadBalancerName", "myLB")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + assertEquals( + 2.0, + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer_name"}, + new String[] {"aws_elb", "", "a", "myLB"}), + .01); } @Test public void testExtendedStatistics() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: Latency\n aws_extended_statistics:\n - p95\n - p99.99", cloudWatchClient, taggingClient).register(registry); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: Latency\n aws_extended_statistics:\n - p95\n - p99.99", + cloudWatchClient, + taggingClient) + .register(registry); HashMap extendedStatistics = new HashMap(); extendedStatistics.put("p95", 1.0); extendedStatistics.put("p99.99", 2.0); - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("Latency")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).extendedStatistics(extendedStatistics).build()).build()); - - assertEquals(1.0, registry.getSampleValue("aws_elb_latency_p95", new String[]{"job", "instance"}, new String[]{"aws_elb", ""}), .01); - assertEquals(2.0, registry.getSampleValue("aws_elb_latency_p99_99", new String[]{"job", "instance"}, new String[]{"aws_elb", ""}), .01); + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB").MetricName("Latency")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder() + .timestamp(new Date().toInstant()) + .extendedStatistics(extendedStatistics) + .build()) + .build()); + + assertEquals( + 1.0, + registry.getSampleValue( + "aws_elb_latency_p95", new String[] {"job", "instance"}, new String[] {"aws_elb", ""}), + .01); + assertEquals( + 2.0, + registry.getSampleValue( + "aws_elb_latency_p99_99", + new String[] {"job", "instance"}, + new String[] {"aws_elb", ""}), + .01); } @Test public void testDynamoIndexDimensions() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/DynamoDB\n aws_metric_name: ConsumedReadCapacityUnits\n aws_dimensions:\n - TableName\n - GlobalSecondaryIndexName\n- aws_namespace: AWS/DynamoDB\n aws_metric_name: OnlineIndexConsumedWriteCapacity\n aws_dimensions:\n - TableName\n - GlobalSecondaryIndexName\n- aws_namespace: AWS/DynamoDB\n aws_metric_name: ConsumedReadCapacityUnits\n aws_dimensions:\n - TableName", cloudWatchClient, taggingClient).register(registry); - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("ConsumedReadCapacityUnits").Dimensions("TableName", "GlobalSecondaryIndexName")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("TableName").value("myTable").build(), Dimension.builder().name("GlobalSecondaryIndexName").value("myIndex").build()).build()).build()); - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("OnlineIndexConsumedWriteCapacity").Dimensions("TableName", "GlobalSecondaryIndexName")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("TableName").value("myTable").build(), Dimension.builder().name("GlobalSecondaryIndexName").value("myIndex").build()).build()).build()); - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("ConsumedReadCapacityUnits").Dimensions("TableName")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("TableName").value("myTable").build()).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("ConsumedReadCapacityUnits").Dimension("TableName", "myTable").Dimension("GlobalSecondaryIndexName", "myIndex")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).sum(1.0).build()).build()); - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("OnlineIndexConsumedWriteCapacity").Dimension("TableName", "myTable").Dimension("GlobalSecondaryIndexName", "myIndex")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).sum(2.0).build()).build()); - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("ConsumedReadCapacityUnits").Dimension("TableName", "myTable")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).sum(3.0).build()).build()); - - assertEquals(1.0, registry.getSampleValue("aws_dynamodb_consumed_read_capacity_units_index_sum", new String[]{"job", "instance", "table_name", "global_secondary_index_name"}, new String[]{"aws_dynamodb", "", "myTable", "myIndex"}), .01); - assertEquals(2.0, registry.getSampleValue("aws_dynamodb_online_index_consumed_write_capacity_sum", new String[]{"job", "instance", "table_name", "global_secondary_index_name"}, new String[]{"aws_dynamodb", "", "myTable", "myIndex"}), .01); - assertEquals(3.0, registry.getSampleValue("aws_dynamodb_consumed_read_capacity_units_sum", new String[]{"job", "instance", "table_name"}, new String[]{"aws_dynamodb", "", "myTable"}), .01); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/DynamoDB\n aws_metric_name: ConsumedReadCapacityUnits\n aws_dimensions:\n - TableName\n - GlobalSecondaryIndexName\n- aws_namespace: AWS/DynamoDB\n aws_metric_name: OnlineIndexConsumedWriteCapacity\n aws_dimensions:\n - TableName\n - GlobalSecondaryIndexName\n- aws_namespace: AWS/DynamoDB\n aws_metric_name: ConsumedReadCapacityUnits\n aws_dimensions:\n - TableName", + cloudWatchClient, + taggingClient) + .register(registry); + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/DynamoDB") + .MetricName("ConsumedReadCapacityUnits") + .Dimensions("TableName", "GlobalSecondaryIndexName")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions( + Dimension.builder().name("TableName").value("myTable").build(), + Dimension.builder() + .name("GlobalSecondaryIndexName") + .value("myIndex") + .build()) + .build()) + .build()); + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/DynamoDB") + .MetricName("OnlineIndexConsumedWriteCapacity") + .Dimensions("TableName", "GlobalSecondaryIndexName")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions( + Dimension.builder().name("TableName").value("myTable").build(), + Dimension.builder() + .name("GlobalSecondaryIndexName") + .value("myIndex") + .build()) + .build()) + .build()); + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/DynamoDB") + .MetricName("ConsumedReadCapacityUnits") + .Dimensions("TableName")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions(Dimension.builder().name("TableName").value("myTable").build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/DynamoDB") + .MetricName("ConsumedReadCapacityUnits") + .Dimension("TableName", "myTable") + .Dimension("GlobalSecondaryIndexName", "myIndex")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints(Datapoint.builder().timestamp(new Date().toInstant()).sum(1.0).build()) + .build()); + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/DynamoDB") + .MetricName("OnlineIndexConsumedWriteCapacity") + .Dimension("TableName", "myTable") + .Dimension("GlobalSecondaryIndexName", "myIndex")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints(Datapoint.builder().timestamp(new Date().toInstant()).sum(2.0).build()) + .build()); + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/DynamoDB") + .MetricName("ConsumedReadCapacityUnits") + .Dimension("TableName", "myTable")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints(Datapoint.builder().timestamp(new Date().toInstant()).sum(3.0).build()) + .build()); + + assertEquals( + 1.0, + registry.getSampleValue( + "aws_dynamodb_consumed_read_capacity_units_index_sum", + new String[] {"job", "instance", "table_name", "global_secondary_index_name"}, + new String[] {"aws_dynamodb", "", "myTable", "myIndex"}), + .01); + assertEquals( + 2.0, + registry.getSampleValue( + "aws_dynamodb_online_index_consumed_write_capacity_sum", + new String[] {"job", "instance", "table_name", "global_secondary_index_name"}, + new String[] {"aws_dynamodb", "", "myTable", "myIndex"}), + .01); + assertEquals( + 3.0, + registry.getSampleValue( + "aws_dynamodb_consumed_read_capacity_units_sum", + new String[] {"job", "instance", "table_name"}, + new String[] {"aws_dynamodb", "", "myTable"}), + .01); } - + @Test public void testDynamoNoDimensions() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/DynamoDB\n aws_metric_name: AccountProvisionedReadCapacityUtilization\n", cloudWatchClient, taggingClient).register(registry); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("AccountProvisionedReadCapacityUtilization")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).sum(1.0).build()).build()); - - assertEquals(1.0, registry.getSampleValue("aws_dynamodb_account_provisioned_read_capacity_utilization_sum", new String[]{"job", "instance"}, new String[]{"aws_dynamodb", ""}), .01); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/DynamoDB\n aws_metric_name: AccountProvisionedReadCapacityUtilization\n", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/DynamoDB") + .MetricName("AccountProvisionedReadCapacityUtilization")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints(Datapoint.builder().timestamp(new Date().toInstant()).sum(1.0).build()) + .build()); + + assertEquals( + 1.0, + registry.getSampleValue( + "aws_dynamodb_account_provisioned_read_capacity_utilization_sum", + new String[] {"job", "instance"}, + new String[] {"aws_dynamodb", ""}), + .01); } + @Test public void testTagSelectEC2() throws Exception { // Testing "aws_tag_select" with an EC2 new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/EC2\n aws_metric_name: CPUUtilization\n aws_dimensions:\n - InstanceId\n aws_tag_select:\n resource_type_selection: \"ec2:instance\"\n resource_id_dimension: InstanceId\n tag_selections:\n Monitoring: [enabled]\n", - cloudWatchClient, taggingClient).register(registry); - - Mockito.when(taggingClient.getResources((GetResourcesRequest)argThat( - new GetResourcesRequestMatcher().ResourceTypeFilter("ec2:instance").TagFilter("Monitoring", Arrays.asList("enabled"))))) - .thenReturn(GetResourcesResponse.builder().resourceTagMappingList( - ResourceTagMapping.builder().tags(Tag.builder().key("Monitoring").value("enabled").build()).resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-1").build()).build()); - - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimensions("InstanceId")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("InstanceId").value("i-1").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("InstanceId").value("i-2").build()).build() - ).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimension("InstanceId", "i-1")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimension("InstanceId", "i-2")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - assertEquals(2.0, registry.getSampleValue("aws_ec2_cpuutilization_average", new String[]{"job", "instance", "instance_id"}, new String[]{"aws_ec2", "", "i-1"}), .01); - assertNull(registry.getSampleValue("aws_ec2_cpuutilization_average", new String[]{"job", "instance", "instance_id"}, new String[]{"aws_ec2", "", "i-2"})); - assertEquals(1.0, registry.getSampleValue("aws_resource_info", new String[]{"job", "instance", "arn", "instance_id", "tag_Monitoring"}, new String[]{"aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-1", "i-1", "enabled"}), .01); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/EC2\n aws_metric_name: CPUUtilization\n aws_dimensions:\n - InstanceId\n aws_tag_select:\n resource_type_selection: \"ec2:instance\"\n resource_id_dimension: InstanceId\n tag_selections:\n Monitoring: [enabled]\n", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + taggingClient.getResources( + (GetResourcesRequest) + argThat( + new GetResourcesRequestMatcher() + .ResourceTypeFilter("ec2:instance") + .TagFilter("Monitoring", Arrays.asList("enabled"))))) + .thenReturn( + GetResourcesResponse.builder() + .resourceTagMappingList( + ResourceTagMapping.builder() + .tags(Tag.builder().key("Monitoring").value("enabled").build()) + .resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-1") + .build()) + .build()); + + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimensions("InstanceId")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions(Dimension.builder().name("InstanceId").value("i-1").build()) + .build(), + Metric.builder() + .dimensions(Dimension.builder().name("InstanceId").value("i-2").build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimension("InstanceId", "i-1")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimension("InstanceId", "i-2")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + assertEquals( + 2.0, + registry.getSampleValue( + "aws_ec2_cpuutilization_average", + new String[] {"job", "instance", "instance_id"}, + new String[] {"aws_ec2", "", "i-1"}), + .01); + assertNull( + registry.getSampleValue( + "aws_ec2_cpuutilization_average", + new String[] {"job", "instance", "instance_id"}, + new String[] {"aws_ec2", "", "i-2"})); + assertEquals( + 1.0, + registry.getSampleValue( + "aws_resource_info", + new String[] {"job", "instance", "arn", "instance_id", "tag_Monitoring"}, + new String[] { + "aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-1", "i-1", "enabled" + }), + .01); } - + @Test public void testTagSelectALB() throws Exception { - // Testing "aws_tag_select" with an ALB, which have a fairly complex ARN + // Testing "aws_tag_select" with an ALB, which have a fairly complex ARN new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ApplicationELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancer\n aws_tag_select:\n resource_type_selection: \"elasticloadbalancing:loadbalancer/app\"\n resource_id_dimension: LoadBalancer\n tag_selections:\n Monitoring: [enabled]\n", - cloudWatchClient, taggingClient).register(registry); - - Mockito.when(taggingClient.getResources((GetResourcesRequest)argThat( - new GetResourcesRequestMatcher().ResourceTypeFilter("elasticloadbalancing:loadbalancer/app").TagFilter("Monitoring", Arrays.asList("enabled"))))) - .thenReturn(GetResourcesResponse.builder().resourceTagMappingList( - ResourceTagMapping.builder().tags(Tag.builder().key("Monitoring").value("enabled").build()).resourceARN("arn:aws:elasticloadbalancing:us-east-1:121212121212:loadbalancer/app/myLB/123").build()).build()); - - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/ApplicationELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancer")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("a").build(), Dimension.builder().name("LoadBalancer").value("app/myLB/123").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("b").build(), Dimension.builder().name("LoadBalancer").value("app/myLB/123").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("a").build(), Dimension.builder().name("LoadBalancer").value("app/myOtherLB/456").build()).build() - ).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ApplicationELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancer", "app/myLB/123")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ApplicationELB").MetricName("RequestCount").Dimension("AvailabilityZone", "b").Dimension("LoadBalancer", "app/myLB/123")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ApplicationELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancer", "app/myOtherLB/456")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(4.0).build()).build()); - - assertEquals(2.0, registry.getSampleValue("aws_applicationelb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer"}, new String[]{"aws_applicationelb", "", "a", "app/myLB/123"}), .01); - assertEquals(3.0, registry.getSampleValue("aws_applicationelb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer"}, new String[]{"aws_applicationelb", "", "b", "app/myLB/123"}), .01); - assertNull(registry.getSampleValue("aws_applicationelb_request_count_average", new String[]{"job", "instance", "availability_zone", "load_balancer"}, new String[]{"aws_applicationelb", "", "a", "app/myOtherLB/456"})); - assertEquals(1.0, registry.getSampleValue("aws_resource_info", new String[]{"job", "instance", "arn", "load_balancer", "tag_Monitoring"}, new String[]{"aws_applicationelb", "", "arn:aws:elasticloadbalancing:us-east-1:121212121212:loadbalancer/app/myLB/123", "app/myLB/123", "enabled"}), .01); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ApplicationELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancer\n aws_tag_select:\n resource_type_selection: \"elasticloadbalancing:loadbalancer/app\"\n resource_id_dimension: LoadBalancer\n tag_selections:\n Monitoring: [enabled]\n", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + taggingClient.getResources( + (GetResourcesRequest) + argThat( + new GetResourcesRequestMatcher() + .ResourceTypeFilter("elasticloadbalancing:loadbalancer/app") + .TagFilter("Monitoring", Arrays.asList("enabled"))))) + .thenReturn( + GetResourcesResponse.builder() + .resourceTagMappingList( + ResourceTagMapping.builder() + .tags(Tag.builder().key("Monitoring").value("enabled").build()) + .resourceARN( + "arn:aws:elasticloadbalancing:us-east-1:121212121212:loadbalancer/app/myLB/123") + .build()) + .build()); + + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/ApplicationELB") + .MetricName("RequestCount") + .Dimensions("AvailabilityZone", "LoadBalancer")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("a").build(), + Dimension.builder().name("LoadBalancer").value("app/myLB/123").build()) + .build(), + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("b").build(), + Dimension.builder().name("LoadBalancer").value("app/myLB/123").build()) + .build(), + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("a").build(), + Dimension.builder() + .name("LoadBalancer") + .value("app/myOtherLB/456") + .build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ApplicationELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "a") + .Dimension("LoadBalancer", "app/myLB/123")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ApplicationELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "b") + .Dimension("LoadBalancer", "app/myLB/123")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ApplicationELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "a") + .Dimension("LoadBalancer", "app/myOtherLB/456")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(4.0).build()) + .build()); + + assertEquals( + 2.0, + registry.getSampleValue( + "aws_applicationelb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer"}, + new String[] {"aws_applicationelb", "", "a", "app/myLB/123"}), + .01); + assertEquals( + 3.0, + registry.getSampleValue( + "aws_applicationelb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer"}, + new String[] {"aws_applicationelb", "", "b", "app/myLB/123"}), + .01); + assertNull( + registry.getSampleValue( + "aws_applicationelb_request_count_average", + new String[] {"job", "instance", "availability_zone", "load_balancer"}, + new String[] {"aws_applicationelb", "", "a", "app/myOtherLB/456"})); + assertEquals( + 1.0, + registry.getSampleValue( + "aws_resource_info", + new String[] {"job", "instance", "arn", "load_balancer", "tag_Monitoring"}, + new String[] { + "aws_applicationelb", + "", + "arn:aws:elasticloadbalancing:us-east-1:121212121212:loadbalancer/app/myLB/123", + "app/myLB/123", + "enabled" + }), + .01); } - + @Test public void testTagSelectUsesPaginationToken() throws Exception { // Testing "aws_tag_select" with an EC2 new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/EC2\n aws_metric_name: CPUUtilization\n aws_dimensions:\n - InstanceId\n aws_tag_select:\n resource_type_selection: \"ec2:instance\"\n resource_id_dimension: InstanceId\n tag_selections:\n Monitoring: [enabled]\n", - cloudWatchClient, taggingClient).register(registry); - - Mockito.when(taggingClient.getResources((GetResourcesRequest)argThat( - new GetResourcesRequestMatcher().ResourceTypeFilter("ec2:instance").TagFilter("Monitoring", Arrays.asList("enabled"))))) - .thenReturn(GetResourcesResponse.builder().paginationToken("ABC").resourceTagMappingList( - ResourceTagMapping.builder().tags(Tag.builder().key("Monitoring").value("enabled").build()).resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-1").build()).build()); - - Mockito.when(taggingClient.getResources((GetResourcesRequest)argThat( - new GetResourcesRequestMatcher().PaginationToken("ABC").ResourceTypeFilter("ec2:instance").TagFilter("Monitoring", Arrays.asList("enabled"))))) - .thenReturn(GetResourcesResponse.builder().resourceTagMappingList( - ResourceTagMapping.builder().tags(Tag.builder().key("Monitoring").value("enabled").build()).resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-2").build()).build()); - - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimensions("InstanceId")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("InstanceId").value("i-1").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("InstanceId").value("i-2").build()).build() - ).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimension("InstanceId", "i-1")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimension("InstanceId", "i-2")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()).build()); - - assertEquals(2.0, registry.getSampleValue("aws_ec2_cpuutilization_average", new String[]{"job", "instance", "instance_id"}, new String[]{"aws_ec2", "", "i-1"}), .01); - assertEquals(3.0, registry.getSampleValue("aws_ec2_cpuutilization_average", new String[]{"job", "instance", "instance_id"}, new String[]{"aws_ec2", "", "i-2"}), .01); - assertEquals(1.0, registry.getSampleValue("aws_resource_info", new String[]{"job", "instance", "arn", "instance_id", "tag_Monitoring"}, new String[]{"aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-1", "i-1", "enabled"}), .01); - assertEquals(1.0, registry.getSampleValue("aws_resource_info", new String[]{"job", "instance", "arn", "instance_id", "tag_Monitoring"}, new String[]{"aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-2", "i-2", "enabled"}), .01); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/EC2\n aws_metric_name: CPUUtilization\n aws_dimensions:\n - InstanceId\n aws_tag_select:\n resource_type_selection: \"ec2:instance\"\n resource_id_dimension: InstanceId\n tag_selections:\n Monitoring: [enabled]\n", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + taggingClient.getResources( + (GetResourcesRequest) + argThat( + new GetResourcesRequestMatcher() + .ResourceTypeFilter("ec2:instance") + .TagFilter("Monitoring", Arrays.asList("enabled"))))) + .thenReturn( + GetResourcesResponse.builder() + .paginationToken("ABC") + .resourceTagMappingList( + ResourceTagMapping.builder() + .tags(Tag.builder().key("Monitoring").value("enabled").build()) + .resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-1") + .build()) + .build()); + + Mockito.when( + taggingClient.getResources( + (GetResourcesRequest) + argThat( + new GetResourcesRequestMatcher() + .PaginationToken("ABC") + .ResourceTypeFilter("ec2:instance") + .TagFilter("Monitoring", Arrays.asList("enabled"))))) + .thenReturn( + GetResourcesResponse.builder() + .resourceTagMappingList( + ResourceTagMapping.builder() + .tags(Tag.builder().key("Monitoring").value("enabled").build()) + .resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-2") + .build()) + .build()); + + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimensions("InstanceId")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions(Dimension.builder().name("InstanceId").value("i-1").build()) + .build(), + Metric.builder() + .dimensions(Dimension.builder().name("InstanceId").value("i-2").build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimension("InstanceId", "i-1")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimension("InstanceId", "i-2")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()) + .build()); + + assertEquals( + 2.0, + registry.getSampleValue( + "aws_ec2_cpuutilization_average", + new String[] {"job", "instance", "instance_id"}, + new String[] {"aws_ec2", "", "i-1"}), + .01); + assertEquals( + 3.0, + registry.getSampleValue( + "aws_ec2_cpuutilization_average", + new String[] {"job", "instance", "instance_id"}, + new String[] {"aws_ec2", "", "i-2"}), + .01); + assertEquals( + 1.0, + registry.getSampleValue( + "aws_resource_info", + new String[] {"job", "instance", "arn", "instance_id", "tag_Monitoring"}, + new String[] { + "aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-1", "i-1", "enabled" + }), + .01); + assertEquals( + 1.0, + registry.getSampleValue( + "aws_resource_info", + new String[] {"job", "instance", "arn", "instance_id", "tag_Monitoring"}, + new String[] { + "aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-2", "i-2", "enabled" + }), + .01); } - + @Test public void testNoSelection() throws Exception { // When no selection is made, all metrics should be returned new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/EC2\n aws_metric_name: CPUUtilization\n aws_dimensions:\n - InstanceId\n", - cloudWatchClient, taggingClient).register(registry); - - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimensions("InstanceId")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("InstanceId").value("i-1").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("InstanceId").value("i-2").build()).build() - ).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimension("InstanceId", "i-1")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimension("InstanceId", "i-2")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()).build()); - - assertEquals(2.0, registry.getSampleValue("aws_ec2_cpuutilization_average", new String[]{"job", "instance", "instance_id"}, new String[]{"aws_ec2", "", "i-1"}), .01); - assertEquals(3.0, registry.getSampleValue("aws_ec2_cpuutilization_average", new String[]{"job", "instance", "instance_id"}, new String[]{"aws_ec2", "", "i-2"}), .01); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/EC2\n aws_metric_name: CPUUtilization\n aws_dimensions:\n - InstanceId\n", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimensions("InstanceId")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions(Dimension.builder().name("InstanceId").value("i-1").build()) + .build(), + Metric.builder() + .dimensions(Dimension.builder().name("InstanceId").value("i-2").build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimension("InstanceId", "i-1")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimension("InstanceId", "i-2")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()) + .build()); + + assertEquals( + 2.0, + registry.getSampleValue( + "aws_ec2_cpuutilization_average", + new String[] {"job", "instance", "instance_id"}, + new String[] {"aws_ec2", "", "i-1"}), + .01); + assertEquals( + 3.0, + registry.getSampleValue( + "aws_ec2_cpuutilization_average", + new String[] {"job", "instance", "instance_id"}, + new String[] {"aws_ec2", "", "i-2"}), + .01); } - + @Test public void testMultipleSelection() throws Exception { // When multiple selections are made, "and" logic should be applied on metrics new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/EC2\n aws_metric_name: CPUUtilization\n aws_dimensions:\n - InstanceId\n aws_tag_select:\n resource_type_selection: \"ec2:instance\"\n resource_id_dimension: InstanceId\n tag_selections:\n Monitoring: [enabled]\n aws_dimension_select:\n InstanceId: [\"i-1\"]", - cloudWatchClient, taggingClient).register(registry); - - Mockito.when(taggingClient.getResources((GetResourcesRequest)argThat( - new GetResourcesRequestMatcher().ResourceTypeFilter("ec2:instance").TagFilter("Monitoring", Arrays.asList("enabled"))))) - .thenReturn(GetResourcesResponse.builder().resourceTagMappingList( - ResourceTagMapping.builder().tags(Tag.builder().key("Monitoring").value("enabled").build()).resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-1").build(), - ResourceTagMapping.builder().tags(Tag.builder().key("Monitoring").value("enabled").build()).resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-2").build()).build()); - - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimensions("InstanceId")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("InstanceId").value("i-1").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("InstanceId").value("i-2").build()).build() - ).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimension("InstanceId", "i-1")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimension("InstanceId", "i-2")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()).build()); - - assertEquals(2.0, registry.getSampleValue("aws_ec2_cpuutilization_average", new String[]{"job", "instance", "instance_id"}, new String[]{"aws_ec2", "", "i-1"}), .01); - assertNull(registry.getSampleValue("aws_ec2_cpuutilization_average", new String[]{"job", "instance", "instance_id"}, new String[]{"aws_ec2", "", "i-2"})); - assertEquals(1.0, registry.getSampleValue("aws_resource_info", new String[]{"job", "instance", "arn", "instance_id", "tag_Monitoring"}, new String[]{"aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-1", "i-1", "enabled"}), .01); - assertEquals(1.0, registry.getSampleValue("aws_resource_info", new String[]{"job", "instance", "arn", "instance_id", "tag_Monitoring"}, new String[]{"aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-2", "i-2", "enabled"}), .01); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/EC2\n aws_metric_name: CPUUtilization\n aws_dimensions:\n - InstanceId\n aws_tag_select:\n resource_type_selection: \"ec2:instance\"\n resource_id_dimension: InstanceId\n tag_selections:\n Monitoring: [enabled]\n aws_dimension_select:\n InstanceId: [\"i-1\"]", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + taggingClient.getResources( + (GetResourcesRequest) + argThat( + new GetResourcesRequestMatcher() + .ResourceTypeFilter("ec2:instance") + .TagFilter("Monitoring", Arrays.asList("enabled"))))) + .thenReturn( + GetResourcesResponse.builder() + .resourceTagMappingList( + ResourceTagMapping.builder() + .tags(Tag.builder().key("Monitoring").value("enabled").build()) + .resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-1") + .build(), + ResourceTagMapping.builder() + .tags(Tag.builder().key("Monitoring").value("enabled").build()) + .resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-2") + .build()) + .build()); + + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimensions("InstanceId")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions(Dimension.builder().name("InstanceId").value("i-1").build()) + .build(), + Metric.builder() + .dimensions(Dimension.builder().name("InstanceId").value("i-2").build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimension("InstanceId", "i-1")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimension("InstanceId", "i-2")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()) + .build()); + + assertEquals( + 2.0, + registry.getSampleValue( + "aws_ec2_cpuutilization_average", + new String[] {"job", "instance", "instance_id"}, + new String[] {"aws_ec2", "", "i-1"}), + .01); + assertNull( + registry.getSampleValue( + "aws_ec2_cpuutilization_average", + new String[] {"job", "instance", "instance_id"}, + new String[] {"aws_ec2", "", "i-2"})); + assertEquals( + 1.0, + registry.getSampleValue( + "aws_resource_info", + new String[] {"job", "instance", "arn", "instance_id", "tag_Monitoring"}, + new String[] { + "aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-1", "i-1", "enabled" + }), + .01); + assertEquals( + 1.0, + registry.getSampleValue( + "aws_resource_info", + new String[] {"job", "instance", "arn", "instance_id", "tag_Monitoring"}, + new String[] { + "aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-2", "i-2", "enabled" + }), + .01); } - + @Test public void testOptionalTagSelection() throws Exception { - // aws_tag_select can be used without tag_selection to activate the aws_resource_info metric on tagged (or previously tagged) resources + // aws_tag_select can be used without tag_selection to activate the aws_resource_info metric on + // tagged (or previously tagged) resources new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/EC2\n aws_metric_name: CPUUtilization\n aws_dimensions:\n - InstanceId\n aws_tag_select:\n resource_type_selection: \"ec2:instance\"\n resource_id_dimension: InstanceId\n aws_dimension_select:\n InstanceId: [\"i-1\", \"i-no-tag\"]", - cloudWatchClient, taggingClient).register(registry); - - Mockito.when(taggingClient.getResources((GetResourcesRequest)argThat( - new GetResourcesRequestMatcher().ResourceTypeFilter("ec2:instance")))) - .thenReturn(GetResourcesResponse.builder().resourceTagMappingList( - ResourceTagMapping.builder().tags(Tag.builder().key("Monitoring").value("enabled").build()).resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-1").build(), - ResourceTagMapping.builder().tags(Tag.builder().key("Monitoring").value("enabled").build()).resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-2").build()).build()); - - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimensions("InstanceId")))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("InstanceId").value("i-1").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("InstanceId").value("i-2").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("InstanceId").value("i-no-tag").build()).build() - ).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimension("InstanceId", "i-1")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimension("InstanceId", "i-2")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/EC2").MetricName("CPUUtilization").Dimension("InstanceId", "i-no-tag")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(4.0).build()).build()); - - assertEquals(2.0, registry.getSampleValue("aws_ec2_cpuutilization_average", new String[]{"job", "instance", "instance_id"}, new String[]{"aws_ec2", "", "i-1"}), .01); - assertNull(registry.getSampleValue("aws_ec2_cpuutilization_average", new String[]{"job", "instance", "instance_id"}, new String[]{"aws_ec2", "", "i-2"})); - assertEquals(4.0, registry.getSampleValue("aws_ec2_cpuutilization_average", new String[]{"job", "instance", "instance_id"}, new String[]{"aws_ec2", "", "i-no-tag"}), .01); - assertEquals(1.0, registry.getSampleValue("aws_resource_info", new String[]{"job", "instance", "arn", "instance_id", "tag_Monitoring"}, new String[]{"aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-1", "i-1", "enabled"}), .01); - assertEquals(1.0, registry.getSampleValue("aws_resource_info", new String[]{"job", "instance", "arn", "instance_id", "tag_Monitoring"}, new String[]{"aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-2", "i-2", "enabled"}), .01); - assertNull(registry.getSampleValue("aws_resource_info", new String[]{"job", "instance", "arn", "instance_id", "tag_Monitoring"}, new String[]{"aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-no-tag", "i-no-tag", "enabled"})); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/EC2\n aws_metric_name: CPUUtilization\n aws_dimensions:\n - InstanceId\n aws_tag_select:\n resource_type_selection: \"ec2:instance\"\n resource_id_dimension: InstanceId\n aws_dimension_select:\n InstanceId: [\"i-1\", \"i-no-tag\"]", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + taggingClient.getResources( + (GetResourcesRequest) + argThat(new GetResourcesRequestMatcher().ResourceTypeFilter("ec2:instance")))) + .thenReturn( + GetResourcesResponse.builder() + .resourceTagMappingList( + ResourceTagMapping.builder() + .tags(Tag.builder().key("Monitoring").value("enabled").build()) + .resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-1") + .build(), + ResourceTagMapping.builder() + .tags(Tag.builder().key("Monitoring").value("enabled").build()) + .resourceARN("arn:aws:ec2:us-east-1:121212121212:instance/i-2") + .build()) + .build()); + + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimensions("InstanceId")))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions(Dimension.builder().name("InstanceId").value("i-1").build()) + .build(), + Metric.builder() + .dimensions(Dimension.builder().name("InstanceId").value("i-2").build()) + .build(), + Metric.builder() + .dimensions( + Dimension.builder().name("InstanceId").value("i-no-tag").build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimension("InstanceId", "i-1")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimension("InstanceId", "i-2")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/EC2") + .MetricName("CPUUtilization") + .Dimension("InstanceId", "i-no-tag")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(4.0).build()) + .build()); + + assertEquals( + 2.0, + registry.getSampleValue( + "aws_ec2_cpuutilization_average", + new String[] {"job", "instance", "instance_id"}, + new String[] {"aws_ec2", "", "i-1"}), + .01); + assertNull( + registry.getSampleValue( + "aws_ec2_cpuutilization_average", + new String[] {"job", "instance", "instance_id"}, + new String[] {"aws_ec2", "", "i-2"})); + assertEquals( + 4.0, + registry.getSampleValue( + "aws_ec2_cpuutilization_average", + new String[] {"job", "instance", "instance_id"}, + new String[] {"aws_ec2", "", "i-no-tag"}), + .01); + assertEquals( + 1.0, + registry.getSampleValue( + "aws_resource_info", + new String[] {"job", "instance", "arn", "instance_id", "tag_Monitoring"}, + new String[] { + "aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-1", "i-1", "enabled" + }), + .01); + assertEquals( + 1.0, + registry.getSampleValue( + "aws_resource_info", + new String[] {"job", "instance", "arn", "instance_id", "tag_Monitoring"}, + new String[] { + "aws_ec2", "", "arn:aws:ec2:us-east-1:121212121212:instance/i-2", "i-2", "enabled" + }), + .01); + assertNull( + registry.getSampleValue( + "aws_resource_info", + new String[] {"job", "instance", "arn", "instance_id", "tag_Monitoring"}, + new String[] { + "aws_ec2", + "", + "arn:aws:ec2:us-east-1:121212121212:instance/i-no-tag", + "i-no-tag", + "enabled" + })); } @Test public void testNotRecentlyActive() throws Exception { new CloudWatchCollector( - "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName\n range_seconds: 12000", cloudWatchClient, taggingClient).register(registry); - - Mockito.when(cloudWatchClient.listMetrics((ListMetricsRequest)argThat( - new ListMetricsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancerName").RecentlyActive(null)))) - .thenReturn(ListMetricsResponse.builder().metrics( - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("a").build(), Dimension.builder().name("LoadBalancerName").value("myLB").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("a").build(), Dimension.builder().name("LoadBalancerName").value("myLB").build(), Dimension.builder().name("ThisExtraDimensionIsIgnored").value("dummy").build()).build(), - Metric.builder().dimensions(Dimension.builder().name("AvailabilityZone").value("b").build(), Dimension.builder().name("LoadBalancerName").value("myOtherLB").build()).build() - ).build()); - - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancerName", "myLB")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()).build()); - Mockito.when(cloudWatchClient.getMetricStatistics((GetMetricStatisticsRequest)argThat( - new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "b").Dimension("LoadBalancerName", "myOtherLB")))) - .thenReturn(GetMetricStatisticsResponse.builder().datapoints( - Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()).build()); - - registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance"}, new String[]{"aws_elb", ""}); - - - Mockito.verify(cloudWatchClient).listMetrics((ListMetricsRequest) argThat( - new ListMetricsRequestMatcher() - .RecentlyActive(null). - Namespace("AWS/ELB"). - MetricName("RequestCount"). - Dimensions("AvailabilityZone", "LoadBalancerName") - )); + "---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount\n aws_dimensions:\n - AvailabilityZone\n - LoadBalancerName\n range_seconds: 12000", + cloudWatchClient, + taggingClient) + .register(registry); + + Mockito.when( + cloudWatchClient.listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimensions("AvailabilityZone", "LoadBalancerName") + .RecentlyActive(null)))) + .thenReturn( + ListMetricsResponse.builder() + .metrics( + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("a").build(), + Dimension.builder().name("LoadBalancerName").value("myLB").build()) + .build(), + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("a").build(), + Dimension.builder().name("LoadBalancerName").value("myLB").build(), + Dimension.builder() + .name("ThisExtraDimensionIsIgnored") + .value("dummy") + .build()) + .build(), + Metric.builder() + .dimensions( + Dimension.builder().name("AvailabilityZone").value("b").build(), + Dimension.builder().name("LoadBalancerName").value("myOtherLB").build()) + .build()) + .build()); + + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "a") + .Dimension("LoadBalancerName", "myLB")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(2.0).build()) + .build()); + Mockito.when( + cloudWatchClient.getMetricStatistics( + (GetMetricStatisticsRequest) + argThat( + new GetMetricStatisticsRequestMatcher() + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimension("AvailabilityZone", "b") + .Dimension("LoadBalancerName", "myOtherLB")))) + .thenReturn( + GetMetricStatisticsResponse.builder() + .datapoints( + Datapoint.builder().timestamp(new Date().toInstant()).average(3.0).build()) + .build()); + + registry.getSampleValue( + "aws_elb_request_count_average", + new String[] {"job", "instance"}, + new String[] {"aws_elb", ""}); + + Mockito.verify(cloudWatchClient) + .listMetrics( + (ListMetricsRequest) + argThat( + new ListMetricsRequestMatcher() + .RecentlyActive(null) + .Namespace("AWS/ELB") + .MetricName("RequestCount") + .Dimensions("AvailabilityZone", "LoadBalancerName"))); } @Test @@ -756,11 +1749,15 @@ public void testBuildInfo() throws Exception { String buildVersion = properties.getProperty("BuildVersion"); String releaseDate = properties.getProperty("ReleaseDate"); - assertEquals(1L, - registry.getSampleValue("cloudwatch_exporter_build_info", - new String[]{"build_version", "release_date"}, - new String[]{buildVersion != null ? buildVersion: "unknown", - releaseDate != null ? releaseDate: "unknown"}), - .00001); + assertEquals( + 1L, + registry.getSampleValue( + "cloudwatch_exporter_build_info", + new String[] {"build_version", "release_date"}, + new String[] { + buildVersion != null ? buildVersion : "unknown", + releaseDate != null ? releaseDate : "unknown" + }), + .00001); } }