Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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 { 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
Expand All @@ -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;
Expand Down Expand Up @@ -130,7 +135,7 @@ export class AwsSpanMetricsProcessor implements SpanProcessor {

private recordMetrics(span: ReadableSpan, attributes: Attributes): void {
// Only record metrics if non-empty attributes are returned.
if (Object.keys(attributes).length > 0) {
if (Object.keys(attributes).length > 0 && !this.isEc2MetadataApiSpan(attributes)) {
this.recordErrorOrFault(span, attributes);
this.recordLatency(span, attributes);
}
Expand All @@ -143,4 +148,8 @@ export class AwsSpanMetricsProcessor implements SpanProcessor {
public forceFlush(): Promise<void> {
return this.forceFlushFunction();
}

private isEc2MetadataApiSpan(attributes: Attributes): boolean {
return attributes[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_SERVICE] === this.EC2_METADATA_API_IP;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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' };
Expand All @@ -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,
Expand Down
Loading