7
7
from urllib .parse import ParseResult , urlparse
8
8
9
9
from amazon .opentelemetry .distro ._aws_attribute_keys import (
10
+ AWS_AUTH_ACCESS_KEY ,
11
+ AWS_AUTH_REGION ,
10
12
AWS_BEDROCK_AGENT_ID ,
11
13
AWS_BEDROCK_DATA_SOURCE_ID ,
12
14
AWS_BEDROCK_GUARDRAIL_ARN ,
13
15
AWS_BEDROCK_GUARDRAIL_ID ,
14
16
AWS_BEDROCK_KNOWLEDGE_BASE_ID ,
15
17
AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER ,
18
+ AWS_DYNAMODB_TABLE_ARN ,
19
+ AWS_KINESIS_STREAM_ARN ,
16
20
AWS_KINESIS_STREAM_NAME ,
17
21
AWS_LAMBDA_FUNCTION_ARN ,
18
22
AWS_LAMBDA_FUNCTION_NAME ,
22
26
AWS_REMOTE_DB_USER ,
23
27
AWS_REMOTE_ENVIRONMENT ,
24
28
AWS_REMOTE_OPERATION ,
29
+ AWS_REMOTE_RESOURCE_ACCESS_KEY ,
30
+ AWS_REMOTE_RESOURCE_ACCOUNT_ID ,
25
31
AWS_REMOTE_RESOURCE_IDENTIFIER ,
32
+ AWS_REMOTE_RESOURCE_REGION ,
26
33
AWS_REMOTE_RESOURCE_TYPE ,
27
34
AWS_REMOTE_SERVICE ,
28
35
AWS_SECRETSMANAGER_SECRET_ARN ,
56
63
SERVICE_METRIC ,
57
64
MetricAttributeGenerator ,
58
65
)
66
+ from amazon .opentelemetry .distro .regional_resource_arn_parser import RegionalResourceArnParser
59
67
from amazon .opentelemetry .distro .sqs_url_parser import SqsUrlParser
60
68
from opentelemetry .sdk .resources import Resource
61
69
from opentelemetry .sdk .trace import BoundedAttributes , ReadableSpan
@@ -148,7 +156,11 @@ def _generate_dependency_metric_attributes(span: ReadableSpan, resource: Resourc
148
156
_set_service (resource , span , attributes )
149
157
_set_egress_operation (span , attributes )
150
158
_set_remote_service_and_operation (span , attributes )
151
- _set_remote_type_and_identifier (span , attributes )
159
+ is_remote_identifier_present = _set_remote_type_and_identifier (span , attributes )
160
+ if is_remote_identifier_present :
161
+ is_remote_account_id_present = _set_remote_account_id_and_region (span , attributes )
162
+ if not is_remote_account_id_present :
163
+ _set_remote_access_key_and_region (span , attributes )
152
164
_set_remote_environment (span , attributes )
153
165
_set_remote_db_user (span , attributes )
154
166
_set_span_kind_for_dependency (span , attributes )
@@ -383,7 +395,7 @@ def _generate_remote_operation(span: ReadableSpan) -> str:
383
395
384
396
385
397
# pylint: disable=too-many-branches,too-many-statements
386
- def _set_remote_type_and_identifier (span : ReadableSpan , attributes : BoundedAttributes ) -> None :
398
+ def _set_remote_type_and_identifier (span : ReadableSpan , attributes : BoundedAttributes ) -> bool :
387
399
"""
388
400
Remote resource attributes {@link AwsAttributeKeys#AWS_REMOTE_RESOURCE_TYPE} and {@link
389
401
AwsAttributeKeys#AWS_REMOTE_RESOURCE_IDENTIFIER} are used to store information about the resource associated with
@@ -403,9 +415,23 @@ def _set_remote_type_and_identifier(span: ReadableSpan, attributes: BoundedAttri
403
415
if is_key_present (span , _AWS_TABLE_NAMES ) and len (span .attributes .get (_AWS_TABLE_NAMES )) == 1 :
404
416
remote_resource_type = _NORMALIZED_DYNAMO_DB_SERVICE_NAME + "::Table"
405
417
remote_resource_identifier = _escape_delimiters (span .attributes .get (_AWS_TABLE_NAMES )[0 ])
418
+ elif is_key_present (span , AWS_DYNAMODB_TABLE_ARN ):
419
+ remote_resource_type = _NORMALIZED_DYNAMO_DB_SERVICE_NAME + "::Table"
420
+ remote_resource_identifier = _escape_delimiters (
421
+ RegionalResourceArnParser .extract_dynamodb_table_name_from_arn (
422
+ span .attributes .get (AWS_DYNAMODB_TABLE_ARN )
423
+ )
424
+ )
406
425
elif is_key_present (span , AWS_KINESIS_STREAM_NAME ):
407
426
remote_resource_type = _NORMALIZED_KINESIS_SERVICE_NAME + "::Stream"
408
427
remote_resource_identifier = _escape_delimiters (span .attributes .get (AWS_KINESIS_STREAM_NAME ))
428
+ elif is_key_present (span , AWS_KINESIS_STREAM_ARN ):
429
+ remote_resource_type = _NORMALIZED_KINESIS_SERVICE_NAME + "::Stream"
430
+ remote_resource_identifier = _escape_delimiters (
431
+ RegionalResourceArnParser .extract_kinesis_stream_name_from_arn (
432
+ span .attributes .get (AWS_KINESIS_STREAM_ARN )
433
+ )
434
+ )
409
435
elif is_key_present (span , _AWS_BUCKET_NAME ):
410
436
remote_resource_type = _NORMALIZED_S3_SERVICE_NAME + "::Bucket"
411
437
remote_resource_identifier = _escape_delimiters (span .attributes .get (_AWS_BUCKET_NAME ))
@@ -442,27 +468,35 @@ def _set_remote_type_and_identifier(span: ReadableSpan, attributes: BoundedAttri
442
468
remote_resource_identifier = _escape_delimiters (span .attributes .get (GEN_AI_REQUEST_MODEL ))
443
469
elif is_key_present (span , AWS_SECRETSMANAGER_SECRET_ARN ):
444
470
remote_resource_type = _NORMALIZED_SECRETSMANAGER_SERVICE_NAME + "::Secret"
445
- remote_resource_identifier = _escape_delimiters (span .attributes .get (AWS_SECRETSMANAGER_SECRET_ARN )).split (
446
- ":"
447
- )[- 1 ]
471
+ remote_resource_identifier = _escape_delimiters (
472
+ RegionalResourceArnParser .extract_resource_name_from_arn (
473
+ span .attributes .get (AWS_SECRETSMANAGER_SECRET_ARN )
474
+ )
475
+ )
448
476
cloudformation_primary_identifier = _escape_delimiters (span .attributes .get (AWS_SECRETSMANAGER_SECRET_ARN ))
449
477
elif is_key_present (span , AWS_SNS_TOPIC_ARN ):
450
478
remote_resource_type = _NORMALIZED_SNS_SERVICE_NAME + "::Topic"
451
- remote_resource_identifier = _escape_delimiters (span .attributes .get (AWS_SNS_TOPIC_ARN )).split (":" )[- 1 ]
479
+ remote_resource_identifier = _escape_delimiters (
480
+ RegionalResourceArnParser .extract_resource_name_from_arn (span .attributes .get (AWS_SNS_TOPIC_ARN ))
481
+ )
452
482
cloudformation_primary_identifier = _escape_delimiters (span .attributes .get (AWS_SNS_TOPIC_ARN ))
453
483
elif is_key_present (span , AWS_STEPFUNCTIONS_STATEMACHINE_ARN ):
454
484
remote_resource_type = _NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + "::StateMachine"
455
485
remote_resource_identifier = _escape_delimiters (
456
- span .attributes .get (AWS_STEPFUNCTIONS_STATEMACHINE_ARN )
457
- ).split (":" )[- 1 ]
486
+ RegionalResourceArnParser .extract_resource_name_from_arn (
487
+ span .attributes .get (AWS_STEPFUNCTIONS_STATEMACHINE_ARN )
488
+ )
489
+ )
458
490
cloudformation_primary_identifier = _escape_delimiters (
459
491
span .attributes .get (AWS_STEPFUNCTIONS_STATEMACHINE_ARN )
460
492
)
461
493
elif is_key_present (span , AWS_STEPFUNCTIONS_ACTIVITY_ARN ):
462
494
remote_resource_type = _NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + "::Activity"
463
- remote_resource_identifier = _escape_delimiters (span .attributes .get (AWS_STEPFUNCTIONS_ACTIVITY_ARN )).split (
464
- ":"
465
- )[- 1 ]
495
+ remote_resource_identifier = _escape_delimiters (
496
+ RegionalResourceArnParser .extract_resource_name_from_arn (
497
+ span .attributes .get (AWS_STEPFUNCTIONS_ACTIVITY_ARN )
498
+ )
499
+ )
466
500
cloudformation_primary_identifier = _escape_delimiters (span .attributes .get (AWS_STEPFUNCTIONS_ACTIVITY_ARN ))
467
501
elif is_key_present (span , AWS_LAMBDA_FUNCTION_NAME ):
468
502
# For non-Invoke Lambda operations, treat Lambda as a resource,
@@ -491,6 +525,48 @@ def _set_remote_type_and_identifier(span: ReadableSpan, attributes: BoundedAttri
491
525
attributes [AWS_REMOTE_RESOURCE_TYPE ] = remote_resource_type
492
526
attributes [AWS_REMOTE_RESOURCE_IDENTIFIER ] = remote_resource_identifier
493
527
attributes [AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER ] = cloudformation_primary_identifier
528
+ return True
529
+ return False
530
+
531
+
532
+ def _set_remote_account_id_and_region (span : ReadableSpan , attributes : BoundedAttributes ) -> bool :
533
+ arn_attributes = [
534
+ AWS_DYNAMODB_TABLE_ARN ,
535
+ AWS_KINESIS_STREAM_ARN ,
536
+ AWS_SNS_TOPIC_ARN ,
537
+ AWS_SECRETSMANAGER_SECRET_ARN ,
538
+ AWS_STEPFUNCTIONS_STATEMACHINE_ARN ,
539
+ AWS_STEPFUNCTIONS_ACTIVITY_ARN ,
540
+ AWS_BEDROCK_GUARDRAIL_ARN ,
541
+ AWS_LAMBDA_FUNCTION_ARN ,
542
+ ]
543
+ remote_account_id : Optional [str ] = None
544
+ remote_region : Optional [str ] = None
545
+
546
+ if is_key_present (span , AWS_SQS_QUEUE_URL ):
547
+ queue_url = _escape_delimiters (span .attributes .get (AWS_SQS_QUEUE_URL ))
548
+ remote_account_id = SqsUrlParser .get_account_id (queue_url )
549
+ remote_region = SqsUrlParser .get_region (queue_url )
550
+ else :
551
+ for arn_attribute in arn_attributes :
552
+ if is_key_present (span , arn_attribute ):
553
+ arn = span .attributes .get (arn_attribute )
554
+ remote_account_id = RegionalResourceArnParser .get_account_id (arn )
555
+ remote_region = RegionalResourceArnParser .get_region (arn )
556
+ break
557
+
558
+ if remote_account_id is not None and remote_region is not None :
559
+ attributes [AWS_REMOTE_RESOURCE_ACCOUNT_ID ] = remote_account_id
560
+ attributes [AWS_REMOTE_RESOURCE_REGION ] = remote_region
561
+ return True
562
+ return False
563
+
564
+
565
+ def _set_remote_access_key_and_region (span : ReadableSpan , attributes : BoundedAttributes ) -> None :
566
+ if is_key_present (span , AWS_AUTH_ACCESS_KEY ):
567
+ attributes [AWS_REMOTE_RESOURCE_ACCESS_KEY ] = span .attributes .get (AWS_AUTH_ACCESS_KEY )
568
+ if is_key_present (span , AWS_AUTH_REGION ):
569
+ attributes [AWS_REMOTE_RESOURCE_REGION ] = span .attributes .get (AWS_AUTH_REGION )
494
570
495
571
496
572
def _set_remote_environment (span : ReadableSpan , attributes : BoundedAttributes ) -> None :
0 commit comments