Skip to content

Commit 2d85020

Browse files
committed
add tests for cfn primary id fallback and set remote environment
1 parent 0ce0b3f commit 2d85020

File tree

1 file changed

+181
-12
lines changed

1 file changed

+181
-12
lines changed

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

Lines changed: 181 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,11 @@ describe('AwsMetricAttributeGeneratorTest', () => {
745745
// them. Queue name is more reliable than queue URL, so we prefer to use name over URL.
746746
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_URL, 'https://sqs.us-east-2.amazonaws.com/123456789012/Queue');
747747
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_NAME, 'aws_queue_name');
748-
validateRemoteResourceAttributes('AWS::SQS::Queue', 'aws_queue_name', 'https://sqs.us-east-2.amazonaws.com/123456789012/Queue');
748+
validateRemoteResourceAttributes(
749+
'AWS::SQS::Queue',
750+
'aws_queue_name',
751+
'https://sqs.us-east-2.amazonaws.com/123456789012/Queue'
752+
);
749753
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_URL, undefined);
750754
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_NAME, undefined);
751755

@@ -758,7 +762,11 @@ describe('AwsMetricAttributeGeneratorTest', () => {
758762

759763
// Validate behaviour of AWS_SQS_QUEUE_URL attribute without queue name, then remove it.
760764
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_URL, 'https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue');
761-
validateRemoteResourceAttributes('AWS::SQS::Queue', 'MyQueue', 'https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue');
765+
validateRemoteResourceAttributes(
766+
'AWS::SQS::Queue',
767+
'MyQueue',
768+
'https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue'
769+
);
762770
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_URL, undefined);
763771

764772
// Validate behaviour of AWS_KINESIS_STREAM_NAME attribute, then remove it.
@@ -776,7 +784,11 @@ describe('AwsMetricAttributeGeneratorTest', () => {
776784
AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN,
777785
'arn:aws:secretsmanager:us-east-1:123456789123:secret:testSecret'
778786
);
779-
validateRemoteResourceAttributes('AWS::SecretsManager::Secret', 'testSecret', 'arn:aws:secretsmanager:us-east-1:123456789123:secret:testSecret');
787+
validateRemoteResourceAttributes(
788+
'AWS::SecretsManager::Secret',
789+
'testSecret',
790+
'arn:aws:secretsmanager:us-east-1:123456789123:secret:testSecret'
791+
);
780792
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN, undefined);
781793

782794
// Validate behaviour of AWS_LAMBDA_FUNCTION_NAME and AWS_LAMBDA_FUNCTION_ARN
@@ -785,7 +797,11 @@ describe('AwsMetricAttributeGeneratorTest', () => {
785797
AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_ARN,
786798
'arn:aws:lambda:us-east-1:123456789012:function:aws_lambda_function_name'
787799
);
788-
validateRemoteResourceAttributes('AWS::Lambda::Function', 'aws_lambda_function_name', 'arn:aws:lambda:us-east-1:123456789012:function:aws_lambda_function_name');
800+
validateRemoteResourceAttributes(
801+
'AWS::Lambda::Function',
802+
'aws_lambda_function_name',
803+
'arn:aws:lambda:us-east-1:123456789012:function:aws_lambda_function_name'
804+
);
789805
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME, undefined);
790806
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_ARN, undefined);
791807

@@ -799,14 +815,22 @@ describe('AwsMetricAttributeGeneratorTest', () => {
799815
AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_STATEMACHINE_ARN,
800816
'arn:aws:states:us-east-1:123456789123:stateMachine:testStateMachine'
801817
);
802-
validateRemoteResourceAttributes('AWS::StepFunctions::StateMachine', 'testStateMachine', 'arn:aws:states:us-east-1:123456789123:stateMachine:testStateMachine');
818+
validateRemoteResourceAttributes(
819+
'AWS::StepFunctions::StateMachine',
820+
'testStateMachine',
821+
'arn:aws:states:us-east-1:123456789123:stateMachine:testStateMachine'
822+
);
803823
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_STATEMACHINE_ARN, undefined);
804824

