|
12 | 12 | # See the License for the specific language governing permissions and
|
13 | 13 | # limitations under the License.
|
14 | 14 | import json
|
| 15 | +import os |
15 | 16 | from unittest.mock import ANY, Mock, patch
|
16 | 17 |
|
17 | 18 | import botocore.session
|
@@ -63,6 +64,9 @@ def _default_span_attributes(self, service: str, operation: str):
|
63 | 64 | "aws.region": self.region,
|
64 | 65 | "retry_attempts": 0,
|
65 | 66 | SpanAttributes.HTTP_STATUS_CODE: 200,
|
| 67 | + # Some services like IAM or STS have a global endpoint and exclude specified region. |
| 68 | + SpanAttributes.SERVER_ADDRESS: f"{service.lower()}.{'' if self.region == 'aws-global' else self.region + '.'}amazonaws.com", |
| 69 | + SpanAttributes.SERVER_PORT: 443, |
66 | 70 | }
|
67 | 71 |
|
68 | 72 | def assert_only_span(self):
|
@@ -330,6 +334,7 @@ def test_sts_client(self):
|
330 | 334 | span = self.assert_only_span()
|
331 | 335 | expected = self._default_span_attributes("STS", "GetCallerIdentity")
|
332 | 336 | expected["aws.request_id"] = ANY
|
| 337 | + expected[SpanAttributes.SERVER_ADDRESS] = "sts.amazonaws.com" |
333 | 338 | # check for exact attribute set to make sure not to leak any sts secrets
|
334 | 339 | self.assertEqual(expected, dict(span.attributes))
|
335 | 340 |
|
@@ -497,3 +502,56 @@ def response_hook(span, service_name, operation_name, result):
|
497 | 502 | response_hook_result_attribute_name: 0,
|
498 | 503 | },
|
499 | 504 | )
|
| 505 | + |
| 506 | + @mock_aws |
| 507 | + def test_server_attributes(self): |
| 508 | + """Test that server attributes are correctly set for AWS services""" |
| 509 | + # Test regional endpoint |
| 510 | + ec2 = self._make_client("ec2") |
| 511 | + ec2.describe_instances() |
| 512 | + self.assert_span( |
| 513 | + "EC2", |
| 514 | + "DescribeInstances", |
| 515 | + request_id="fdcdcab1-ae5c-489e-9c33-4637c5dda355", |
| 516 | + attributes={ |
| 517 | + SpanAttributes.SERVER_ADDRESS: f"ec2.{self.region}.amazonaws.com", |
| 518 | + SpanAttributes.SERVER_PORT: 443, |
| 519 | + }, |
| 520 | + ) |
| 521 | + self.memory_exporter.clear() |
| 522 | + |
| 523 | + # Test global endpoint |
| 524 | + iam_global = self._make_client("iam") |
| 525 | + iam_global.list_users() |
| 526 | + self.assert_span( |
| 527 | + "IAM", |
| 528 | + "ListUsers", |
| 529 | + attributes={ |
| 530 | + SpanAttributes.SERVER_ADDRESS: "iam.amazonaws.com", |
| 531 | + SpanAttributes.SERVER_PORT: 443, |
| 532 | + "aws.region": "aws-global", |
| 533 | + }, |
| 534 | + ) |
| 535 | + |
| 536 | + @mock_aws |
| 537 | + def test_server_attributes_with_custom_endpoint(self): |
| 538 | + with patch.dict( |
| 539 | + os.environ, |
| 540 | + {"MOTO_S3_CUSTOM_ENDPOINTS": "https://proxy.amazon.org:2025"}, |
| 541 | + ): |
| 542 | + s3 = self.session.create_client( |
| 543 | + "s3", |
| 544 | + region_name=self.region, |
| 545 | + endpoint_url="https://proxy.amazon.org:2025", |
| 546 | + ) |
| 547 | + |
| 548 | + s3.list_buckets() |
| 549 | + |
| 550 | + self.assert_span( |
| 551 | + "S3", |
| 552 | + "ListBuckets", |
| 553 | + attributes={ |
| 554 | + SpanAttributes.SERVER_ADDRESS: "proxy.amazon.org", |
| 555 | + SpanAttributes.SERVER_PORT: 2025, |
| 556 | + }, |
| 557 | + ) |
0 commit comments