Skip to content

Commit b1f1d20

Browse files
remove length check for account id & move resource extraction into arn parser
1 parent b58d2a0 commit b1f1d20

File tree

7 files changed

+82
-36
lines changed

7 files changed

+82
-36
lines changed

aws-distro-opentelemetry-node-autoinstrumentation/src/aws-metric-attribute-generator.ts

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,9 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
399399
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_DYNAMODB_TABLE_ARN)) {
400400
remoteResourceType = NORMALIZED_DYNAMO_DB_SERVICE_NAME + '::Table';
401401
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
402-
this.extractDynamoDbTableNameFromArn(span.attributes[AWS_ATTRIBUTE_KEYS.AWS_DYNAMODB_TABLE_ARN])
402+
RegionalResourceArnParser.extractDynamoDbTableNameFromArn(
403+
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_DYNAMODB_TABLE_ARN]
404+
)
403405
);
404406
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_KINESIS_STREAM_NAME)) {
405407
remoteResourceType = NORMALIZED_KINESIS_SERVICE_NAME + '::Stream';
@@ -409,7 +411,9 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
409411
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_KINESIS_STREAM_ARN)) {
410412
remoteResourceType = NORMALIZED_KINESIS_SERVICE_NAME + '::Stream';
411413
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
412-
this.extractKinesisStreamNameFromArn(span.attributes[AWS_ATTRIBUTE_KEYS.AWS_KINESIS_STREAM_ARN])
414+
RegionalResourceArnParser.extractKinesisStreamNameFromArn(
415+
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_KINESIS_STREAM_ARN]
416+
)
413417
);
414418
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_S3_BUCKET)) {
415419
remoteResourceType = NORMALIZED_S3_SERVICE_NAME + '::Bucket';
@@ -421,31 +425,31 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
421425

422426
remoteResourceType = NORMALIZED_SNS_SERVICE_NAME + '::Topic';
423427
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
424-
this.extractResourceNameFromArn(snsArn)
428+
RegionalResourceArnParser.extractResourceNameFromArn(snsArn)
425429
);
426430
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(snsArn);
427431
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN)) {
428432
const secretsArn = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN];
429433

430434
remoteResourceType = NORMALIZED_SECRETSMANAGER_SERVICE_NAME + '::Secret';
431435
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
432-
this.extractResourceNameFromArn(secretsArn)
436+
RegionalResourceArnParser.extractResourceNameFromArn(secretsArn)
433437
);
434438
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(secretsArn);
435439
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_STATEMACHINE_ARN)) {
436440
const stateMachineArn = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_STATEMACHINE_ARN];
437441

438442
remoteResourceType = NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + '::StateMachine';
439443
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
440-
this.extractResourceNameFromArn(stateMachineArn)
444+
RegionalResourceArnParser.extractResourceNameFromArn(stateMachineArn)
441445
);
442446
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(stateMachineArn);
443447
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_ACTIVITY_ARN)) {
444448
const activityArn = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_ACTIVITY_ARN];
445449

446450
remoteResourceType = NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + '::Activity';
447451
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
448-
this.extractResourceNameFromArn(activityArn)
452+
RegionalResourceArnParser.extractResourceNameFromArn(activityArn)
449453
);
450454
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(activityArn);
451455
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME)) {
@@ -725,24 +729,6 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
725729
return rpcService === 'Lambda' && span.attributes[SEMATTRS_RPC_METHOD] === LAMBDA_INVOKE_OPERATION;
726730
}
727731