805825
mockAttribute(
806826
AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_ACTIVITY_ARN,
807827
'arn:aws:states:us-east-1:123456789123:activity:testActivity'
808828
);
809-
validateRemoteResourceAttributes('AWS::StepFunctions::Activity', 'testActivity', 'arn:aws:states:us-east-1:123456789123:activity:testActivity');
829+
validateRemoteResourceAttributes(
830+
'AWS::StepFunctions::Activity',
831+
'testActivity',
832+
'arn:aws:states:us-east-1:123456789123:activity:testActivity'
833+
);
810834
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_ACTIVITY_ARN, undefined);
811835

812836
// Validate behaviour of AWS_TABLE_NAMES attribute with one table name, then remove it.
@@ -854,21 +878,39 @@ describe('AwsMetricAttributeGeneratorTest', () => {
854878
// Validate behaviour of AWS_BEDROCK_DATA_SOURCE_ID attribute with special chars(^), then remove it.
855879
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID, 'test_datasource_^id');
856880
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID, 'test_kb_^id');
857-
validateRemoteResourceAttributes('AWS::Bedrock::DataSource', 'test_datasource_^^id', 'test_kb_^^id|test_datasource_^^id');
881+
validateRemoteResourceAttributes(
882+
'AWS::Bedrock::DataSource',
883+
'test_datasource_^^id',
884+
'test_kb_^^id|test_datasource_^^id'
885+
);
858886
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID, undefined);
859887
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID, undefined);
860888

861889
// Validate behaviour of AWS_BEDROCK_GUARDRAIL_ID attribute, then remove it.
862890
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID, 'test_guardrail_id');
863-
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ARN, 'arn:aws:bedrock:us-east-1:123456789012:guardrail/test_guardrail_id');
864-
validateRemoteResourceAttributes('AWS::Bedrock::Guardrail', 'test_guardrail_id', 'arn:aws:bedrock:us-east-1:123456789012:guardrail/test_guardrail_id');
891+
mockAttribute(
892+
AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ARN,
893+
'arn:aws:bedrock:us-east-1:123456789012:guardrail/test_guardrail_id'
894+
);
895+
validateRemoteResourceAttributes(
896+
'AWS::Bedrock::Guardrail',
897+
'test_guardrail_id',
898+
'arn:aws:bedrock:us-east-1:123456789012:guardrail/test_guardrail_id'
899+
);
865900
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID, undefined);
866901
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ARN, undefined);
867902

868903
// Validate behaviour of AWS_BEDROCK_GUARDRAIL_ID attribute with special chars(^), then remove it.
869904
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID, 'test_guardrail_^id');
870-
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ARN, 'arn:aws:bedrock:us-east-1:123456789012:guardrail/test_guardrail_^id');
871-
validateRemoteResourceAttributes('AWS::Bedrock::Guardrail', 'test_guardrail_^^id', 'arn:aws:bedrock:us-east-1:123456789012:guardrail/test_guardrail_^^id');
905+
mockAttribute(
906+
AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ARN,
907+
'arn:aws:bedrock:us-east-1:123456789012:guardrail/test_guardrail_^id'
908+
);
909+
validateRemoteResourceAttributes(
910+
'AWS::Bedrock::Guardrail',
911+
'test_guardrail_^^id',
912+
'arn:aws:bedrock:us-east-1:123456789012:guardrail/test_guardrail_^^id'
913+
);
872914
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID, undefined);
873915
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ARN, undefined);
874916

