Skip to content

Commit aafbabe

Browse files
authored
Remove spans with ec2 metadata ip address from metrics (#1015)
*Issue #, if available:* ADOT SDK resource detectors by default have enabled a few AWS resource detector which will call EC2 metadata API endpoints. These activities have been captured by auto-instrumentation and generated AppSignals metrics. These calls should be present in traces, but not in metrics. *Description of changes:* Suppress AwsSpanMetricsProcessor from generating metrics when the RemoteService points to `169.254.169.254` *Testing* Deployed two EC2 instance with Java sample application and ADOT Java - `sample-application-2025-02-06-test`: ADOT Java with changes in this PR - `sample-application-2025-02-06`: Public latest ADOT Java *Traces:* Present from both EC2 instance ![image](https://github.com/user-attachments/assets/9c10a81d-0336-473f-81f3-9d4e61069401) ![image](https://github.com/user-attachments/assets/8be02cc9-dddb-4461-834e-98ad65d5a23f) *Metrics*: Present only for `sample-application-2025-02-06`: ![image](https://github.com/user-attachments/assets/97d29884-7133-47b5-aa0e-c5ac7a09cc3e) *Logs*: Present only for `sample-application-2025-02-06`: By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 2740c56 commit aafbabe

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessor.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static io.opentelemetry.semconv.SemanticAttributes.HTTP_RESPONSE_STATUS_CODE;
1919
import static io.opentelemetry.semconv.SemanticAttributes.HTTP_STATUS_CODE;
20+
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_SERVICE;
2021
import static software.amazon.opentelemetry.javaagent.providers.AwsSpanProcessingUtil.isKeyPresent;
2122

2223
import io.opentelemetry.api.common.Attributes;
@@ -61,6 +62,10 @@ public final class AwsSpanMetricsProcessor implements SpanProcessor {
6162
private static final int FAULT_CODE_LOWER_BOUND = 500;
6263
private static final int FAULT_CODE_UPPER_BOUND = 599;
6364

65+
// EC2 Metadata API IP Address
66+
// https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html#instancedata-inside-access
67+
private final String EC2_METADATA_API_IP = "169.254.169.254";
68+
6469
// Metric instruments
6570
private final LongHistogram errorHistogram;
6671
private final LongHistogram faultHistogram;
@@ -172,9 +177,18 @@ private void recordLatency(ReadableSpan span, Attributes attributes) {
172177

173178
private void recordMetrics(ReadableSpan span, SpanData spanData, Attributes attributes) {
174179
// Only record metrics if non-empty attributes are returned.
175-
if (!attributes.isEmpty()) {
180+
if (!attributes.isEmpty() && !isEc2MetadataSpan((attributes))) {
176181
recordErrorOrFault(spanData, attributes);
177182
recordLatency(span, attributes);
178183
}
179184
}
185+
186+
private boolean isEc2MetadataSpan(Attributes attributes) {
187+
if (attributes.get(AWS_REMOTE_SERVICE) != null
188+
&& attributes.get(AWS_REMOTE_SERVICE).equals(EC2_METADATA_API_IP)) {
189+
return true;
190+
}
191+
192+
return false;
193+
}
180194
}

awsagentprovider/src/test/java/software/amazon/opentelemetry/javaagent/providers/AwsSpanMetricsProcessorTest.java

+24
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static org.mockito.Mockito.verify;
2626
import static org.mockito.Mockito.verifyNoInteractions;
2727
import static org.mockito.Mockito.when;
28+
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_SERVICE;
2829
import static software.amazon.opentelemetry.javaagent.providers.MetricAttributeGenerator.DEPENDENCY_METRIC;
2930
import static software.amazon.opentelemetry.javaagent.providers.MetricAttributeGenerator.SERVICE_METRIC;
3031

@@ -378,6 +379,21 @@ public void testOnEndMetricsGenerationWithStatusDataOk() {
378379
validateMetricsGeneratedForStatusDataOk(600L, ExpectedStatusMetric.NEITHER);
379380
}
380381

382+
@Test
383+
public void testOnEndMetricsGenerationFromEc2MetadataApi() {
384+
Attributes spanAttributes = Attributes.of(AWS_REMOTE_SERVICE, "169.254.169.254");
385+
ReadableSpan readableSpanMock =
386+
buildReadableSpanMock(
387+
spanAttributes, SpanKind.CLIENT, SpanContext.getInvalid(), StatusData.unset());
388+
Map<String, Attributes> metricAttributesMap = buildEc2MetadataApiMetricAttributes();
389+
configureMocksForOnEnd(readableSpanMock, metricAttributesMap);
390+
391+
awsSpanMetricsProcessor.onEnd(readableSpanMock);
392+
verifyNoInteractions(errorHistogramMock);
393+
verifyNoInteractions(faultHistogramMock);
394+
verifyNoInteractions(latencyHistogramMock);
395+
}
396+
381397
private static Attributes buildSpanAttributes(boolean containsAttribute) {
382398
if (containsAttribute) {
383399
return Attributes.of(AttributeKey.stringKey("original key"), "original value");
@@ -404,6 +420,14 @@ private static Map<String, Attributes> buildMetricAttributes(
404420
return attributesMap;
405421
}
406422

423+
private static Map<String, Attributes> buildEc2MetadataApiMetricAttributes() {
424+
Map<String, Attributes> attributesMap = new HashMap<>();
425+
Attributes attributes =
426+
Attributes.of(AttributeKey.stringKey(AWS_REMOTE_SERVICE.toString()), "169.254.169.254");
427+
attributesMap.put(MetricAttributeGenerator.DEPENDENCY_METRIC, attributes);
428+
return attributesMap;
429+
}
430+
407431
private static ReadableSpan buildReadableSpanMock(Attributes spanAttributes) {
408432
return buildReadableSpanMock(spanAttributes, SpanKind.SERVER, null, StatusData.unset());
409433
}

0 commit comments

Comments
 (0)