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..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 @@ -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; @@ -172,9 +177,18 @@ 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(Attributes attributes) { + if (attributes.get(AWS_REMOTE_SERVICE) != null + && attributes.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()); }