package io.prometheus.cloudwatch;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.argThat;
import com.amazonaws.services.cloudwatch.AmazonCloudWatchClient;
import com.amazonaws.services.cloudwatch.model.Datapoint;
import com.amazonaws.services.cloudwatch.model.Dimension;
import com.amazonaws.services.cloudwatch.model.DimensionFilter;
import com.amazonaws.services.cloudwatch.model.GetMetricStatisticsRequest;
import com.amazonaws.services.cloudwatch.model.GetMetricStatisticsResult;
import com.amazonaws.services.cloudwatch.model.ListMetricsRequest;
import com.amazonaws.services.cloudwatch.model.ListMetricsResult;
import com.amazonaws.services.cloudwatch.model.Metric;
import io.prometheus.client.CollectorRegistry;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import org.mockito.Mockito;
public class CloudWatchCollectorTest {
AmazonCloudWatchClient client;
CollectorRegistry registry;
@Before
public void setUp() {
client = Mockito.mock(AmazonCloudWatchClient.class);
registry = new CollectorRegistry();
}
class ListMetricsRequestMatcher extends ArgumentMatcher {
String namespace;
String metricName;
String nextToken;
List<DimensionFilter> dimensions = new ArrayList<DimensionFilter>();
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<DimensionFilter>();
for (int i = 0; i < dimensions.length; i++) {
this.dimensions.add(new DimensionFilter().withName(dimensions[i]));
}
return this;
}
public boolean matches(Object o) {
ListMetricsRequest request = (ListMetricsRequest) o;
if (request == null) return false;
if (namespace != null && !namespace.equals(request.getNamespace())){
return false;
}
if (metricName != null && !metricName.equals(request.getMetricName())){
return false;
}
if (nextToken == null ^ request.getNextToken() == null) {
return false;
}
if (nextToken != null && !nextToken.equals(request.getNextToken())) {
return false;
}
if (!dimensions.equals(request.getDimensions())) {
return false;
}
return true;
}
}
class GetMetricStatisticsRequestMatcher extends ArgumentMatcher {
String namespace;
String metricName;
List<Dimension> dimensions = new ArrayList<Dimension>();
Integer period;
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(new Dimension().withName(name).withValue(value));
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.getNamespace())){
return false;
}
if (metricName != null && !metricName.equals(request.getMetricName())){
return false;
}
if (!dimensions.equals(request.getDimensions())) {
return false;
}
if (period != null && !period.equals(request.getPeriod())) {
return false;
}
return true;
}
}
@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", client).register(registry);
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest) anyObject()))
.thenReturn(new GetMetricStatisticsResult());
registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance"}, new String[]{"aws_elb", ""});
Mockito.verify(client).getMetricStatistics((GetMetricStatisticsRequest) 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", client).register(registry);
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest) anyObject()))
.thenReturn(new GetMetricStatisticsResult());
registry.getSampleValue("aws_elb_request_count_average", new String[]{"job", "instance"}, new String[]{"aws_elb", ""});
Mockito.verify(client).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", client).register(registry);
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest)argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withAverage(1.0)
.withMaximum(2.0).withMinimum(3.0).withSampleCount(4.0).withSum(5.0)));
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 testUsesNewestDatapoint() throws Exception {
new CloudWatchCollector(
"---\nregion: reg\nmetrics:\n- aws_namespace: AWS/ELB\n aws_metric_name: RequestCount", client).register(registry);
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest)argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date(1)).withAverage(1.0),
new Datapoint().withTimestamp(new Date(3)).withAverage(3.0),
new Datapoint().withTimestamp(new Date(2)).withAverage(2.0)));
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", client).register(registry);
Mockito.when(client.listMetrics((ListMetricsRequest)argThat(
new ListMetricsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancerName"))))
.thenReturn(new ListMetricsResult().withMetrics(
new Metric().withDimensions(new Dimension().withName("AvailabilityZone").withValue("a"), new Dimension().withName("LoadBalancerName").withValue("myLB")),
new Metric().withDimensions(new Dimension().withName("AvailabilityZone").withValue("a"), new Dimension().withName("LoadBalancerName").withValue("myLB"), new Dimension().withName("ThisExtraDimensionIsIgnored").withValue("dummy")),
new Metric().withDimensions(new Dimension().withName("AvailabilityZone").withValue("b"), new Dimension().withName("LoadBalancerName").withValue("myOtherLB"))));
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest)argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancerName", "myLB"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withAverage(2.0)));
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest)argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "b").Dimension("LoadBalancerName", "myOtherLB"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withAverage(3.0)));
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", client).register(registry);
Mockito.when(client.listMetrics((ListMetricsRequest)argThat(
new ListMetricsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancerName"))))
.thenReturn(new ListMetricsResult().withMetrics(
new Metric().withDimensions(new Dimension().withName("AvailabilityZone").withValue("a"), new Dimension().withName("LoadBalancerName").withValue("myLB")),
new Metric().withDimensions(new Dimension().withName("AvailabilityZone").withValue("b"), new Dimension().withName("LoadBalancerName").withValue("myLB")),
new Metric().withDimensions(new Dimension().withName("AvailabilityZone").withValue("a"), new Dimension().withName("LoadBalancerName").withValue("myOtherLB"))));
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest)argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancerName", "myLB"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withAverage(2.0)));
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest)argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "b").Dimension("LoadBalancerName", "myLB"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withAverage(2.0)));
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(.*)", client).register(registry);
Mockito.when(client.listMetrics((ListMetricsRequest) argThat(
new ListMetricsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancerName"))))
.thenReturn(new ListMetricsResult().withMetrics(
new Metric().withDimensions(new Dimension().withName("AvailabilityZone").withValue("a"), new Dimension().withName("LoadBalancerName").withValue("myLB1")),
new Metric().withDimensions(new Dimension().withName("AvailabilityZone").withValue("b"), new Dimension().withName("LoadBalancerName").withValue("myLB2")),
new Metric().withDimensions(new Dimension().withName("AvailabilityZone").withValue("a"), new Dimension().withName("LoadBalancerName").withValue("myOtherLB"))));
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest) argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancerName", "myLB1"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withAverage(2.0)));
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest) argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "b").Dimension("LoadBalancerName", "myLB2"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withAverage(2.0)));
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", client).register(registry);
Mockito.when(client.listMetrics((ListMetricsRequest)argThat(
new ListMetricsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancerName"))))
.thenReturn(new ListMetricsResult().withNextToken("ABC"));
Mockito.when(client.listMetrics((ListMetricsRequest)argThat(
new ListMetricsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimensions("AvailabilityZone", "LoadBalancerName").NextToken("ABC"))))
.thenReturn(new ListMetricsResult().withMetrics(
new Metric().withDimensions(new Dimension().withName("AvailabilityZone").withValue("a"), new Dimension().withName("LoadBalancerName").withValue("myLB"))));
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest)argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("RequestCount").Dimension("AvailabilityZone", "a").Dimension("LoadBalancerName", "myLB"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withAverage(2.0)));
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 testGetMonitoringEndpoint() throws Exception {
CloudWatchCollector us_collector = new CloudWatchCollector("---\nregion: us-east-1\nmetrics: []\n");
assertEquals("https://monitoring.us-east-1.amazonaws.com", us_collector.getMonitoringEndpoint());
CloudWatchCollector cn_collector = new CloudWatchCollector("---\nregion: cn-north-1\nmetrics: []\n");
assertEquals("https://monitoring.cn-north-1.amazonaws.com.cn", cn_collector.getMonitoringEndpoint());
}
@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", client).register(registry);
HashMap<String, Double> extendedStatistics = new HashMap<String, Double>();
extendedStatistics.put("p95", 1.0);
extendedStatistics.put("p99.99", 2.0);
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest)argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/ELB").MetricName("Latency"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withExtendedStatistics(extendedStatistics)));
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", client).register(registry);
Mockito.when(client.listMetrics((ListMetricsRequest)argThat(
new ListMetricsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("ConsumedReadCapacityUnits").Dimensions("TableName", "GlobalSecondaryIndexName"))))
.thenReturn(new ListMetricsResult().withMetrics(
new Metric().withDimensions(new Dimension().withName("TableName").withValue("myTable"), new Dimension().withName("GlobalSecondaryIndexName").withValue("myIndex"))));
Mockito.when(client.listMetrics((ListMetricsRequest)argThat(
new ListMetricsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("OnlineIndexConsumedWriteCapacity").Dimensions("TableName", "GlobalSecondaryIndexName"))))
.thenReturn(new ListMetricsResult().withMetrics(
new Metric().withDimensions(new Dimension().withName("TableName").withValue("myTable"), new Dimension().withName("GlobalSecondaryIndexName").withValue("myIndex"))));
Mockito.when(client.listMetrics((ListMetricsRequest)argThat(
new ListMetricsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("ConsumedReadCapacityUnits").Dimensions("TableName"))))
.thenReturn(new ListMetricsResult().withMetrics(
new Metric().withDimensions(new Dimension().withName("TableName").withValue("myTable"))));
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest)argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("ConsumedReadCapacityUnits").Dimension("TableName", "myTable").Dimension("GlobalSecondaryIndexName", "myIndex"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withSum(1.0)));
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest)argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("OnlineIndexConsumedWriteCapacity").Dimension("TableName", "myTable").Dimension("GlobalSecondaryIndexName", "myIndex"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withSum(2.0)));
Mockito.when(client.getMetricStatistics((GetMetricStatisticsRequest)argThat(
new GetMetricStatisticsRequestMatcher().Namespace("AWS/DynamoDB").MetricName("ConsumedReadCapacityUnits").Dimension("TableName", "myTable"))))
.thenReturn(new GetMetricStatisticsResult().withDatapoints(
new Datapoint().withTimestamp(new Date()).withSum(3.0)));
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);
}
}