From 3daa168183a490d055029bdcee3dec613d3dea1b Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 7 Feb 2025 10:16:36 -0800 Subject: [PATCH] Remove spans with ec2 metadata ip address from metrics --- .../src/aws-span-metrics-processor.ts | 19 +++++++++++---- .../test/aws-span-metrics-processor.test.ts | 23 +++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-span-metrics-processor.ts b/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-span-metrics-processor.ts index 48e1f59d..7da0a0a2 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-span-metrics-processor.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-span-metrics-processor.ts @@ -5,8 +5,9 @@ import { AttributeValue, Attributes, Context, Histogram, SpanStatusCode } from ' import { Resource } from '@opentelemetry/resources'; import { ReadableSpan, Span, SpanProcessor } from '@opentelemetry/sdk-trace-base'; import { SEMATTRS_HTTP_STATUS_CODE } from '@opentelemetry/semantic-conventions'; -import { AttributeMap, MetricAttributeGenerator } from './metric-attribute-generator'; +import { AttributeMap, DEPENDENCY_METRIC, MetricAttributeGenerator } from './metric-attribute-generator'; import { ForceFlushFunction } from './aws-span-processing-util'; +import { AWS_ATTRIBUTE_KEYS } from './aws-attribute-keys'; /** * This processor will generate metrics based on span data. It depends on a @@ -33,6 +34,10 @@ export class AwsSpanMetricsProcessor implements SpanProcessor { private FAULT_CODE_LOWER_BOUND: number = 500; private FAULT_CODE_UPPER_BOUND: number = 599; + // EC2 Metadata API IP Address + // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html#instancedata-inside-access + private EC2_METADATA_API_IP: string = '169.254.169.254'; + // Metric instruments private errorHistogram: Histogram; private faultHistogram: Histogram; @@ -83,8 +88,10 @@ export class AwsSpanMetricsProcessor implements SpanProcessor { public onEnd(span: ReadableSpan): void { const attributeMap: AttributeMap = this.generator.generateMetricAttributeMapFromSpan(span, this.resource); - for (const attribute in attributeMap) { - this.recordMetrics(span, attributeMap[attribute]); + if (!this.isEc2MetadataApiSpan(attributeMap)) { + for (const attribute in attributeMap) { + this.recordMetrics(span, attributeMap[attribute]); + } } } @@ -143,4 +150,8 @@ export class AwsSpanMetricsProcessor implements SpanProcessor { public forceFlush(): Promise { return this.forceFlushFunction(); } -} + + private isEc2MetadataApiSpan(attributeMap: AttributeMap): boolean { + return attributeMap[DEPENDENCY_METRIC]?.[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_SERVICE] === this.EC2_METADATA_API_IP; + } +} \ No newline at end of file diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-span-metrics-processor.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-span-metrics-processor.test.ts index 9409eee1..9f4845ae 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-span-metrics-processor.test.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/aws-span-metrics-processor.test.ts @@ -397,6 +397,22 @@ describe('AwsSpanMetricsProcessorTest', () => { validateMetricsGeneratedForStatusDataOk(600, ExpectedStatusMetric.NEITHER); }); + it('testOnEndMetricsGenerationFromEc2MetadataApi', () => { + const spanAttributes: Attributes = { [AWS_ATTRIBUTE_KEYS.AWS_REMOTE_SERVICE]: '169.254.169.254' }; + const readableSpanMock: ReadableSpan = buildReadableSpanMock( + spanAttributes, + SpanKind.CLIENT, + INVALID_SPAN_CONTEXT, + { code: SpanStatusCode.UNSET } + ); + const metricAttributesMap: AttributeMap = buildEc2MetadataApiMetricAttributes(); + configureMocksForOnEnd(readableSpanMock, metricAttributesMap); + awsSpanMetricsProcessor.onEnd(readableSpanMock); + sinon.assert.notCalled(errorHistogramMockRecord); + sinon.assert.notCalled(faultHistogramMockRecord); + sinon.assert.notCalled(latencyHistogramMockRecord); + }); + function buildSpanAttributes(containsAttribute: boolean): Attributes { if (containsAttribute) { return { 'original key': 'original value' }; @@ -421,6 +437,13 @@ describe('AwsSpanMetricsProcessorTest', () => { return attributesMap; } + function buildEc2MetadataApiMetricAttributes(): AttributeMap { + const attributesMap: AttributeMap = {}; + const attributes: Attributes = { [AWS_ATTRIBUTE_KEYS.AWS_REMOTE_SERVICE]: '169.254.169.254' }; + attributesMap[DEPENDENCY_METRIC] = attributes; + return attributesMap; + } + function buildReadableSpanMock( spanAttributes: Attributes, spanKind: SpanKind = SpanKind.SERVER,