Skip to content

Commit 5aa3d0c

Browse files
authored
[Metricbeat] Fix tags_filter for cloudwatch metricset in aws module (#18524)
* Fix tags_filter for cloudwatch metricset * if tags_filter is given, overwrite tags in cloudwatch specific config
1 parent a0788d7 commit 5aa3d0c

File tree

4 files changed

+70
-2
lines changed

4 files changed

+70
-2
lines changed

CHANGELOG.next.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ field. You can revert this change by configuring tags for the module and omittin
198198
- Fix overflow on Prometheus rates when new buckets are added on the go. {pull}17753[17753]
199199
- Remove specific win32 api errors from events in perfmon. {issue}18292[18292] {pull}18361[18361]
200200
- Fix application_pool metricset after pdh changes. {pull}18477[18477]
201+
- Fix tags_filter for cloudwatch metricset in aws. {pull}18524[18524]
201202

202203
*Packetbeat*
203204

x-pack/metricbeat/module/aws/aws.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ func NewMetricSet(base mb.BaseMetricSet) (*MetricSet, error) {
9090
TagsFilter: config.TagsFilter,
9191
}
9292

93+
base.Logger().Debug("Metricset level config for period: ", metricSet.Period)
94+
base.Logger().Debug("Metricset level config for tags filter: ", metricSet.TagsFilter)
95+
9396
// Get IAM account name
9497
awsConfig.Region = "us-east-1"
9598
svcIam := iam.New(awscommon.EnrichAWSConfigWithEndpoint(
@@ -129,11 +132,13 @@ func NewMetricSet(base mb.BaseMetricSet) (*MetricSet, error) {
129132
}
130133

131134
metricSet.RegionsList = completeRegionsList
135+
base.Logger().Debug("Metricset level config for regions: ", metricSet.RegionsList)
132136
return &metricSet, nil
133137
}
134138

135139
// Construct MetricSet with specific regions list from config
136140
metricSet.RegionsList = config.Regions
141+
base.Logger().Debug("Metricset level config for regions: ", metricSet.RegionsList)
137142
return &metricSet, nil
138143
}
139144

x-pack/metricbeat/module/aws/cloudwatch/cloudwatch.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ type namespaceDetail struct {
9595
// New creates a new instance of the MetricSet. New is responsible for unpacking
9696
// any MetricSet specific configuration options if there are any.
9797
func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
98+
logger := logp.NewLogger(metricsetName)
9899
metricSet, err := aws.NewMetricSet(base)
99100
if err != nil {
100101
return nil, errors.Wrap(err, "error creating aws metricset")
@@ -109,13 +110,14 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
109110
return nil, errors.Wrap(err, "error unpack raw module config using UnpackConfig")
110111
}
111112

113+
logger.Debugf("cloudwatch config = %s", config)
112114
if len(config.CloudwatchMetrics) == 0 {
113115
return nil, errors.New("metrics in config is missing")
114116
}
115117

116118
return &MetricSet{
117119
MetricSet: metricSet,
118-
logger: logp.NewLogger(metricsetName),
120+
logger: logger,
119121
CloudwatchConfigs: config.CloudwatchMetrics,
120122
}, nil
121123
}
@@ -288,6 +290,12 @@ func (m *MetricSet) readCloudwatchConfig() (listMetricWithDetail, map[string][]n
288290
resourceTypesWithTags := map[string][]aws.Tag{}
289291

290292
for _, config := range m.CloudwatchConfigs {
293+
// If tags_filter on metricset level is given, overwrite tags in
294+
// cloudwatch metrics with tags_filter.
295+
if m.MetricSet.TagsFilter != nil {
296+
config.Tags = m.MetricSet.TagsFilter
297+
}
298+
291299
// If there is no statistic method specified, then use the default.
292300
if config.Statistic == nil {
293301
config.Statistic = defaultStatistics
@@ -461,6 +469,8 @@ func (m *MetricSet) createEvents(svcCloudwatch cloudwatchiface.ClientAPI, svcRes
461469

462470
// Find a timestamp for all metrics in output
463471
timestamp := aws.FindTimestamp(metricDataResults)
472+
473+
// Create events when there is no tags_filter or tags.resource_type_filter specified.
464474
if len(resourceTypeTagFilters) == 0 {
465475
if !timestamp.IsZero() {
466476
for _, output := range metricDataResults {
@@ -492,8 +502,10 @@ func (m *MetricSet) createEvents(svcCloudwatch cloudwatchiface.ClientAPI, svcRes
492502
return events, nil
493503
}
494504

495-
// Get tags
505+
// Create events with tags
496506
for resourceType, tagsFilter := range resourceTypeTagFilters {
507+
m.logger.Debugf("resourceType = %s", resourceType)
508+
m.logger.Debugf("tagsFilter = %s", tagsFilter)
497509
resourceTagMap, err := aws.GetResourcesTags(svcResourceAPI, []string{resourceType})
498510
if err != nil {
499511
// If GetResourcesTags failed, continue report event just without tags.
@@ -507,8 +519,11 @@ func (m *MetricSet) createEvents(svcCloudwatch cloudwatchiface.ClientAPI, svcRes
507519
// filter resourceTagMap
508520
for identifier, tags := range resourceTagMap {
509521
if exists := aws.CheckTagFiltersExist(tagsFilter, tags); !exists {
522+
m.logger.Debugf("In region %s, service %s tags does not match tags_filter", regionName, identifier)
510523
delete(resourceTagMap, identifier)
524+
continue
511525
}
526+
m.logger.Debugf("In region %s, service %s tags match tags_filter", regionName, identifier)
512527
}
513528

514529
if !timestamp.IsZero() {
@@ -537,6 +552,12 @@ func (m *MetricSet) createEvents(svcCloudwatch cloudwatchiface.ClientAPI, svcRes
537552

538553
identifierValue := labels[identifierValueIdx]
539554
if _, ok := events[identifierValue]; !ok {
555+
// when tagsFilter is not empty but no entry in
556+
// resourceTagMap for this identifier, do not initialize
557+
// an event for this identifier.
558+
if len(tagsFilter) != 0 && resourceTagMap[identifierValue] == nil {
559+
continue
560+
}
540561
events[identifierValue] = aws.InitEvent(regionName, m.AccountName, m.AccountID)
541562
}
542563
events[identifierValue] = insertRootFields(events[identifierValue], output.Values[timestampIdx], labels)

x-pack/metricbeat/module/aws/cloudwatch/cloudwatch_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ func TestConstructLabel(t *testing.T) {
146146

147147
func TestReadCloudwatchConfig(t *testing.T) {
148148
m := MetricSet{}
149+
m.MetricSet = &aws.MetricSet{Period: 5}
149150
resourceTypeFiltersEC2 := map[string][]aws.Tag{}
150151
resourceTypeFiltersEC2["ec2:instance"] = nil
151152

@@ -1313,6 +1314,46 @@ func TestCreateEventsWithoutIdentifier(t *testing.T) {
13131314
assert.Equal(t, value2, dimension)
13141315
}
13151316

1317+
func TestCreateEventsWithTagsFilter(t *testing.T) {
1318+
m := MetricSet{}
1319+
m.CloudwatchConfigs = []Config{{Statistic: []string{"Average"}}}
1320+
m.MetricSet = &aws.MetricSet{Period: 5}
1321+
m.logger = logp.NewLogger("test")
1322+
1323+
mockTaggingSvc := &MockResourceGroupsTaggingClient{}
1324+
mockCloudwatchSvc := &MockCloudWatchClient{}
1325+
listMetricWithStatsTotal := []metricsWithStatistics{
1326+
{
1327+
cloudwatch.Metric{
1328+
Dimensions: []cloudwatch.Dimension{{
1329+
Name: awssdk.String("InstanceId"),
1330+
Value: awssdk.String("i-1"),
1331+
}},
1332+
MetricName: awssdk.String("CPUUtilization"),
1333+
Namespace: awssdk.String("AWS/EC2"),
1334+
},
1335+
[]string{"Average"},
1336+
[]aws.Tag{
1337+
{Key: "name", Value: "test-ec2"},
1338+
},
1339+
},
1340+
}
1341+
1342+
// Specify a tag filter that does not match the tag for i-1
1343+
resourceTypeTagFilters := map[string][]aws.Tag{}
1344+
resourceTypeTagFilters["ec2:instance"] = []aws.Tag{
1345+
{
1346+
Key: "name",
1347+
Value: "foo",
1348+
},
1349+
}
1350+
startTime, endTime := aws.GetStartTimeEndTime(m.MetricSet.Period)
1351+
1352+
events, err := m.createEvents(mockCloudwatchSvc, mockTaggingSvc, listMetricWithStatsTotal, resourceTypeTagFilters, regionName, startTime, endTime)
1353+
assert.NoError(t, err)
1354+
assert.Equal(t, 0, len(events))
1355+
}
1356+
13161357
func TestInsertTags(t *testing.T) {
13171358
identifier1 := "StandardStorage,test-s3-1"
13181359
identifier2 := "test-s3-2"

0 commit comments

Comments
 (0)