@@ -1127,7 +1169,11 @@ describe('AwsMetricAttributeGeneratorTest', () => {
11271169
mockAttribute(SEMATTRS_PEER_SERVICE, undefined);
11281170
}
11291171

1130-
function validateRemoteResourceAttributes(type: string | undefined, identifier: string | undefined, cfnPrimaryId: string | undefined = undefined): void {
1172+
function validateRemoteResourceAttributes(
1173+
type: string | undefined,
1174+
identifier: string | undefined,
1175+
cfnPrimaryId: string | undefined = undefined
1176+
): void {
11311177
// If cfnPrimaryId is not provided, it defaults to identifier
11321178
if (cfnPrimaryId === undefined) {
11331179
cfnPrimaryId = identifier;
@@ -1283,6 +1329,129 @@ describe('AwsMetricAttributeGeneratorTest', () => {
12831329
expect(attributeMap[DEPENDENCY_METRIC]).toEqual(dependencyAttributes);
12841330
});
12851331

1332+
it('testCloudformationPrimaryIdentifierFallbackToRemoteResourceIdentifier', () => {
1333+
// Test that when cloudformationPrimaryIdentifier is not explicitly set,
1334+
// it falls back to use the same value as remoteResourceIdentifier.
1335+
mockAttribute(SEMATTRS_RPC_SYSTEM, 'aws-api');
1336+
(spanDataMock as any).kind = SpanKind.CLIENT;
1337+
1338+
// Test case 1: S3 Bucket (no ARN available, should use bucket name for both)
1339+
mockAttribute(SEMATTRS_RPC_SERVICE, 'S3');
1340+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_S3_BUCKET, 'my-test-bucket');
1341+
validateRemoteResourceAttributes('AWS::S3::Bucket', 'my-test-bucket');
1342+
1343+
// Test S3 bucket with special characters
1344+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_S3_BUCKET, 'my-test|bucket^name');
1345+
validateRemoteResourceAttributes('AWS::S3::Bucket', 'my-test^|bucket^^name');
1346+
mockAttribute(SEMATTRS_RPC_SERVICE, undefined);
1347+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_S3_BUCKET, undefined);
1348+
1349+
// Test case 2: SQS Queue by name (no ARN, should use queue name for both)
1350+
mockAttribute(SEMATTRS_RPC_SERVICE, 'SQS');
1351+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_NAME, 'my-test-queue');
1352+
validateRemoteResourceAttributes('AWS::SQS::Queue', 'my-test-queue');
1353+
1354+
// Test SQS queue with special characters
1355+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_NAME, 'my^queue|name');
1356+
validateRemoteResourceAttributes('AWS::SQS::Queue', 'my^^queue^|name');
1357+
mockAttribute(SEMATTRS_RPC_SERVICE, undefined);
1358+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_NAME, undefined);
1359+
1360+
// Test case 3: DynamoDB Table (no ARN, should use table name for both)
1361+
mockAttribute(SEMATTRS_RPC_SERVICE, 'DynamoDB');
1362+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_DYNAMODB_TABLE_NAMES, ['my-test-table']);
1363+
validateRemoteResourceAttributes('AWS::DynamoDB::Table', 'my-test-table');
1364+
1365+
// Test DynamoDB table with special characters
1366+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_DYNAMODB_TABLE_NAMES, ['my|test^table']);
1367+
validateRemoteResourceAttributes('AWS::DynamoDB::Table', 'my^|test^^table');
1368+
mockAttribute(SEMATTRS_RPC_SERVICE, undefined);
1369+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_DYNAMODB_TABLE_NAMES, undefined);
1370+
1371+
// Test case 4: Kinesis Stream
1372+
mockAttribute(SEMATTRS_RPC_SERVICE, 'Kinesis');
1373+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_KINESIS_STREAM_NAME, 'my-test-stream');
1374+
validateRemoteResourceAttributes('AWS::Kinesis::Stream', 'my-test-stream');
1375+
1376+
// Test Kinesis stream with special characters
1377+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_KINESIS_STREAM_NAME, 'my-stream^with|chars');
1378+
validateRemoteResourceAttributes('AWS::Kinesis::Stream', 'my-stream^^with^|chars');
1379+
mockAttribute(SEMATTRS_RPC_SERVICE, undefined);
1380+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_KINESIS_STREAM_NAME, undefined);
1381+
1382+
// Test case 5: Lambda Function (non-invoke operation, no ARN)
1383+
mockAttribute(SEMATTRS_RPC_SERVICE, 'Lambda');
1384+
mockAttribute(SEMATTRS_RPC_METHOD, 'GetFunction');
1385+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME, 'my-test-function');
1386+
validateRemoteResourceAttributes('AWS::Lambda::Function', 'my-test-function');
1387+
1388+
// Test Lambda function with special characters
1389+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME, 'my-function|with^chars');
1390+
validateRemoteResourceAttributes('AWS::Lambda::Function', 'my-function^|with^^chars');
1391+
mockAttribute(SEMATTRS_RPC_SERVICE, undefined);
1392+
mockAttribute(SEMATTRS_RPC_METHOD, undefined);
1393+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME, undefined);
1394+
1395+
mockAttribute(SEMATTRS_RPC_SYSTEM, undefined);
1396+
});
1397+
1398+
it('testSetRemoteEnvironment', () => {
1399+
// Test remote environment setting for Lambda invoke operations.
1400+
1401+
// Test 1: Setting remote environment when all relevant attributes are present
1402+
(spanDataMock as any).kind = SpanKind.CLIENT;
1403+
mockAttribute(SEMATTRS_RPC_SYSTEM, 'aws-api');
1404+
mockAttribute(SEMATTRS_RPC_SERVICE, 'Lambda');
1405+
mockAttribute(SEMATTRS_RPC_METHOD, 'Invoke');
1406+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME, 'testFunction');
1407+
1408+
let actualAttributes: Attributes = GENERATOR.generateMetricAttributeMapFromSpan(spanDataMock, resource)[
1409+
DEPENDENCY_METRIC
1410+
];
1411+
expect(actualAttributes[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_ENVIRONMENT]).toEqual('lambda:default');
1412+
1413+
// Test 2: NOT setting it when RPC_SYSTEM is missing
1414+
mockAttribute(SEMATTRS_RPC_SYSTEM, undefined);
1415+
actualAttributes = GENERATOR.generateMetricAttributeMapFromSpan(spanDataMock, resource)[DEPENDENCY_METRIC];
1416+
expect(actualAttributes[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_ENVIRONMENT]).toBeUndefined();
1417+
mockAttribute(SEMATTRS_RPC_SYSTEM, 'aws-api');
1418+
1419+
// Test 3: NOT setting it when RPC_METHOD is missing
1420+
mockAttribute(SEMATTRS_RPC_METHOD, undefined);
1421+
actualAttributes = GENERATOR.generateMetricAttributeMapFromSpan(spanDataMock, resource)[DEPENDENCY_METRIC];
1422+
expect(actualAttributes[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_ENVIRONMENT]).toBeUndefined();
1423+
mockAttribute(SEMATTRS_RPC_METHOD, 'Invoke');
1424+
1425+
// Test 4: Still setting it to lambda:default when AWS_LAMBDA_FUNCTION_NAME is missing
1426+
// Keep the other attributes but remove AWS_LAMBDA_FUNCTION_NAME
1427+
mockAttribute(SEMATTRS_RPC_SYSTEM, 'aws-api');
1428+
mockAttribute(SEMATTRS_RPC_SERVICE, 'Lambda');
1429+
mockAttribute(SEMATTRS_RPC_METHOD, 'Invoke');
1430+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME, undefined);
1431+
1432+
actualAttributes = GENERATOR.generateMetricAttributeMapFromSpan(spanDataMock, resource)[DEPENDENCY_METRIC];
1433+
expect(actualAttributes[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_ENVIRONMENT]).toEqual('lambda:default');
1434+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME, 'testFunction');
1435+
1436+
// Test 5: NOT setting it for non-Lambda services
1437+
mockAttribute(SEMATTRS_RPC_SERVICE, 'S3');
1438+
mockAttribute(SEMATTRS_RPC_METHOD, 'GetObject');
1439+
actualAttributes = GENERATOR.generateMetricAttributeMapFromSpan(spanDataMock, resource)[DEPENDENCY_METRIC];
1440+
expect(actualAttributes[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_ENVIRONMENT]).toBeUndefined();
1441+
1442+
// Test 6: NOT setting it for Lambda non-Invoke operations
1443+
mockAttribute(SEMATTRS_RPC_SERVICE, 'Lambda');
1444+
mockAttribute(SEMATTRS_RPC_METHOD, 'GetFunction');
1445+
actualAttributes = GENERATOR.generateMetricAttributeMapFromSpan(spanDataMock, resource)[DEPENDENCY_METRIC];
1446+
expect(actualAttributes[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_ENVIRONMENT]).toBeUndefined();
1447+
1448+
// Clean up
1449+
mockAttribute(SEMATTRS_RPC_SYSTEM, undefined);
1450+
mockAttribute(SEMATTRS_RPC_SERVICE, undefined);
1451+
mockAttribute(SEMATTRS_RPC_METHOD, undefined);
1452+
mockAttribute(AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME, undefined);
1453+
});
1454+
12861455
it('testJdbcDbConnectionString', () => {
12871456
mockAttribute(SEMATTRS_DB_SYSTEM, 'mysql');
12881457

0 commit comments

Comments
 (0)