Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AWS] Add tags to events based on parsed identifier #33472

Merged
merged 4 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ https://github.com/elastic/beats/compare/v8.2.0\...main[Check the HEAD diff]
- Add GCP CloudSQL region filter {pull}32943[32943]
- Fix logstash cgroup mappings {pull}33131[33131]
- Remove unused `elasticsearch.node_stats.indices.bulk.avg_time.bytes` mapping {pull}33263[33263]
- Add tags to events based on parsed identifier. {pull}33472[33472]

*Packetbeat*

Expand Down
63 changes: 31 additions & 32 deletions x-pack/metricbeat/module/aws/cloudwatch/cloudwatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,19 +565,26 @@ func (m *MetricSet) createEvents(svcCloudwatch cloudwatch.GetMetricDataAPIClient

identifierValue := labels[identifierValueIdx]
uniqueIdentifierValue := *output.Label + fmt.Sprint("-", valI)
if _, ok := events[uniqueIdentifierValue]; !ok {
// when tagsFilter is not empty but no entry in
// resourceTagMap for this identifier, do not initialize
// an event for this identifier.
if len(tagsFilter) != 0 && resourceTagMap[identifierValue] == nil {
continue
}
events[uniqueIdentifierValue] = aws.InitEvent(regionName, m.AccountName, m.AccountID, output.Timestamps[valI])
}
events[uniqueIdentifierValue] = insertRootFields(events[uniqueIdentifierValue], metricDataResultValue, labels)

// add tags to event based on identifierValue
insertTags(events, uniqueIdentifierValue, identifierValue, resourceTagMap)
// Check if identifier includes dimensionSeparator (comma in this case),
// split the identifier and check for each sub-identifier.
// For example, identifier might be [storageType, s3BucketName].
// And tags are only store under s3BucketName in resourceTagMap.
subIdentifiers := strings.Split(identifierValue, dimensionSeparator)
for _, subIdentifier := range subIdentifiers {
if _, ok := events[uniqueIdentifierValue]; !ok {
// when tagsFilter is not empty but no entry in
// resourceTagMap for this identifier, do not initialize
// an event for this identifier.
if len(tagsFilter) != 0 && resourceTagMap[subIdentifier] == nil {
continue
}
events[uniqueIdentifierValue] = aws.InitEvent(regionName, m.AccountName, m.AccountID, output.Timestamps[valI])
}
events[uniqueIdentifierValue] = insertRootFields(events[uniqueIdentifierValue], metricDataResultValue, labels)
insertTags(events, uniqueIdentifierValue, subIdentifier, resourceTagMap)
}
}
}
}
Expand Down Expand Up @@ -617,28 +624,20 @@ func compareAWSDimensions(dim1 []types.Dimension, dim2 []types.Dimension) bool {
return reflect.DeepEqual(dim1NameToValue, dim2NameToValue)
}

func insertTags(events map[string]mb.Event, uniqueIdentifierValue string, identifier string, resourceTagMap map[string][]resourcegroupstaggingapitypes.Tag) {
// Check if identifier includes dimensionSeparator (comma in this case),
// split the identifier and check for each sub-identifier.
// For example, identifier might be [storageType, s3BucketName].
// And tags are only store under s3BucketName in resourceTagMap.
subIdentifiers := strings.Split(identifier, dimensionSeparator)
for _, v := range subIdentifiers {
tags := resourceTagMap[v]
// some metric dimension values are arn format, eg: AWS/DDOS namespace metric
if len(tags) == 0 && strings.HasPrefix(v, "arn:") {
resourceID, err := aws.FindShortIdentifierFromARN(v)
if err == nil {
tags = resourceTagMap[resourceID]
}
func insertTags(events map[string]mb.Event, uniqueIdentifierValue string, subIdentifier string, resourceTagMap map[string][]resourcegroupstaggingapitypes.Tag) {
tags := resourceTagMap[subIdentifier]
// some metric dimension values are arn format, eg: AWS/DDOS namespace metric
if len(tags) == 0 && strings.HasPrefix(subIdentifier, "arn:") {
resourceID, err := aws.FindShortIdentifierFromARN(subIdentifier)
if err == nil {
tags = resourceTagMap[resourceID]
}
if len(tags) != 0 {
// By default, replace dot "." using underscore "_" for tag keys.
// Note: tag values are not dedotted.
for _, tag := range tags {
_, _ = events[uniqueIdentifierValue].RootFields.Put("aws.tags."+common.DeDot(*tag.Key), *tag.Value)
}
continue
}
if len(tags) != 0 {
// By default, replace dot "." using underscore "_" for tag keys.
// Note: tag values are not dedotted.
for _, tag := range tags {
_, _ = events[uniqueIdentifierValue].RootFields.Put("aws.tags."+common.DeDot(*tag.Key), *tag.Value)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package cloudwatch
import (
"context"
"errors"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -1646,7 +1647,10 @@ func TestInsertTags(t *testing.T) {

for _, c := range cases {
t.Run(c.title, func(t *testing.T) {
insertTags(events, c.identifier, c.identifier, resourceTagMap)
subIdentifiers := strings.Split(c.identifier, dimensionSeparator)
for _, subIdentifier := range subIdentifiers {
insertTags(events, c.identifier, subIdentifier, resourceTagMap)
}
value, err := events[c.identifier].RootFields.GetValue(c.expectedTagKey)
assert.NoError(t, err)
assert.Equal(t, c.expectedTagValue, value)
Expand Down