diff --git a/exporter/awsemfexporter/grouped_metric.go b/exporter/awsemfexporter/grouped_metric.go index dd3426cdc2e9..7b2319bb2e2c 100644 --- a/exporter/awsemfexporter/grouped_metric.go +++ b/exporter/awsemfexporter/grouped_metric.go @@ -5,6 +5,8 @@ package awsemfexporter // import "github.com/open-telemetry/opentelemetry-collec import ( "encoding/json" + "errors" + "reflect" "strings" "go.opentelemetry.io/collector/pdata/pmetric" @@ -77,9 +79,13 @@ func addToGroupedMetric( } } + unit, val, err := translateUnit(pmd, descriptor, dp.value) + if err != nil { + config.logger.Warn("failed to translate unit", zap.Error(err)) + } metric := &metricInfo{ - value: dp.value, - unit: translateUnit(pmd, descriptor), + value: val, + unit: unit, } if dp.timestampMs > 0 { @@ -186,14 +192,28 @@ func mapGetHelper(labels map[string]string, key string) string { return "" } -func translateUnit(metric pmetric.Metric, descriptor map[string]MetricDescriptor) string { +func translateUnit(metric pmetric.Metric, descriptor map[string]MetricDescriptor, value any) (string, any, error) { unit := metric.Unit() if descriptor, exists := descriptor[metric.Name()]; exists { if unit == "" || descriptor.Overwrite { - return descriptor.Unit + return descriptor.Unit, value, nil } } switch unit { + case "1": + unit = "Count" + case "ns": + // CloudWatch doesn't support Nanoseconds + switch v := value.(type) { + case int: + return "Microseconds", v / 1000, nil + case int64: + return "Microseconds", v / 1000, nil + case float64: + return "Microseconds", v / 1000, nil + default: + return unit, value, errors.New("Failed to convert ns to us with type " + reflect.TypeOf(value).String()) + } case "ms": unit = "Milliseconds" case "s": @@ -202,8 +222,8 @@ func translateUnit(metric pmetric.Metric, descriptor map[string]MetricDescriptor unit = "Microseconds" case "By": unit = "Bytes" - case "Bi": + case "bit": unit = "Bits" } - return unit + return unit, value, nil } diff --git a/exporter/awsemfexporter/grouped_metric_test.go b/exporter/awsemfexporter/grouped_metric_test.go index d2b1a86610f0..a930b9a8104a 100644 --- a/exporter/awsemfexporter/grouped_metric_test.go +++ b/exporter/awsemfexporter/grouped_metric_test.go @@ -487,25 +487,41 @@ func TestTranslateUnit(t *testing.T) { } translateUnitCases := map[string]string{ - "Count": "Count", - "ms": "Milliseconds", - "s": "Seconds", - "us": "Microseconds", - "By": "Bytes", - "Bi": "Bits", + "raw": "raw", + "1": "Count", + "ms": "Milliseconds", + "ns": "Microseconds", + "s": "Seconds", + "us": "Microseconds", + "By": "Bytes", + "bit": "Bits", } for input, output := range translateUnitCases { t.Run(input, func(_ *testing.T) { metric.SetUnit(input) - v := translateUnit(metric, translator.metricDescriptor) - assert.Equal(t, output, v) + convertedUnit, data, err := translateUnit(metric, translator.metricDescriptor, 1000) + if err != nil { + assert.Error(t, err) + } else { + assert.Equal(t, output, convertedUnit) + if input == "ns" { + assert.Equal(t, 1, data) + } + } }) } metric.SetName("forceOverwrite") - v := translateUnit(metric, translator.metricDescriptor) - assert.Equal(t, "Count", v) + convertedUnit, _, _ := translateUnit(metric, translator.metricDescriptor, 1) + assert.Equal(t, "Count", convertedUnit) + + metric.SetName("failedConversion") + metric.SetUnit("ns") + convertedUnit, data, err := translateUnit(metric, translator.metricDescriptor, "any") + assert.NotNil(t, err) + assert.Equal(t, "ns", convertedUnit) + assert.Equal(t, "any", data) } func generateTestMetricMetadata(namespace string, timestamp int64, logGroup, logStreamName, instrumentationScopeName string, metricType pmetric.MetricType) cWMetricMetadata {