42
42
import static io .opentelemetry .semconv .SemanticAttributes .SERVER_SOCKET_PORT ;
43
43
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_AGENT_ID ;
44
44
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_BUCKET_NAME ;
45
+ import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER ;
45
46
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_DATA_SOURCE_ID ;
46
47
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_GUARDRAIL_ID ;
47
48
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_KNOWLEDGE_BASE_ID ;
49
+ import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_LAMBDA_NAME ;
50
+ import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_LAMBDA_RESOURCE_ID ;
48
51
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_LOCAL_OPERATION ;
49
52
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_LOCAL_SERVICE ;
50
53
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_QUEUE_NAME ;
54
57
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_REMOTE_RESOURCE_IDENTIFIER ;
55
58
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_REMOTE_RESOURCE_TYPE ;
56
59
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_REMOTE_SERVICE ;
60
+ import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_SECRET_ARN ;
61
+ import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_SNS_TOPIC_ARN ;
57
62
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_SPAN_KIND ;
63
+ import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_STATE_MACHINE_ARN ;
64
+ import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_STEP_FUNCTIONS_ACTIVITY_ARN ;
58
65
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_STREAM_NAME ;
59
66
import static software .amazon .opentelemetry .javaagent .providers .AwsAttributeKeys .AWS_TABLE_NAME ;
60
67
import static software .amazon .opentelemetry .javaagent .providers .AwsSpanProcessingUtil .GEN_AI_REQUEST_MODEL ;
67
74
import static software .amazon .opentelemetry .javaagent .providers .AwsSpanProcessingUtil .isDBSpan ;
68
75
import static software .amazon .opentelemetry .javaagent .providers .AwsSpanProcessingUtil .isKeyPresent ;
69
76
77
+ import com .amazonaws .arn .Arn ;
70
78
import io .opentelemetry .api .common .AttributeKey ;
71
79
import io .opentelemetry .api .common .Attributes ;
72
80
import io .opentelemetry .api .common .AttributesBuilder ;
@@ -111,6 +119,10 @@ final class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
111
119
private static final String NORMALIZED_SQS_SERVICE_NAME = "AWS::SQS" ;
112
120
private static final String NORMALIZED_BEDROCK_SERVICE_NAME = "AWS::Bedrock" ;
113
121
private static final String NORMALIZED_BEDROCK_RUNTIME_SERVICE_NAME = "AWS::BedrockRuntime" ;
122
+ private static final String NORMALIZED_STEPFUNCTIONS_SERVICE_NAME = "AWS::StepFunctions" ;
123
+ private static final String NORMALIZED_SNS_SERVICE_NAME = "AWS::SNS" ;
124
+ private static final String NORMALIZED_SECRETSMANAGER_SERVICE_NAME = "AWS::SecretsManager" ;
125
+ private static final String NORMALIZED_LAMBDA_SERVICE_NAME = "AWS::Lambda" ;
114
126
115
127
// Special DEPENDENCY attribute value if GRAPHQL_OPERATION_TYPE attribute key is present.
116
128
private static final String GRAPHQL = "graphql" ;
@@ -371,6 +383,18 @@ private static String normalizeRemoteServiceName(SpanData span, String serviceNa
371
383
case "AmazonBedrockRuntime" : // AWS SDK v1
372
384
case "BedrockRuntime" : // AWS SDK v2
373
385
return NORMALIZED_BEDROCK_RUNTIME_SERVICE_NAME ;
386
+ case "AWSStepFunctions" : // AWS SDK v1
387
+ case "Sfn" : // AWS SDK v2
388
+ return NORMALIZED_STEPFUNCTIONS_SERVICE_NAME ;
389
+ case "AmazonSNS" :
390
+ case "Sns" :
391
+ return NORMALIZED_SNS_SERVICE_NAME ;
392
+ case "AWSSecretsManager" : // AWS SDK v1
393
+ case "SecretsManager" : // AWS SDK v2
394
+ return NORMALIZED_SECRETSMANAGER_SERVICE_NAME ;
395
+ case "AWSLambda" : // AWS SDK v1
396
+ case "Lambda" : // AWS SDK v2
397
+ return NORMALIZED_LAMBDA_SERVICE_NAME ;
374
398
default :
375
399
return "AWS::" + serviceName ;
376
400
}
@@ -392,6 +416,7 @@ private static String normalizeRemoteServiceName(SpanData span, String serviceNa
392
416
private static void setRemoteResourceTypeAndIdentifier (SpanData span , AttributesBuilder builder ) {
393
417
Optional <String > remoteResourceType = Optional .empty ();
394
418
Optional <String > remoteResourceIdentifier = Optional .empty ();
419
+ Optional <String > cloudformationPrimaryIdentifier = Optional .empty ();
395
420
396
421
if (isAwsSDKSpan (span )) {
397
422
if (isKeyPresent (span , AWS_TABLE_NAME )) {
@@ -434,18 +459,88 @@ private static void setRemoteResourceTypeAndIdentifier(SpanData span, Attributes
434
459
remoteResourceType = Optional .of (NORMALIZED_BEDROCK_SERVICE_NAME + "::Model" );
435
460
remoteResourceIdentifier =
436
461
Optional .ofNullable (escapeDelimiters (span .getAttributes ().get (GEN_AI_REQUEST_MODEL )));
462
+ } else if (isKeyPresent (span , AWS_STATE_MACHINE_ARN )) {
463
+ remoteResourceType = Optional .of (NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + "::StateMachine" );
464
+ remoteResourceIdentifier =
465
+ getSfnResourceNameFromArn (
466
+ Optional .ofNullable (
467
+ escapeDelimiters (span .getAttributes ().get (AWS_STATE_MACHINE_ARN ))));
468
+ cloudformationPrimaryIdentifier =
469
+ Optional .ofNullable (escapeDelimiters (span .getAttributes ().get (AWS_STATE_MACHINE_ARN )));
470
+ } else if (isKeyPresent (span , AWS_STEP_FUNCTIONS_ACTIVITY_ARN )) {
471
+ remoteResourceType = Optional .of (NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + "::Activity" );
472
+ remoteResourceIdentifier =
473
+ getSfnResourceNameFromArn (
474
+ Optional .ofNullable (
475
+ escapeDelimiters (span .getAttributes ().get (AWS_STEP_FUNCTIONS_ACTIVITY_ARN ))));
476
+ cloudformationPrimaryIdentifier =
477
+ Optional .ofNullable (
478
+ escapeDelimiters (span .getAttributes ().get (AWS_STEP_FUNCTIONS_ACTIVITY_ARN )));
479
+ } else if (isKeyPresent (span , AWS_SNS_TOPIC_ARN )) {
480
+ remoteResourceType = Optional .of (NORMALIZED_SNS_SERVICE_NAME + "::Topic" );
481
+ remoteResourceIdentifier =
482
+ getSnsResourceNameFromArn (
483
+ Optional .ofNullable (escapeDelimiters (span .getAttributes ().get (AWS_SNS_TOPIC_ARN ))));
484
+ cloudformationPrimaryIdentifier =
485
+ Optional .ofNullable (escapeDelimiters (span .getAttributes ().get (AWS_SNS_TOPIC_ARN )));
486
+ } else if (isKeyPresent (span , AWS_SECRET_ARN )) {
487
+ remoteResourceType = Optional .of (NORMALIZED_SECRETSMANAGER_SERVICE_NAME + "::Secret" );
488
+ remoteResourceIdentifier =
489
+ getSecretsManagerResourceNameFromArn (
490
+ Optional .ofNullable (escapeDelimiters (span .getAttributes ().get (AWS_SECRET_ARN ))));
491
+ cloudformationPrimaryIdentifier =
492
+ Optional .ofNullable (escapeDelimiters (span .getAttributes ().get (AWS_SECRET_ARN )));
493
+ } else if (isKeyPresent (span , AWS_LAMBDA_NAME )) {
494
+ remoteResourceType = Optional .of (NORMALIZED_LAMBDA_SERVICE_NAME + "::Function" );
495
+ remoteResourceIdentifier =
496
+ getLambdaResourceNameFromAribitraryName (
497
+ Optional .ofNullable (escapeDelimiters (span .getAttributes ().get (AWS_LAMBDA_NAME ))));
498
+ } else if (isKeyPresent (span , AWS_LAMBDA_RESOURCE_ID )) {
499
+ remoteResourceType = Optional .of (NORMALIZED_LAMBDA_SERVICE_NAME + "::EventSourceMapping" );
500
+ remoteResourceIdentifier =
501
+ Optional .ofNullable (escapeDelimiters (span .getAttributes ().get (AWS_LAMBDA_RESOURCE_ID )));
437
502
}
438
503
} else if (isDBSpan (span )) {
439
504
remoteResourceType = Optional .of (DB_CONNECTION_RESOURCE_TYPE );
440
505
remoteResourceIdentifier = getDbConnection (span );
441
506
}
442
507
508
+ if (cloudformationPrimaryIdentifier .isEmpty ()) {
509
+ cloudformationPrimaryIdentifier = remoteResourceIdentifier ;
510
+ }
511
+
443
512
if (remoteResourceType .isPresent () && remoteResourceIdentifier .isPresent ()) {
444
513
builder .put (AWS_REMOTE_RESOURCE_TYPE , remoteResourceType .get ());
445
514
builder .put (AWS_REMOTE_RESOURCE_IDENTIFIER , remoteResourceIdentifier .get ());
515
+ builder .put (AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER , cloudformationPrimaryIdentifier .get ());
446
516
}
447
517
}
448
518
519
+ // NOTE: "name" in this case can be either the lambda name or lambda arn
520
+ private static Optional <String > getLambdaResourceNameFromAribitraryName (
521
+ Optional <String > arbitraryName ) {
522
+ if (arbitraryName != null && arbitraryName .get ().startsWith ("arn:aws:lambda:" )) {
523
+ Arn resourceArn = Arn .fromString (arbitraryName .get ());
524
+ return Optional .of (resourceArn .getResource ().toString ().split (":" )[1 ]);
525
+ }
526
+ return arbitraryName ;
527
+ }
528
+
529
+ private static Optional <String > getSecretsManagerResourceNameFromArn (Optional <String > stringArn ) {
530
+ Arn resourceArn = Arn .fromString (stringArn .get ());
531
+ return Optional .of (resourceArn .getResource ().toString ().split (":" )[1 ]);
532
+ }
533
+
534
+ private static Optional <String > getSfnResourceNameFromArn (Optional <String > stringArn ) {
535
+ Arn resourceArn = Arn .fromString (stringArn .get ());
536
+ return Optional .of (resourceArn .getResource ().toString ().split (":" )[1 ]);
537
+ }
538
+
539
+ private static Optional <String > getSnsResourceNameFromArn (Optional <String > stringArn ) {
540
+ Arn resourceArn = Arn .fromString (stringArn .get ());
541
+ return Optional .of (resourceArn .getResource ().toString ());
542
+ }
543
+
449
544
/**
450
545
* RemoteResourceIdentifier is populated with rule <code>
451
546
* ^[{db.name}|]?{address}[|{port}]?
0 commit comments