From ff3554b701c7b7cfe386049a14965ba2767acc82 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 6 Feb 2025 16:30:02 -0800 Subject: [PATCH 1/2] Remove spans with ec2 metadata ip address from metrics --- .../providers/AwsSpanMetricsProcessor.java | 25 +++++++++++++++++-- .../AwsSpanMetricsProcessorTest.java | 24 ++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessor.java b/awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessor.java index b8479dbedd..0c62500817 100644 --- a/awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessor.java +++ b/awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessor.java @@ -17,6 +17,7 @@ import static io.opentelemetry.semconv.SemanticAttributes.HTTP_RESPONSE_STATUS_CODE; import static io.opentelemetry.semconv.SemanticAttributes.HTTP_STATUS_CODE; +import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_SERVICE; import static software.amazon.opentelemetry.javaagent.providers.AwsSpanProcessingUtil.isKeyPresent; import io.opentelemetry.api.common.Attributes; @@ -61,6 +62,10 @@ public final class AwsSpanMetricsProcessor implements SpanProcessor { private static final int FAULT_CODE_LOWER_BOUND = 500; private static final int FAULT_CODE_UPPER_BOUND = 599; + // EC2 Metadata API IP Address + // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html#instancedata-inside-access + private final String EC2_METADATA_API_IP = "169.254.169.254"; + // Metric instruments private final LongHistogram errorHistogram; private final LongHistogram faultHistogram; @@ -117,8 +122,10 @@ public void onEnd(ReadableSpan span) { Map attributeMap = generator.generateMetricAttributeMapFromSpan(spanData, resource); - for (Map.Entry attribute : attributeMap.entrySet()) { - recordMetrics(span, spanData, attribute.getValue()); + if (!isEc2MetadataSpan(attributeMap)) { + for (Map.Entry attribute : attributeMap.entrySet()) { + recordMetrics(span, spanData, attribute.getValue()); + } } } @@ -177,4 +184,18 @@ private void recordMetrics(ReadableSpan span, SpanData spanData, Attributes attr recordLatency(span, attributes); } } + + private boolean isEc2MetadataSpan(Map attributeMap) { + if (attributeMap.get(MetricAttributeGenerator.DEPENDENCY_METRIC) != null + && attributeMap.get(MetricAttributeGenerator.DEPENDENCY_METRIC).get(AWS_REMOTE_SERVICE) + != null + && attributeMap + .get(MetricAttributeGenerator.DEPENDENCY_METRIC) + .get(AWS_REMOTE_SERVICE) + .equals(EC2_METADATA_API_IP)) { + return true; + } + + return false; + } } diff --git a/awsagentprovider/src/test/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessorTest.java b/awsagentprovider/src/test/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessorTest.java index 16fc889cec..65bba3a513 100644 --- a/awsagentprovider/src/test/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessorTest.java +++ b/awsagentprovider/src/test/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessorTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; +import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_SERVICE; import static software.amazon.opentelemetry.javaagent.providers.MetricAttributeGenerator.DEPENDENCY_METRIC; import static software.amazon.opentelemetry.javaagent.providers.MetricAttributeGenerator.SERVICE_METRIC; @@ -378,6 +379,21 @@ public void testOnEndMetricsGenerationWithStatusDataOk() { validateMetricsGeneratedForStatusDataOk(600L, ExpectedStatusMetric.NEITHER); } + @Test + public void testOnEndMetricsGenerationFromEc2MetadataApi() { + Attributes spanAttributes = Attributes.of(AWS_REMOTE_SERVICE, "169.254.169.254"); + ReadableSpan readableSpanMock = + buildReadableSpanMock( + spanAttributes, SpanKind.CLIENT, SpanContext.getInvalid(), StatusData.unset()); + Map metricAttributesMap = buildEc2MetadataApiMetricAttributes(); + configureMocksForOnEnd(readableSpanMock, metricAttributesMap); + + awsSpanMetricsProcessor.onEnd(readableSpanMock); + verifyNoInteractions(errorHistogramMock); + verifyNoInteractions(faultHistogramMock); + verifyNoInteractions(latencyHistogramMock); + } + private static Attributes buildSpanAttributes(boolean containsAttribute) { if (containsAttribute) { return Attributes.of(AttributeKey.stringKey("original key"), "original value"); @@ -404,6 +420,14 @@ private static Map buildMetricAttributes( return attributesMap; } + private static Map buildEc2MetadataApiMetricAttributes() { + Map attributesMap = new HashMap<>(); + Attributes attributes = + Attributes.of(AttributeKey.stringKey(AWS_REMOTE_SERVICE.toString()), "169.254.169.254"); + attributesMap.put(MetricAttributeGenerator.DEPENDENCY_METRIC, attributes); + return attributesMap; + } + private static ReadableSpan buildReadableSpanMock(Attributes spanAttributes) { return buildReadableSpanMock(spanAttributes, SpanKind.SERVER, null, StatusData.unset()); } From c17a1243f8209d008a2f3b71bd517e5c1351ffce Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 10 Feb 2025 15:03:37 -0800 Subject: [PATCH 2/2] Move EC2 Metadata Span Check --- .../providers/AwsSpanMetricsProcessor.java | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessor.java b/awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessor.java index 0c62500817..c2f133a48d 100644 --- a/awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessor.java +++ b/awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessor.java @@ -122,10 +122,8 @@ public void onEnd(ReadableSpan span) { Map attributeMap = generator.generateMetricAttributeMapFromSpan(spanData, resource); - if (!isEc2MetadataSpan(attributeMap)) { - for (Map.Entry attribute : attributeMap.entrySet()) { - recordMetrics(span, spanData, attribute.getValue()); - } + for (Map.Entry attribute : attributeMap.entrySet()) { + recordMetrics(span, spanData, attribute.getValue()); } } @@ -179,20 +177,15 @@ private void recordLatency(ReadableSpan span, Attributes attributes) { private void recordMetrics(ReadableSpan span, SpanData spanData, Attributes attributes) { // Only record metrics if non-empty attributes are returned. - if (!attributes.isEmpty()) { + if (!attributes.isEmpty() && !isEc2MetadataSpan((attributes))) { recordErrorOrFault(spanData, attributes); recordLatency(span, attributes); } } - private boolean isEc2MetadataSpan(Map attributeMap) { - if (attributeMap.get(MetricAttributeGenerator.DEPENDENCY_METRIC) != null - && attributeMap.get(MetricAttributeGenerator.DEPENDENCY_METRIC).get(AWS_REMOTE_SERVICE) - != null - && attributeMap - .get(MetricAttributeGenerator.DEPENDENCY_METRIC) - .get(AWS_REMOTE_SERVICE) - .equals(EC2_METADATA_API_IP)) { + private boolean isEc2MetadataSpan(Attributes attributes) { + if (attributes.get(AWS_REMOTE_SERVICE) != null + && attributes.get(AWS_REMOTE_SERVICE).equals(EC2_METADATA_API_IP)) { return true; }