Collect cloudwatch stats using GetMetricData (#5544)
This commit is contained in:
@@ -6,46 +6,98 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatch"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdata/telegraf/filter"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type mockGatherCloudWatchClient struct{}
|
||||
|
||||
func (m *mockGatherCloudWatchClient) ListMetrics(params *cloudwatch.ListMetricsInput) (*cloudwatch.ListMetricsOutput, error) {
|
||||
metric := &cloudwatch.Metric{
|
||||
Namespace: params.Namespace,
|
||||
MetricName: aws.String("Latency"),
|
||||
Dimensions: []*cloudwatch.Dimension{
|
||||
return &cloudwatch.ListMetricsOutput{
|
||||
Metrics: []*cloudwatch.Metric{
|
||||
{
|
||||
Name: aws.String("LoadBalancerName"),
|
||||
Value: aws.String("p-example"),
|
||||
Namespace: params.Namespace,
|
||||
MetricName: aws.String("Latency"),
|
||||
Dimensions: []*cloudwatch.Dimension{
|
||||
{
|
||||
Name: aws.String("LoadBalancerName"),
|
||||
Value: aws.String("p-example"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result := &cloudwatch.ListMetricsOutput{
|
||||
Metrics: []*cloudwatch.Metric{metric},
|
||||
}
|
||||
return result, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *mockGatherCloudWatchClient) GetMetricStatistics(params *cloudwatch.GetMetricStatisticsInput) (*cloudwatch.GetMetricStatisticsOutput, error) {
|
||||
dataPoint := &cloudwatch.Datapoint{
|
||||
Timestamp: params.EndTime,
|
||||
Minimum: aws.Float64(0.1),
|
||||
Maximum: aws.Float64(0.3),
|
||||
Average: aws.Float64(0.2),
|
||||
Sum: aws.Float64(123),
|
||||
SampleCount: aws.Float64(100),
|
||||
Unit: aws.String("Seconds"),
|
||||
}
|
||||
result := &cloudwatch.GetMetricStatisticsOutput{
|
||||
Label: aws.String("Latency"),
|
||||
Datapoints: []*cloudwatch.Datapoint{dataPoint},
|
||||
}
|
||||
return result, nil
|
||||
func (m *mockGatherCloudWatchClient) GetMetricData(params *cloudwatch.GetMetricDataInput) (*cloudwatch.GetMetricDataOutput, error) {
|
||||
return &cloudwatch.GetMetricDataOutput{
|
||||
MetricDataResults: []*cloudwatch.MetricDataResult{
|
||||
{
|
||||
Id: aws.String("minimum_0_0"),
|
||||
Label: aws.String("latency_minimum"),
|
||||
StatusCode: aws.String("completed"),
|
||||
Timestamps: []*time.Time{
|
||||
params.EndTime,
|
||||
},
|
||||
Values: []*float64{
|
||||
aws.Float64(0.1),
|
||||
},
|
||||
},
|
||||
{
|
||||
Id: aws.String("maximum_0_0"),
|
||||
Label: aws.String("latency_maximum"),
|
||||
StatusCode: aws.String("completed"),
|
||||
Timestamps: []*time.Time{
|
||||
params.EndTime,
|
||||
},
|
||||
Values: []*float64{
|
||||
aws.Float64(0.3),
|
||||
},
|
||||
},
|
||||
{
|
||||
Id: aws.String("average_0_0"),
|
||||
Label: aws.String("latency_average"),
|
||||
StatusCode: aws.String("completed"),
|
||||
Timestamps: []*time.Time{
|
||||
params.EndTime,
|
||||
},
|
||||
Values: []*float64{
|
||||
aws.Float64(0.2),
|
||||
},
|
||||
},
|
||||
{
|
||||
Id: aws.String("sum_0_0"),
|
||||
Label: aws.String("latency_sum"),
|
||||
StatusCode: aws.String("completed"),
|
||||
Timestamps: []*time.Time{
|
||||
params.EndTime,
|
||||
},
|
||||
Values: []*float64{
|
||||
aws.Float64(123),
|
||||
},
|
||||
},
|
||||
{
|
||||
Id: aws.String("sample_count_0_0"),
|
||||
Label: aws.String("latency_sample_count"),
|
||||
StatusCode: aws.String("completed"),
|
||||
Timestamps: []*time.Time{
|
||||
params.EndTime,
|
||||
},
|
||||
Values: []*float64{
|
||||
aws.Float64(100),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestSnakeCase(t *testing.T) {
|
||||
assert.Equal(t, "cluster_name", snakeCase("Cluster Name"))
|
||||
assert.Equal(t, "broker_id", snakeCase("Broker ID"))
|
||||
}
|
||||
|
||||
func TestGather(t *testing.T) {
|
||||
@@ -64,7 +116,7 @@ func TestGather(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
c.client = &mockGatherCloudWatchClient{}
|
||||
|
||||
acc.GatherError(c.Gather)
|
||||
assert.NoError(t, acc.GatherError(c.Gather))
|
||||
|
||||
fields := map[string]interface{}{}
|
||||
fields["latency_minimum"] = 0.1
|
||||
@@ -74,13 +126,11 @@ func TestGather(t *testing.T) {
|
||||
fields["latency_sample_count"] = 100.0
|
||||
|
||||
tags := map[string]string{}
|
||||
tags["unit"] = "seconds"
|
||||
tags["region"] = "us-east-1"
|
||||
tags["load_balancer_name"] = "p-example"
|
||||
|
||||
assert.True(t, acc.HasMeasurement("cloudwatch_aws_elb"))
|
||||
acc.AssertContainsTaggedFields(t, "cloudwatch_aws_elb", fields, tags)
|
||||
|
||||
}
|
||||
|
||||
type mockSelectMetricsCloudWatchClient struct{}
|
||||
@@ -132,7 +182,7 @@ func (m *mockSelectMetricsCloudWatchClient) ListMetrics(params *cloudwatch.ListM
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (m *mockSelectMetricsCloudWatchClient) GetMetricStatistics(params *cloudwatch.GetMetricStatisticsInput) (*cloudwatch.GetMetricStatisticsOutput, error) {
|
||||
func (m *mockSelectMetricsCloudWatchClient) GetMetricData(params *cloudwatch.GetMetricDataInput) (*cloudwatch.GetMetricDataOutput, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -164,10 +214,10 @@ func TestSelectMetrics(t *testing.T) {
|
||||
},
|
||||
}
|
||||
c.client = &mockSelectMetricsCloudWatchClient{}
|
||||
metrics, err := SelectMetrics(c)
|
||||
filtered, err := getFilteredMetrics(c)
|
||||
// We've asked for 2 (out of 4) metrics, over all 3 load balancers in all 2
|
||||
// AZs. We should get 12 metrics.
|
||||
assert.Equal(t, 12, len(metrics))
|
||||
assert.Equal(t, 12, len(filtered[0].metrics))
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
@@ -199,25 +249,66 @@ func TestGenerateStatisticsInputParams(t *testing.T) {
|
||||
|
||||
c.updateWindow(now)
|
||||
|
||||
params := c.getStatisticsInput(m)
|
||||
statFilter, _ := filter.NewIncludeExcludeFilter(nil, nil)
|
||||
queries, _ := c.getDataQueries([]filteredMetric{{metrics: []*cloudwatch.Metric{m}, statFilter: statFilter}})
|
||||
params := c.getDataInputs(queries)
|
||||
|
||||
assert.EqualValues(t, *params.EndTime, now.Add(-c.Delay.Duration))
|
||||
assert.EqualValues(t, *params.StartTime, now.Add(-c.Period.Duration).Add(-c.Delay.Duration))
|
||||
assert.Len(t, params.Dimensions, 1)
|
||||
assert.Len(t, params.Statistics, 5)
|
||||
assert.EqualValues(t, *params.Period, 60)
|
||||
require.Len(t, params.MetricDataQueries, 5)
|
||||
assert.Len(t, params.MetricDataQueries[0].MetricStat.Metric.Dimensions, 1)
|
||||
assert.EqualValues(t, *params.MetricDataQueries[0].MetricStat.Period, 60)
|
||||
}
|
||||
|
||||
func TestGenerateStatisticsInputParamsFiltered(t *testing.T) {
|
||||
d := &cloudwatch.Dimension{
|
||||
Name: aws.String("LoadBalancerName"),
|
||||
Value: aws.String("p-example"),
|
||||
}
|
||||
|
||||
m := &cloudwatch.Metric{
|
||||
MetricName: aws.String("Latency"),
|
||||
Dimensions: []*cloudwatch.Dimension{d},
|
||||
}
|
||||
|
||||
duration, _ := time.ParseDuration("1m")
|
||||
internalDuration := internal.Duration{
|
||||
Duration: duration,
|
||||
}
|
||||
|
||||
c := &CloudWatch{
|
||||
Namespace: "AWS/ELB",
|
||||
Delay: internalDuration,
|
||||
Period: internalDuration,
|
||||
}
|
||||
|
||||
c.initializeCloudWatch()
|
||||
|
||||
now := time.Now()
|
||||
|
||||
c.updateWindow(now)
|
||||
|
||||
statFilter, _ := filter.NewIncludeExcludeFilter([]string{"average", "sample_count"}, nil)
|
||||
queries, _ := c.getDataQueries([]filteredMetric{{metrics: []*cloudwatch.Metric{m}, statFilter: statFilter}})
|
||||
params := c.getDataInputs(queries)
|
||||
|
||||
assert.EqualValues(t, *params.EndTime, now.Add(-c.Delay.Duration))
|
||||
assert.EqualValues(t, *params.StartTime, now.Add(-c.Period.Duration).Add(-c.Delay.Duration))
|
||||
require.Len(t, params.MetricDataQueries, 2)
|
||||
assert.Len(t, params.MetricDataQueries[0].MetricStat.Metric.Dimensions, 1)
|
||||
assert.EqualValues(t, *params.MetricDataQueries[0].MetricStat.Period, 60)
|
||||
}
|
||||
|
||||
func TestMetricsCacheTimeout(t *testing.T) {
|
||||
cache := &MetricCache{
|
||||
Metrics: []*cloudwatch.Metric{},
|
||||
Fetched: time.Now(),
|
||||
TTL: time.Minute,
|
||||
cache := &metricCache{
|
||||
metrics: []filteredMetric{},
|
||||
built: time.Now(),
|
||||
ttl: time.Minute,
|
||||
}
|
||||
|
||||
assert.True(t, cache.IsValid())
|
||||
cache.Fetched = time.Now().Add(-time.Minute)
|
||||
assert.False(t, cache.IsValid())
|
||||
assert.True(t, cache.isValid())
|
||||
cache.built = time.Now().Add(-time.Minute)
|
||||
assert.False(t, cache.isValid())
|
||||
}
|
||||
|
||||
func TestUpdateWindow(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user