728-
private static extractDynamoDbTableNameFromArn(attribute: AttributeValue | undefined): string | undefined {
729-
return this.extractResourceNameFromArn(attribute)?.replace('table/', '');
730-
}
731-
732-
private static extractKinesisStreamNameFromArn(attribute: AttributeValue | undefined): string | undefined {
733-
return this.extractResourceNameFromArn(attribute)?.replace('stream/', '');
734-
}
735-
736-
// Extracts the name of the resource from an arn
737-
private static extractResourceNameFromArn(attribute: AttributeValue | undefined): string | undefined {
738-
if (typeof attribute === 'string' && attribute.startsWith('arn:aws:')) {
739-
const split = attribute.split(':');
740-
return split[split.length - 1];
741-
}
742-
743-
return undefined;
744-
}
745-
746732
/** Span kind is needed for differentiating metrics in the EMF exporter */
747733
private static setSpanKindForService(span: ReadableSpan, attributes: Attributes): void {
748734
let spanKind: string = SpanKind[span.kind];

aws-distro-opentelemetry-node-autoinstrumentation/src/regional-resource-arn-parser.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,24 @@ export class RegionalResourceArnParser {
1919
return undefined;
2020
}
2121

22+
public static extractDynamoDbTableNameFromArn(arn: AttributeValue | undefined): string | undefined {
23+
return this.extractResourceNameFromArn(arn)?.replace('table/', '');
24+
}
25+
26+
public static extractKinesisStreamNameFromArn(arn: AttributeValue | undefined): string | undefined {
27+
return this.extractResourceNameFromArn(arn)?.replace('stream/', '');
28+
}
29+
30+
// Extracts the name of the resource from an arn
31+
public static extractResourceNameFromArn(arn: AttributeValue | undefined): string | undefined {
32+
if (typeof arn === 'string' && this.isArn(arn)) {
33+
const split = arn.split(':');
34+
return split[split.length - 1];
35+
}
36+
37+
return undefined;
38+
}
39+
2240
public static isArn(arn: string): boolean {
2341
// Check if arn follows the format:
2442
// arn:partition:service:region:account-id:resource-type/resource-id or

aws-distro-opentelemetry-node-autoinstrumentation/src/sqs-url-parser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const HTTPS_SCHEMA: string = 'https://';
1111
// eslint-disable-next-line @typescript-eslint/typedef
1212
const ALPHABET_REGEX = /^[a-zA-Z]+$/;
1313

14-
export interface ParsedSqsUrl {
14+
export interface ParsedSqsUrl {
1515
queueName: string;
1616
accountId: string;
1717
region?: string;
@@ -22,7 +22,7 @@ export class SqsUrlParser {
2222
* Best-effort logic to extract queue name from an HTTP url. This method should only be used with
2323
* a string that is, with reasonably high confidence, an SQS queue URL. Handles new/legacy/some
2424
* custom URLs. Essentially, we require that the URL should have exactly three parts, delimited by
25-
* /'s (excluding schema), the second part should be a 12-digit account id, and the third part
25+
* /'s (excluding schema), the second part should be a account id consisting of digits, and the third part
2626
* should be a valid queue name, per SQS naming conventions.
2727
*/
2828
public static getQueueName(url: AttributeValue | undefined): string | undefined {

aws-distro-opentelemetry-node-autoinstrumentation/src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const checkDigits = (str: string): boolean => {
2323
};
2424

2525
export const isAccountId = (input: string): boolean => {
26-
if (input == null || input.length !== 12) {
26+
if (input == null) {
2727
return false;
2828
}
2929

aws-distro-opentelemetry-node-autoinstrumentation/test/aws-metric-attribute-generator.test.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,11 +1145,7 @@ describe('AwsMetricAttributeGeneratorTest', () => {
11451145
AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_STATEMACHINE_ARN,
11461146
'arn:aws:states:us-east-1:invalid_account_id:stateMachine:testStateMachine'
11471147
);
1148-
validateRemoteResourceAttributes(
1149-
'AWS::StepFunctions::StateMachine',
1150-
'testStateMachine',
1151-
'arn:aws:states:us-east-1:invalid_account_id:stateMachine:testStateMachine'
1152-
);
1148+
validateRemoteResourceAttributes(undefined, undefined);
11531149
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_STATEMACHINE_ARN, undefined);
11541150

11551151
// Arn with invalid region

aws-distro-opentelemetry-node-autoinstrumentation/test/regional-resource-arn-parser.test.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ describe('RegionalResourceArnParserTest', () => {
1313
validateAccountId('::::::', undefined);
1414
validateAccountId('not:an:arn:string', undefined);
1515
validateAccountId('arn:aws:ec2:us-west-2:123456', undefined);
16-
validateAccountId('arn:aws:ec2:us-west-2:1234567xxxxx', undefined);
1716
validateAccountId('arn:aws:ec2:us-west-2:123456789012', undefined);
17+
validateAccountId('arn:aws:ec2:us-west-2:1234567xxxxx:table/test_table', undefined);
1818
validateAccountId('arn:aws:dynamodb:us-west-2:123456789012:table/test_table', '123456789012');
1919
validateAccountId('arn:aws:acm:us-east-1:123456789012:certificate:abc-123', '123456789012');
2020
});
@@ -34,6 +34,52 @@ describe('RegionalResourceArnParserTest', () => {
3434
});
3535
});
3636

37+
it('testExtractDynamoDbTableNameFromArn', () => {
38+
validateDynamoDbTableName(undefined, undefined);
39+
validateDynamoDbTableName('', undefined);
40+
validateDynamoDbTableName(' ', undefined);
41+
validateDynamoDbTableName(':', undefined);
42+
validateDynamoDbTableName('::::::', undefined);
43+
validateDynamoDbTableName('not:an:arn:string', undefined);
44+
validateDynamoDbTableName('arn:aws:dynamodb:us-west-2:123456789012:table/test_table', 'test_table');
45+
validateDynamoDbTableName('arn:aws:dynamodb:us-west-2:123456789012:table/my-table-name', 'my-table-name');
46+
});
47+
48+
it('testExtractKinesisStreamNameFromArn', () => {
49+
validateKinesisStreamName(undefined, undefined);
50+
validateKinesisStreamName('', undefined);
51+
validateKinesisStreamName(' ', undefined);
52+
validateKinesisStreamName(':', undefined);
53+
validateKinesisStreamName('::::::', undefined);
54+
validateKinesisStreamName('not:an:arn:string', undefined);
55+
validateKinesisStreamName('arn:aws:kinesis:us-west-2:123456789012:stream/test_stream', 'test_stream');
56+
validateKinesisStreamName('arn:aws:kinesis:us-west-2:123456789012:stream/my-stream-name', 'my-stream-name');
57+
});
58+
59+
it('testExtractResourceNameFromArn', () => {
60+
validateResourceName(undefined, undefined);
61+
validateResourceName('', undefined);
62+
validateResourceName(' ', undefined);
63+
validateResourceName(':', undefined);
64+
validateResourceName('::::::', undefined);
65+
validateResourceName('not:an:arn:string', undefined);
66+
validateResourceName('arn:aws:dynamodb:us-west-2:123456789012:table/test_table', 'table/test_table');
67+
validateResourceName('arn:aws:kinesis:us-west-2:123456789012:stream/test_stream', 'stream/test_stream');
68+
validateResourceName('arn:aws:s3:us-west-2:123456789012:my-bucket', 'my-bucket');
69+
});
70+
71+
function validateDynamoDbTableName(arn: string | undefined, expectedName: string | undefined): void {
72+
expect(RegionalResourceArnParser.extractDynamoDbTableNameFromArn(arn)).toEqual(expectedName);
73+
}
74+
75+
function validateKinesisStreamName(arn: string | undefined, expectedName: string | undefined): void {
76+
expect(RegionalResourceArnParser.extractKinesisStreamNameFromArn(arn)).toEqual(expectedName);
77+
}
78+
79+
function validateResourceName(arn: string | undefined, expectedName: string | undefined): void {
80+
expect(RegionalResourceArnParser.extractResourceNameFromArn(arn)).toEqual(expectedName);
81+
}
82+
3783
function validateAccountId(arn: string | undefined, expectedAccountId: string | undefined): void {
3884
expect(RegionalResourceArnParser.getAccountId(arn)).toEqual(expectedAccountId);
3985
}

aws-distro-opentelemetry-node-autoinstrumentation/test/sqs-url-parser.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ describe('SqsUrlParserTest', () => {
4747
validateGetQueueName('invalidUrl', undefined);
4848
validateGetQueueName('https://www.amazon.com', undefined);
4949
validateGetQueueName('https://sqs.us-east-1.amazonaws.com/123412341234/.', undefined);
50-
validateGetQueueName('https://sqs.us-east-1.amazonaws.com/12/Queue', undefined);
50+
validateGetQueueName('https://sqs.us-east-1.amazonaws.com/12341234xxxx/.', undefined);
5151
validateGetQueueName('https://sqs.us-east-1.amazonaws.com/A/A', undefined);
5252
validateGetQueueName('https://sqs.us-east-1.amazonaws.com/123412341234/A/ThisShouldNotBeHere', undefined);
5353
});
@@ -63,7 +63,7 @@ describe('SqsUrlParserTest', () => {
6363
validateGetAccountId('/123412341234/as&df', undefined);
6464
validateGetAccountId('invalidUrl', undefined);
6565
validateGetAccountId('https://www.amazon.com', undefined);
66-
validateGetAccountId('https://sqs.us-east-1.amazonaws.com/12341234/Queue', undefined);
66+
validateGetAccountId('https://sqs.us-east-1.amazonaws.com/12341234/Queue', '12341234');
6767
validateGetAccountId('https://sqs.us-east-1.amazonaws.com/1234123412xx/Queue', undefined);
6868
validateGetAccountId('https://sqs.us-east-1.amazonaws.com/1234123412xx', undefined);
6969
validateGetAccountId('https://sqs.us-east-1.amazonaws.com/123412341234/Q_Namez-5', '123412341234');
@@ -80,7 +80,7 @@ describe('SqsUrlParserTest', () => {
8080
validateGetRegion('/123412341234/as&df', undefined);
8181
validateGetRegion('invalidUrl', undefined);
8282
validateGetRegion('https://www.amazon.com', undefined);
83-
validateGetRegion('https://sqs.us-east-1.amazonaws.com/12341234/Queue', undefined);
83+
validateGetRegion('https://sqs.us-east-1.amazonaws.com/12341234/Queue', 'us-east-1');
8484
validateGetRegion('https://sqs.us-east-1.amazonaws.com/1234123412xx/Queue', undefined);
8585
validateGetRegion('https://sqs.us-east-1.amazonaws.com/1234123412xx', undefined);
8686
validateGetRegion('https://sqs.us-east-1.amazonaws.com/123412341234/Q_Namez-5', 'us-east-1');

0 commit comments

Comments
 (0)