-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Add support for 1-second Storage Resolution in the AWS EMF Exporter #36057
Changes from 4 commits
2d92ca8
a29de76
856c373
0bc7132
111d623
ea995d4
891e660
55a2416
bb7e1a0
ce5b86d
74e2e30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,8 @@ import ( | |
"encoding/json" | ||
"fmt" | ||
"reflect" | ||
"regexp" | ||
"strconv" | ||
"time" | ||
|
||
"go.opentelemetry.io/collector/pdata/pmetric" | ||
|
@@ -29,6 +31,11 @@ const ( | |
prometheusReceiver = "prometheus" | ||
attributeReceiver = "receiver" | ||
fieldPrometheusMetricType = "prom_metric_type" | ||
|
||
// metric attributes for AWS EMF, not to be treated as metric labels | ||
// emfAttributeFilterRE = regexp.MustCompile("^awsemf.[A-Za-z_]*$") | ||
emfAttributeFilter = "^awsemf.[A-Za-z_]*$" | ||
emfStorageResolutionAttribute = "aws.emf.storage_resolution" | ||
) | ||
|
||
var fieldPrometheusTypes = map[pmetric.MetricType]string{ | ||
|
@@ -45,10 +52,16 @@ type cWMetrics struct { | |
fields map[string]any | ||
} | ||
|
||
type cWMetricInfo struct { | ||
Name string | ||
Unit string | ||
StorageResolution int | ||
} | ||
|
||
type cWMeasurement struct { | ||
Namespace string | ||
Dimensions [][]string | ||
Metrics []map[string]string | ||
Metrics []cWMetricInfo | ||
} | ||
|
||
type cWMetricStats struct { | ||
|
@@ -156,7 +169,7 @@ func (mt metricTranslator) translateOTelToGroupedMetric(rm pmetric.ResourceMetri | |
|
||
// translateGroupedMetricToCWMetric converts Grouped Metric format to CloudWatch Metric format. | ||
func translateGroupedMetricToCWMetric(groupedMetric *groupedMetric, config *Config) *cWMetrics { | ||
labels := groupedMetric.labels | ||
labels := filterAWSEMFAttributes(groupedMetric.labels) | ||
fieldsLength := len(labels) + len(groupedMetric.metrics) | ||
|
||
isPrometheusMetric := groupedMetric.metadata.receiver == prometheusReceiver | ||
|
@@ -198,7 +211,7 @@ func translateGroupedMetricToCWMetric(groupedMetric *groupedMetric, config *Conf | |
|
||
// groupedMetricToCWMeasurement creates a single CW Measurement from a grouped metric. | ||
func groupedMetricToCWMeasurement(groupedMetric *groupedMetric, config *Config) cWMeasurement { | ||
labels := groupedMetric.labels | ||
labels := filterAWSEMFAttributes(groupedMetric.labels) | ||
dimensionRollupOption := config.DimensionRollupOption | ||
|
||
// Create a dimension set containing list of label names | ||
|
@@ -208,8 +221,13 @@ func groupedMetricToCWMeasurement(groupedMetric *groupedMetric, config *Config) | |
dimSet[idx] = labelName | ||
idx++ | ||
} | ||
|
||
fmt.Printf("##--## Dim Set: %+v\n", dimSet) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove the debug logs |
||
dimensions := [][]string{dimSet} | ||
|
||
fmt.Printf("##--## Dimensions: %+v", dimensions) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
||
|
||
// Apply single/zero dimension rollup to labels | ||
rollupDimensionArray := dimensionRollup(dimensionRollupOption, labels) | ||
|
||
|
@@ -228,14 +246,22 @@ func groupedMetricToCWMeasurement(groupedMetric *groupedMetric, config *Config) | |
// Add on rolled-up dimensions | ||
dimensions = append(dimensions, rollupDimensionArray...) | ||
|
||
metrics := make([]map[string]string, len(groupedMetric.metrics)) | ||
fmt.Printf("##--## Post Dimensions: %+v", dimensions) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
||
|
||
metrics := make([]cWMetricInfo, len(groupedMetric.metrics)) | ||
idx = 0 | ||
for metricName, metricInfo := range groupedMetric.metrics { | ||
metrics[idx] = map[string]string{ | ||
"Name": metricName, | ||
metrics[idx] = cWMetricInfo{ | ||
Name: metricName, | ||
StorageResolution: 60, | ||
} | ||
if metricInfo.unit != "" { | ||
metrics[idx]["Unit"] = metricInfo.unit | ||
metrics[idx].Unit = metricInfo.unit | ||
} | ||
if storRes, ok := groupedMetric.labels[emfStorageResolutionAttribute]; ok { | ||
if storResInt, err := strconv.Atoi(storRes); err == nil { | ||
metrics[idx].StorageResolution = storResInt | ||
} | ||
} | ||
idx++ | ||
} | ||
|
@@ -250,7 +276,7 @@ func groupedMetricToCWMeasurement(groupedMetric *groupedMetric, config *Config) | |
// groupedMetricToCWMeasurementsWithFilters filters the grouped metric using the given list of metric | ||
// declarations and returns the corresponding list of CW Measurements. | ||
func groupedMetricToCWMeasurementsWithFilters(groupedMetric *groupedMetric, config *Config) (cWMeasurements []cWMeasurement) { | ||
labels := groupedMetric.labels | ||
labels := filterAWSEMFAttributes(groupedMetric.labels) | ||
|
||
// Filter metric declarations by labels | ||
metricDeclarations := make([]*MetricDeclaration, 0, len(config.MetricDeclarations)) | ||
|
@@ -278,7 +304,7 @@ func groupedMetricToCWMeasurementsWithFilters(groupedMetric *groupedMetric, conf | |
// Group metrics by matched metric declarations | ||
type metricDeclarationGroup struct { | ||
metricDeclIdxList []int | ||
metrics []map[string]string | ||
metrics []cWMetricInfo | ||
} | ||
|
||
metricDeclGroups := make(map[string]*metricDeclarationGroup) | ||
|
@@ -299,19 +325,25 @@ func groupedMetricToCWMeasurementsWithFilters(groupedMetric *groupedMetric, conf | |
continue | ||
} | ||
|
||
metric := map[string]string{ | ||
"Name": metricName, | ||
metric := cWMetricInfo{ | ||
Name: metricName, | ||
StorageResolution: 60, | ||
} | ||
if metricInfo.unit != "" { | ||
metric["Unit"] = metricInfo.unit | ||
metric.Unit = metricInfo.unit | ||
} | ||
if storRes, ok := groupedMetric.labels[emfStorageResolutionAttribute]; ok { | ||
if storResInt, err := strconv.Atoi(storRes); err == nil { | ||
metric.StorageResolution = storResInt | ||
} | ||
} | ||
metricDeclKey := fmt.Sprint(metricDeclIdx) | ||
if group, ok := metricDeclGroups[metricDeclKey]; ok { | ||
group.metrics = append(group.metrics, metric) | ||
} else { | ||
metricDeclGroups[metricDeclKey] = &metricDeclarationGroup{ | ||
metricDeclIdxList: metricDeclIdx, | ||
metrics: []map[string]string{metric}, | ||
metrics: []cWMetricInfo{metric}, | ||
} | ||
} | ||
} | ||
|
@@ -467,3 +499,15 @@ func translateGroupedMetricToEmf(groupedMetric *groupedMetric, config *Config, d | |
|
||
return event, nil | ||
} | ||
|
||
func filterAWSEMFAttributes(labels map[string]string) map[string]string { | ||
// remove any labels that are attributes specific to AWS EMF Exporter | ||
filteredLabels := make(map[string]string) | ||
emfAttributeFilterRE := regexp.MustCompile(emfAttributeFilter) | ||
for labelName := range labels { | ||
if !emfAttributeFilterRE.MatchString(labelName) { | ||
filteredLabels[labelName] = labels[labelName] | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm concerned about the performance impact of applying regex matching on every metric attribute for each grouped metric data point. |
||
return filteredLabels | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
q: why regex rule is
^awsemf.[A-Za-z_]*$
instead of^aws.emf.[A-Za-z_]*$
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @mxiamxia - I've swapped the more complex regex for a simpler comparison operator. As new metric attributes are added this can be expanded to a switch statement which will likely still perform better than a compiled regex.