Skip to content

Commit 77199b8

Browse files
committed
feat: update existing contract tests for cfn primary id
1 parent de63a81 commit 77199b8

File tree

4 files changed

+56
-1
lines changed

4 files changed

+56
-1
lines changed

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/patches/_botocore_patches.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,16 @@ def patch_extract_attributes(self, attributes: _AttributeMapT):
178178
if queue_url:
179179
attributes[AWS_SQS_QUEUE_URL] = queue_url
180180

181+
old_on_success = _SqsExtension.on_success
182+
183+
def patch_on_success(self, span: Span, result: _BotoResultT):
184+
old_on_success(self, span, result)
185+
queue_url = result.get("QueueUrl")
186+
if queue_url:
187+
span.set_attribute(AWS_SQS_QUEUE_URL, queue_url)
188+
181189
_SqsExtension.extract_attributes = patch_extract_attributes
190+
_SqsExtension.on_success = patch_on_success
182191

183192

184193
def _apply_botocore_bedrock_patch() -> None:

contract-tests/images/applications/botocore/botocore_server.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ def _handle_bedrock_request(self) -> None:
246246
set_main_status(200)
247247
bedrock_client.meta.events.register(
248248
"before-call.bedrock.GetGuardrail",
249-
lambda **kwargs: inject_200_success(guardrailId="bt4o77i015cu", **kwargs),
249+
lambda **kwargs: inject_200_success(guardrailId="bt4o77i015cu", guardrailArn="arn:aws:bedrock:us-east-1:000000000000:guardrail/bt4o77i015cu", **kwargs),
250250
)
251251
bedrock_client.get_guardrail(
252252
guardrailIdentifier="arn:aws:bedrock:us-east-1:000000000000:guardrail/bt4o77i015cu"
@@ -363,6 +363,9 @@ def inject_200_success(**kwargs):
363363
guardrail_id = kwargs.get("guardrailId")
364364
if guardrail_id is not None:
365365
response_body["guardrailId"] = guardrail_id
366+
guardrail_arn = kwargs.get("guardrailArn")
367+
if guardrail_arn is not None:
368+
response_body["guardrailArn"] = guardrail_arn
366369

367370
HTTPResponse = namedtuple("HTTPResponse", ["status_code", "headers", "body"])
368371
headers = kwargs.get("headers", {})

contract-tests/tests/test/amazon/botocore/botocore_test.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from amazon.base.contract_test_base import NETWORK_NAME, ContractTestBase
1212
from amazon.utils.application_signals_constants import (
13+
AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER,
1314
AWS_LOCAL_OPERATION,
1415
AWS_LOCAL_SERVICE,
1516
AWS_REMOTE_OPERATION,
@@ -99,6 +100,7 @@ def test_s3_create_bucket(self):
99100
remote_operation="CreateBucket",
100101
remote_resource_type="AWS::S3::Bucket",
101102
remote_resource_identifier="test-bucket-name",
103+
cloudformation_primary_identifier="test-bucket-name",
102104
request_specific_attributes={
103105
SpanAttributes.AWS_S3_BUCKET: "test-bucket-name",
104106
},
@@ -116,6 +118,7 @@ def test_s3_create_object(self):
116118
remote_operation="PutObject",
117119
remote_resource_type="AWS::S3::Bucket",
118120
remote_resource_identifier="test-put-object-bucket-name",
121+
cloudformation_primary_identifier="test-put-object-bucket-name",
119122
request_specific_attributes={
120123
SpanAttributes.AWS_S3_BUCKET: "test-put-object-bucket-name",
121124
},
@@ -133,6 +136,7 @@ def test_s3_get_object(self):
133136
remote_operation="GetObject",
134137
remote_resource_type="AWS::S3::Bucket",
135138
remote_resource_identifier="test-get-object-bucket-name",
139+
cloudformation_primary_identifier="test-get-object-bucket-name",
136140
request_specific_attributes={
137141
SpanAttributes.AWS_S3_BUCKET: "test-get-object-bucket-name",
138142
},
@@ -150,6 +154,7 @@ def test_s3_error(self):
150154
remote_operation="CreateBucket",
151155
remote_resource_type="AWS::S3::Bucket",
152156
remote_resource_identifier="-",
157+
cloudformation_primary_identifier="-",
153158
request_specific_attributes={
154159
SpanAttributes.AWS_S3_BUCKET: "-",
155160
},
@@ -167,6 +172,7 @@ def test_s3_fault(self):
167172
remote_operation="CreateBucket",
168173
remote_resource_type="AWS::S3::Bucket",
169174
remote_resource_identifier="valid-bucket-name",
175+
cloudformation_primary_identifier="valid-bucket-name",
170176
request_specific_attributes={
171177
SpanAttributes.AWS_S3_BUCKET: "valid-bucket-name",
172178
},
@@ -184,6 +190,7 @@ def test_dynamodb_create_table(self):
184190
remote_operation="CreateTable",
185191
remote_resource_type="AWS::DynamoDB::Table",
186192
remote_resource_identifier="test_table",
193+
cloudformation_primary_identifier="test_table",
187194
request_specific_attributes={
188195
SpanAttributes.AWS_DYNAMODB_TABLE_NAMES: ["test_table"],
189196
},
@@ -201,6 +208,7 @@ def test_dynamodb_put_item(self):
201208
remote_operation="PutItem",
202209
remote_resource_type="AWS::DynamoDB::Table",
203210
remote_resource_identifier="put_test_table",
211+
cloudformation_primary_identifier="put_test_table",
204212
request_specific_attributes={
205213
SpanAttributes.AWS_DYNAMODB_TABLE_NAMES: ["put_test_table"],
206214
},
@@ -218,6 +226,7 @@ def test_dynamodb_error(self):
218226
remote_operation="PutItem",
219227
remote_resource_type="AWS::DynamoDB::Table",
220228
remote_resource_identifier="invalid_table",
229+
cloudformation_primary_identifier="invalid_table",
221230
request_specific_attributes={
222231
SpanAttributes.AWS_DYNAMODB_TABLE_NAMES: ["invalid_table"],
223232
},
@@ -235,6 +244,7 @@ def test_dynamodb_fault(self):
235244
remote_operation="PutItem",
236245
remote_resource_type="AWS::DynamoDB::Table",
237246
remote_resource_identifier="invalid_table",
247+
cloudformation_primary_identifier="invalid_table",
238248
request_specific_attributes={
239249
SpanAttributes.AWS_DYNAMODB_TABLE_NAMES: ["invalid_table"],
240250
},
@@ -252,9 +262,13 @@ def test_sqs_create_queue(self):
252262
remote_operation="CreateQueue",
253263
remote_resource_type="AWS::SQS::Queue",
254264
remote_resource_identifier="test_queue",
265+
cloudformation_primary_identifier="http://sqs.us-west-2.localhost.localstack.cloud:4566/000000000000/test_queue",
255266
request_specific_attributes={
256267
_AWS_SQS_QUEUE_NAME: "test_queue",
257268
},
269+
response_specific_attributes={
270+
_AWS_SQS_QUEUE_URL: "http://sqs.us-west-2.localhost.localstack.cloud:4566/000000000000/test_queue",
271+
},
258272
span_name="SQS.CreateQueue",
259273
)
260274

@@ -269,6 +283,7 @@ def test_sqs_send_message(self):
269283
remote_operation="SendMessage",
270284
remote_resource_type="AWS::SQS::Queue",
271285
remote_resource_identifier="test_put_get_queue",
286+
cloudformation_primary_identifier="http://localstack:4566/000000000000/test_put_get_queue",
272287
request_specific_attributes={
273288
_AWS_SQS_QUEUE_URL: "http://localstack:4566/000000000000/test_put_get_queue",
274289
},
@@ -286,6 +301,7 @@ def test_sqs_receive_message(self):
286301
remote_operation="ReceiveMessage",
287302
remote_resource_type="AWS::SQS::Queue",
288303
remote_resource_identifier="test_put_get_queue",
304+
cloudformation_primary_identifier="http://localstack:4566/000000000000/test_put_get_queue",
289305
request_specific_attributes={
290306
_AWS_SQS_QUEUE_URL: "http://localstack:4566/000000000000/test_put_get_queue",
291307
},
@@ -303,6 +319,7 @@ def test_sqs_error(self):
303319
remote_operation="SendMessage",
304320
remote_resource_type="AWS::SQS::Queue",
305321
remote_resource_identifier="sqserror",
322+
cloudformation_primary_identifier="http://error.test:8080/000000000000/sqserror",
306323
request_specific_attributes={
307324
_AWS_SQS_QUEUE_URL: "http://error.test:8080/000000000000/sqserror",
308325
},
@@ -320,6 +337,7 @@ def test_sqs_fault(self):
320337
remote_operation="CreateQueue",
321338
remote_resource_type="AWS::SQS::Queue",
322339
remote_resource_identifier="invalid_test",
340+
cloudformation_primary_identifier="invalid_test",
323341
request_specific_attributes={
324342
_AWS_SQS_QUEUE_NAME: "invalid_test",
325343
},
@@ -337,6 +355,7 @@ def test_kinesis_put_record(self):
337355
remote_operation="PutRecord",
338356
remote_resource_type="AWS::Kinesis::Stream",
339357
remote_resource_identifier="test_stream",
358+
cloudformation_primary_identifier="test_stream",
340359
request_specific_attributes={
341360
_AWS_KINESIS_STREAM_NAME: "test_stream",
342361
},
@@ -354,6 +373,7 @@ def test_kinesis_error(self):
354373
remote_operation="PutRecord",
355374
remote_resource_type="AWS::Kinesis::Stream",
356375
remote_resource_identifier="invalid_stream",
376+
cloudformation_primary_identifier="invalid_stream",
357377
request_specific_attributes={
358378
_AWS_KINESIS_STREAM_NAME: "invalid_stream",
359379
},
@@ -371,6 +391,7 @@ def test_kinesis_fault(self):
371391
remote_operation="PutRecord",
372392
remote_resource_type="AWS::Kinesis::Stream",
373393
remote_resource_identifier="test_stream",
394+
cloudformation_primary_identifier="test_stream",
374395
request_specific_attributes={
375396
_AWS_KINESIS_STREAM_NAME: "test_stream",
376397
},
@@ -389,6 +410,7 @@ def test_bedrock_runtime_invoke_model(self):
389410
remote_operation="InvokeModel",
390411
remote_resource_type="AWS::Bedrock::Model",
391412
remote_resource_identifier="amazon.titan-text-premier-v1:0",
413+
cloudformation_primary_identifier="amazon.titan-text-premier-v1:0",
392414
request_specific_attributes={
393415
_GEN_AI_REQUEST_MODEL: "amazon.titan-text-premier-v1:0",
394416
},
@@ -407,6 +429,7 @@ def test_bedrock_get_guardrail(self):
407429
remote_operation="GetGuardrail",
408430
remote_resource_type="AWS::Bedrock::Guardrail",
409431
remote_resource_identifier="bt4o77i015cu",
432+
cloudformation_primary_identifier="arn:aws:bedrock:us-east-1:000000000000:guardrail/bt4o77i015cu",
410433
request_specific_attributes={
411434
_AWS_BEDROCK_GUARDRAIL_ID: "bt4o77i015cu",
412435
},
@@ -425,6 +448,7 @@ def test_bedrock_agent_runtime_invoke_agent(self):
425448
remote_operation="InvokeAgent",
426449
remote_resource_type="AWS::Bedrock::Agent",
427450
remote_resource_identifier="Q08WFRPHVL",
451+
cloudformation_primary_identifier="Q08WFRPHVL",
428452
request_specific_attributes={
429453
_AWS_BEDROCK_AGENT_ID: "Q08WFRPHVL",
430454
},
@@ -443,6 +467,7 @@ def test_bedrock_agent_runtime_retrieve(self):
443467
remote_operation="Retrieve",
444468
remote_resource_type="AWS::Bedrock::KnowledgeBase",
445469
remote_resource_identifier="test-knowledge-base-id",
470+
cloudformation_primary_identifier="test-knowledge-base-id",
446471
request_specific_attributes={
447472
_AWS_BEDROCK_KNOWLEDGE_BASE_ID: "test-knowledge-base-id",
448473
},
@@ -461,6 +486,7 @@ def test_bedrock_agent_get_agent(self):
461486
remote_operation="GetAgent",
462487
remote_resource_type="AWS::Bedrock::Agent",
463488
remote_resource_identifier="TESTAGENTID",
489+
cloudformation_primary_identifier="TESTAGENTID",
464490
request_specific_attributes={
465491
_AWS_BEDROCK_AGENT_ID: "TESTAGENTID",
466492
},
@@ -479,6 +505,7 @@ def test_bedrock_agent_get_knowledge_base(self):
479505
remote_operation="GetKnowledgeBase",
480506
remote_resource_type="AWS::Bedrock::KnowledgeBase",
481507
remote_resource_identifier="invalid-knowledge-base-id",
508+
cloudformation_primary_identifier="invalid-knowledge-base-id",
482509
request_specific_attributes={
483510
_AWS_BEDROCK_KNOWLEDGE_BASE_ID: "invalid-knowledge-base-id",
484511
},
@@ -497,8 +524,10 @@ def test_bedrock_agent_get_data_source(self):
497524
remote_operation="GetDataSource",
498525
remote_resource_type="AWS::Bedrock::DataSource",
499526
remote_resource_identifier="DATASURCID",
527+
cloudformation_primary_identifier="TESTKBSEID|DATASURCID",
500528
request_specific_attributes={
501529
_AWS_BEDROCK_DATA_SOURCE_ID: "DATASURCID",
530+
_AWS_BEDROCK_KNOWLEDGE_BASE_ID: "TESTKBSEID",
502531
},
503532
span_name="Bedrock Agent.GetDataSource",
504533
)
@@ -519,6 +548,7 @@ def _assert_aws_span_attributes(self, resource_scope_spans: List[ResourceScopeSp
519548
"LOCAL_ROOT",
520549
kwargs.get("remote_resource_type", "None"),
521550
kwargs.get("remote_resource_identifier", "None"),
551+
kwargs.get("cloudformation_primary_identifier", "None"),
522552
)
523553

524554
def _assert_aws_attributes(
@@ -529,6 +559,7 @@ def _assert_aws_attributes(
529559
span_kind: str,
530560
remote_resource_type: str,
531561
remote_resource_identifier: str,
562+
cloudformation_primary_identifier: str,
532563
) -> None:
533564
attributes_dict: Dict[str, AnyValue] = self._get_attributes_dict(attributes_list)
534565
self._assert_str_attribute(attributes_dict, AWS_LOCAL_SERVICE, self.get_application_otel_service_name())
@@ -541,6 +572,8 @@ def _assert_aws_attributes(
541572
self._assert_str_attribute(attributes_dict, AWS_REMOTE_RESOURCE_TYPE, remote_resource_type)
542573
if remote_resource_identifier != "None":
543574
self._assert_str_attribute(attributes_dict, AWS_REMOTE_RESOURCE_IDENTIFIER, remote_resource_identifier)
575+
if cloudformation_primary_identifier != "None":
576+
self._assert_str_attribute(attributes_dict, AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER, cloudformation_primary_identifier)
544577
# See comment above AWS_LOCAL_OPERATION
545578
self._assert_str_attribute(attributes_dict, AWS_SPAN_KIND, span_kind)
546579

@@ -562,6 +595,7 @@ def _assert_semantic_conventions_span_attributes(
562595
kwargs.get("remote_operation"),
563596
status_code,
564597
kwargs.get("request_specific_attributes", {}),
598+
kwargs.get("response_specific_attributes", {}),
565599
)
566600

567601
# pylint: disable=unidiomatic-typecheck
@@ -572,6 +606,7 @@ def _assert_semantic_conventions_attributes(
572606
operation: str,
573607
status_code: int,
574608
request_specific_attributes: dict,
609+
response_specific_attributes: dict,
575610
) -> None:
576611
attributes_dict: Dict[str, AnyValue] = self._get_attributes_dict(attributes_list)
577612
self._assert_str_attribute(attributes_dict, SpanAttributes.RPC_METHOD, operation)
@@ -587,6 +622,13 @@ def _assert_semantic_conventions_attributes(
587622
self._assert_int_attribute(attributes_dict, key, value)
588623
else:
589624
self._assert_array_value_ddb_table_name(attributes_dict, key, value)
625+
for key, value in response_specific_attributes.items():
626+
if isinstance(value, str):
627+
self._assert_str_attribute(attributes_dict, key, value)
628+
elif isinstance(value, int):
629+
self._assert_int_attribute(attributes_dict, key, value)
630+
else:
631+
self._assert_array_value_ddb_table_name(attributes_dict, key, value)
590632

591633
@override
592634
def _assert_metric_attributes(

contract-tests/tests/test/amazon/utils/application_signals_constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
FAULT_METRIC: str = "fault"
1111

1212
# Attribute names
13+
AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER: str = "aws.remote.resource.cfn.primary.identifier"
1314
AWS_LOCAL_SERVICE: str = "aws.local.service"
1415
AWS_LOCAL_OPERATION: str = "aws.local.operation"
1516
AWS_REMOTE_DB_USER: str = "aws.remote.db.user"

0 commit comments

Comments
 (0)