diff --git a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/exporter/aws/metrics/aws_cloudwatch_emf_exporter.py b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/exporter/aws/metrics/aws_cloudwatch_emf_exporter.py index 643897da0..168ac7df1 100644 --- a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/exporter/aws/metrics/aws_cloudwatch_emf_exporter.py +++ b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/exporter/aws/metrics/aws_cloudwatch_emf_exporter.py @@ -509,11 +509,13 @@ def _create_emf_log( for name, value in all_attributes.items(): emf_log[name] = str(value) - # Add the single dimension set to CloudWatch Metrics if we have dimensions and metrics - if dimension_names and metric_definitions: - emf_log["_aws"]["CloudWatchMetrics"].append( - {"Namespace": self.namespace, "Dimensions": [dimension_names], "Metrics": metric_definitions} - ) + # Add CloudWatch Metrics if we have metrics, include dimensions only if they exist + if metric_definitions: + cloudwatch_metric = {"Namespace": self.namespace, "Metrics": metric_definitions} + if dimension_names: + cloudwatch_metric["Dimensions"] = [dimension_names] + + emf_log["_aws"]["CloudWatchMetrics"].append(cloudwatch_metric) return emf_log diff --git a/aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/exporter/aws/metrics/test_aws_cloudwatch_emf_exporter.py b/aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/exporter/aws/metrics/test_aws_cloudwatch_emf_exporter.py index 9a90c56a5..d6a5903af 100644 --- a/aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/exporter/aws/metrics/test_aws_cloudwatch_emf_exporter.py +++ b/aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/exporter/aws/metrics/test_aws_cloudwatch_emf_exporter.py @@ -391,9 +391,38 @@ def test_create_emf_log_with_resource(self): # Check CloudWatch metrics structure cw_metrics = result["_aws"]["CloudWatchMetrics"][0] self.assertEqual(cw_metrics["Namespace"], "TestNamespace") + self.assertIn("Dimensions", cw_metrics) self.assertEqual(set(cw_metrics["Dimensions"][0]), {"env", "service"}) self.assertEqual(cw_metrics["Metrics"][0]["Name"], "gauge_metric") + def test_create_emf_log_without_dimensions(self): + """Test EMF log creation with metrics but no dimensions.""" + # Create test record without attributes (no dimensions) + gauge_record = self.exporter._create_metric_record("gauge_metric", "Count", "Gauge") + gauge_record.value = 75.0 + gauge_record.timestamp = int(time.time() * 1000) + gauge_record.attributes = {} # No attributes = no dimensions + + records = [gauge_record] + resource = Resource.create({"service.name": "test-service"}) + + result = self.exporter._create_emf_log(records, resource, 1234567890) + + # Verify EMF log structure + self.assertIn("_aws", result) + self.assertIn("CloudWatchMetrics", result["_aws"]) + self.assertEqual(result["_aws"]["Timestamp"], 1234567890) + self.assertEqual(result["Version"], "1") + + # Check metric value + self.assertEqual(result["gauge_metric"], 75.0) + + # Check CloudWatch metrics structure - should have metrics but no dimensions + cw_metrics = result["_aws"]["CloudWatchMetrics"][0] + self.assertEqual(cw_metrics["Namespace"], "TestNamespace") + self.assertNotIn("Dimensions", cw_metrics) # No dimensions should be present + self.assertEqual(cw_metrics["Metrics"][0]["Name"], "gauge_metric") + def test_create_emf_log_skips_empty_metric_names(self): """Test that EMF log creation skips records with empty metric names.""" # Create a record with no metric name