@@ -55,6 +55,10 @@ const NORMALIZED_DYNAMO_DB_SERVICE_NAME: string = 'AWS::DynamoDB';
5555const NORMALIZED_KINESIS_SERVICE_NAME : string = 'AWS::Kinesis' ;
5656const NORMALIZED_S3_SERVICE_NAME : string = 'AWS::S3' ;
5757const NORMALIZED_SQS_SERVICE_NAME : string = 'AWS::SQS' ;
58+ const NORMALIZED_SNS_SERVICE_NAME : string = 'AWS::SNS' ;
59+ const NORMALIZED_SECRETSMANAGER_SERVICE_NAME = 'AWS::SecretsManager' ;
60+ const NORMALIZED_STEPFUNCTIONS_SERVICE_NAME = 'AWS::StepFunctions' ;
61+ const NORMALIZED_LAMBDA_SERVICE_NAME = 'AWS::Lambda' ;
5862const NORMALIZED_BEDROCK_SERVICE_NAME : string = 'AWS::Bedrock' ;
5963const NORMALIZED_BEDROCK_RUNTIME_SERVICE_NAME : string = 'AWS::BedrockRuntime' ;
6064
@@ -330,6 +334,8 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
330334 BedrockAgent : NORMALIZED_BEDROCK_SERVICE_NAME ,
331335 BedrockAgentRuntime : NORMALIZED_BEDROCK_SERVICE_NAME ,
332336 BedrockRuntime : NORMALIZED_BEDROCK_RUNTIME_SERVICE_NAME ,
337+ SecretsManager : NORMALIZED_SECRETSMANAGER_SERVICE_NAME ,
338+ SFN : NORMALIZED_STEPFUNCTIONS_SERVICE_NAME ,
333339 } ;
334340 return awsSdkServiceMapping [ serviceName ] || 'AWS::' + serviceName ;
335341 }
@@ -350,6 +356,7 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
350356 private static setRemoteResourceTypeAndIdentifier ( span : ReadableSpan , attributes : Attributes ) : void {
351357 let remoteResourceType : AttributeValue | undefined ;
352358 let remoteResourceIdentifier : AttributeValue | undefined ;
359+ let cloudFormationIdentifier : AttributeValue | undefined ;
353360
354361 if ( AwsSpanProcessingUtil . isAwsSDKSpan ( span ) ) {
355362 const awsTableNames : AttributeValue | undefined = span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_DYNAMODB_TABLE_NAMES ] ;
@@ -370,16 +377,56 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
370377 remoteResourceIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
371378 span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_S3_BUCKET ]
372379 ) ;
380+ } else if ( AwsSpanProcessingUtil . isKeyPresent ( span , AWS_ATTRIBUTE_KEYS . AWS_SNS_TOPIC_ARN ) ) {
381+ const snsArn = span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_SNS_TOPIC_ARN ] ;
382+
383+ remoteResourceType = NORMALIZED_SNS_SERVICE_NAME + '::Topic' ;
384+ remoteResourceIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
385+ this . extractResourceNameFromArn ( snsArn )
386+ ) ;
387+ cloudFormationIdentifier = AwsMetricAttributeGenerator . escapeDelimiters ( snsArn ) ;
388+ } else if ( AwsSpanProcessingUtil . isKeyPresent ( span , AWS_ATTRIBUTE_KEYS . AWS_SECRETSMANAGER_SECRET_ARN ) ) {
389+ const secretsArn = span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_SECRETSMANAGER_SECRET_ARN ] ;
390+
391+ remoteResourceType = NORMALIZED_SECRETSMANAGER_SERVICE_NAME + '::Secret' ;
392+ remoteResourceIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
393+ this . extractResourceNameFromArn ( secretsArn )
394+ ) ;
395+ cloudFormationIdentifier = AwsMetricAttributeGenerator . escapeDelimiters ( secretsArn ) ;
396+ } else if ( AwsSpanProcessingUtil . isKeyPresent ( span , AWS_ATTRIBUTE_KEYS . AWS_STEPFUNCTIONS_STATEMACHINE_ARN ) ) {
397+ const stateMachineArn = span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_STEPFUNCTIONS_STATEMACHINE_ARN ] ;
398+
399+ remoteResourceType = NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + '::StateMachine' ;
400+ remoteResourceIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
401+ this . extractResourceNameFromArn ( stateMachineArn )
402+ ) ;
403+ cloudFormationIdentifier = AwsMetricAttributeGenerator . escapeDelimiters ( stateMachineArn ) ;
404+ } else if ( AwsSpanProcessingUtil . isKeyPresent ( span , AWS_ATTRIBUTE_KEYS . AWS_STEPFUNCTIONS_ACTIVITY_ARN ) ) {
405+ const activityArn = span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_STEPFUNCTIONS_ACTIVITY_ARN ] ;
406+
407+ remoteResourceType = NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + '::Activity' ;
408+ remoteResourceIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
409+ this . extractResourceNameFromArn ( activityArn )
410+ ) ;
411+ cloudFormationIdentifier = AwsMetricAttributeGenerator . escapeDelimiters ( activityArn ) ;
412+ } else if ( AwsSpanProcessingUtil . isKeyPresent ( span , AWS_ATTRIBUTE_KEYS . AWS_LAMBDA_RESOURCE_MAPPING_ID ) ) {
413+ remoteResourceType = NORMALIZED_LAMBDA_SERVICE_NAME + '::EventSourceMapping' ;
414+ remoteResourceIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
415+ span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_LAMBDA_RESOURCE_MAPPING_ID ]
416+ ) ;
373417 } else if ( AwsSpanProcessingUtil . isKeyPresent ( span , AWS_ATTRIBUTE_KEYS . AWS_SQS_QUEUE_NAME ) ) {
374418 remoteResourceType = NORMALIZED_SQS_SERVICE_NAME + '::Queue' ;
375419 remoteResourceIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
376420 span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_SQS_QUEUE_NAME ]
377421 ) ;
378422 } else if ( AwsSpanProcessingUtil . isKeyPresent ( span , AWS_ATTRIBUTE_KEYS . AWS_SQS_QUEUE_URL ) ) {
379- remoteResourceType = NORMALIZED_SQS_SERVICE_NAME + '::Queue' ;
380- remoteResourceIdentifier = SqsUrlParser . getQueueName (
381- AwsMetricAttributeGenerator . escapeDelimiters ( span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_SQS_QUEUE_URL ] )
423+ const sqsQueueUrl = AwsMetricAttributeGenerator . escapeDelimiters (
424+ span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_SQS_QUEUE_URL ]
382425 ) ;
426+
427+ remoteResourceType = NORMALIZED_SQS_SERVICE_NAME + '::Queue' ;
428+ remoteResourceIdentifier = SqsUrlParser . getQueueName ( sqsQueueUrl ) ;
429+ cloudFormationIdentifier = sqsQueueUrl ;
383430 } else if ( AwsSpanProcessingUtil . isKeyPresent ( span , AWS_ATTRIBUTE_KEYS . AWS_BEDROCK_AGENT_ID ) ) {
384431 remoteResourceType = NORMALIZED_BEDROCK_SERVICE_NAME + '::Agent' ;
385432 remoteResourceIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
@@ -390,11 +437,17 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
390437 remoteResourceIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
391438 span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_BEDROCK_DATA_SOURCE_ID ]
392439 ) ;
440+ cloudFormationIdentifier = `${ AwsMetricAttributeGenerator . escapeDelimiters (
441+ span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_BEDROCK_KNOWLEDGE_BASE_ID ]
442+ ) } |${ remoteResourceIdentifier } `;
393443 } else if ( AwsSpanProcessingUtil . isKeyPresent ( span , AWS_ATTRIBUTE_KEYS . AWS_BEDROCK_GUARDRAIL_ID ) ) {
394444 remoteResourceType = NORMALIZED_BEDROCK_SERVICE_NAME + '::Guardrail' ;
395445 remoteResourceIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
396446 span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_BEDROCK_GUARDRAIL_ID ]
397447 ) ;
448+ cloudFormationIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
449+ span . attributes [ AWS_ATTRIBUTE_KEYS . AWS_BEDROCK_GUARDRAIL_ARN ]
450+ ) ;
398451 } else if ( AwsSpanProcessingUtil . isKeyPresent ( span , AWS_ATTRIBUTE_KEYS . AWS_BEDROCK_KNOWLEDGE_BASE_ID ) ) {
399452 remoteResourceType = NORMALIZED_BEDROCK_SERVICE_NAME + '::KnowledgeBase' ;
400453 remoteResourceIdentifier = AwsMetricAttributeGenerator . escapeDelimiters (
@@ -414,6 +467,14 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
414467 if ( remoteResourceType !== undefined && remoteResourceIdentifier !== undefined ) {
415468 attributes [ AWS_ATTRIBUTE_KEYS . AWS_REMOTE_RESOURCE_TYPE ] = remoteResourceType ;
416469 attributes [ AWS_ATTRIBUTE_KEYS . AWS_REMOTE_RESOURCE_IDENTIFIER ] = remoteResourceIdentifier ;
470+
471+ if ( AwsSpanProcessingUtil . isAwsSDKSpan ( span ) ) {
472+ if ( cloudFormationIdentifier === undefined ) {
473+ cloudFormationIdentifier = remoteResourceIdentifier ;
474+ }
475+
476+ attributes [ AWS_ATTRIBUTE_KEYS . AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER ] = cloudFormationIdentifier ;
477+ }
417478 }
418479 }
419480
@@ -532,6 +593,16 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
532593 return input . split ( '^' ) . join ( '^^' ) . split ( '|' ) . join ( '^|' ) ;
533594 }
534595
596+ // Extracts the name of the resource from an arn
597+ private static extractResourceNameFromArn ( attribute : AttributeValue | undefined ) : string | undefined {
598+ if ( typeof attribute === 'string' && attribute . startsWith ( 'arn:aws:' ) ) {
599+ const split = attribute . split ( ':' ) ;
600+ return split [ split . length - 1 ] ;
601+ }
602+
603+ return undefined ;
604+ }
605+
535606 /** Span kind is needed for differentiating metrics in the EMF exporter */
536607 private static setSpanKindForService ( span : ReadableSpan , attributes : Attributes ) : void {
537608 let spanKind : string = SpanKind [ span . kind ] ;
0 commit comments