Skip to content

Commit 6525da4

Browse files
lukeina2zxrmx
andauthored
botocore: Add support for SNS semantic convention attribute aws.sns.topic.arn (#3734)
* botocore: Add support for SNS semantic convention attribute aws.sns.topic.arn The AWS SNS semantic convention defines the attribute aws.sns.topic.arn: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/registry/attributes/aws.md#amazon-sns-attributes Currently, this attribute is not set in the botocore instrumentation library. This PR adds support for it by setting the attribute from both the request and response objects. Tests New unit tests added and passing. Verified with: tox -e py312-test-instrumentation-botocore tox -e spellcheck tox -e lint-instrumentation-botocore tox -e ruff Backward Compatibility There is no risk of breaking existing functionality. This change only adds instrumentation for an additional AWS resource without modifying the existing behavior of the auto-instrumentation library. * add changelog. --------- Co-authored-by: Riccardo Magliocchetti <[email protected]>
1 parent 5caf8c2 commit 6525da4

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4444
([#3366](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3366))
4545
- `opentelemetry-instrumentation`: add support for `OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH` to inform opentelemetry-instrument about gevent monkeypatching
4646
([#3699](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3699))
47+
- `opentelemetry-instrumentation-botocore`: Add support for SNS semantic convention attribute aws.sns.topic.arn
48+
([#3734](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3734))
4749

4850
## Version 1.36.0/0.57b0 (2025-07-29)
4951

instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/sns.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
_AwsSdkCallContext,
2525
_AwsSdkExtension,
2626
_BotocoreInstrumentorContext,
27+
_BotoResultT,
28+
)
29+
from opentelemetry.semconv._incubating.attributes.aws_attributes import (
30+
AWS_SNS_TOPIC_ARN,
2731
)
2832
from opentelemetry.semconv.trace import (
2933
MessagingDestinationKindValues,
@@ -161,6 +165,9 @@ def __init__(self, call_context: _AwsSdkCallContext):
161165

162166
def extract_attributes(self, attributes: _AttributeMapT):
163167
attributes[SpanAttributes.MESSAGING_SYSTEM] = "aws.sns"
168+
topic_arn = self._call_context.params.get("TopicArn")
169+
if topic_arn:
170+
attributes[AWS_SNS_TOPIC_ARN] = topic_arn
164171

165172
if self._op:
166173
self._op.extract_attributes(self._call_context, attributes)
@@ -170,3 +177,16 @@ def before_service_call(
170177
):
171178
if self._op:
172179
self._op.before_service_call(self._call_context, span)
180+
181+
def on_success(
182+
self,
183+
span: Span,
184+
result: _BotoResultT,
185+
instrumentor_context: _BotocoreInstrumentorContext,
186+
):
187+
if not span.is_recording():
188+
return
189+
190+
topic_arn = result.get("TopicArn")
191+
if topic_arn:
192+
span.set_attribute(AWS_SNS_TOPIC_ARN, topic_arn)

instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_sns.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
from moto import mock_aws
2222

2323
from opentelemetry.instrumentation.botocore import BotocoreInstrumentor
24+
from opentelemetry.semconv._incubating.attributes.aws_attributes import (
25+
AWS_SNS_TOPIC_ARN,
26+
)
2427
from opentelemetry.semconv.trace import (
2528
MessagingDestinationKindValues,
2629
SpanAttributes,
@@ -151,6 +154,10 @@ def test_publish_injects_span(self):
151154
)
152155

153156
span = self.assert_span(f"{self.topic_name} send")
157+
self.assertEqual(
158+
topic_arn,
159+
span.attributes[AWS_SNS_TOPIC_ARN],
160+
)
154161
self.assert_injected_span(message_attrs, span)
155162

156163
def test_publish_batch_to_topic(self):
@@ -188,6 +195,10 @@ def test_publish_batch_to_topic(self):
188195
MessagingDestinationKindValues.TOPIC.value,
189196
span.attributes[SpanAttributes.MESSAGING_DESTINATION_KIND],
190197
)
198+
self.assertEqual(
199+
topic_arn,
200+
span.attributes[AWS_SNS_TOPIC_ARN],
201+
)
191202
self.assertEqual(
192203
topic_arn,
193204
span.attributes[SpanAttributes.MESSAGING_DESTINATION],
@@ -199,3 +210,16 @@ def test_publish_batch_to_topic(self):
199210

200211
self.assert_injected_span(message1_attrs, span)
201212
self.assert_injected_span(message2_attrs, span)
213+
214+
@mock_aws
215+
def test_create_topic_span(self):
216+
_ = self.client.create_topic(Name=self.topic_name)
217+
spans = self.memory_exporter.get_finished_spans()
218+
self.assertEqual(1, len(spans))
219+
span = spans[0]
220+
self.assertEqual(SpanKind.CLIENT, span.kind)
221+
self.assertEqual("SNS.CreateTopic", span.name)
222+
self.assertEqual(
223+
self.topic_arn,
224+
span.attributes[AWS_SNS_TOPIC_ARN],
225+
)

0 commit comments

Comments
 (0)