GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — feat(boto3): Add SNS extension (#8142) · getsentry/sentry-python@36870b8

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • MIGRATION_GUIDE.md
  • sentry_sdk
    • consts.py
    • integrations/boto3/_services
      • sns.py
  • tests/integrations/boto3
    • test_sns.py
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎MIGRATION_GUIDE.md‎

Copy file name to clipboardExpand all lines: MIGRATION_GUIDE.md
+2-2Lines changed: 2 additions & 2 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh
4747
- The `RustTracingIntegration` no longer includes the values of tracing fields if `send_default_pii` is enabled. Pass `include_tracing_fields=True` to the integration to include them.
4848
- Whether the Dramatiq integration attaches message bodies to events is now controlled by `data_collection`'s `queues` setting instead of `http_bodies`.
4949
- The Celery integration no longer sets the status of task spans to error when a task raises a control flow exception (`Retry`, `Ignore`, or `Reject`).
50-
- The boto3 integration now names spans `<ServiceID>.<Operation>` (for example, `S3.GetObject` or `DynamoDB.GetItem`), following OpenTelemetry semantic conventions. Previously, spans were named `aws.<service-id>.<Operation>` (for example, `aws.s3.GetObject`). Its spans, including the span for reading a streamed response body, now also have the origin `auto.aws.boto3` instead of `auto.http.boto3`. SQS messaging calls are the exception: `SendMessage` and `SendMessageBatch` are named `send <queue name>`, `ReceiveMessage` is named `receive <queue name>`, and `DeleteMessage` and `DeleteMessageBatch` are named `settle <queue name>`. Update any alerts, dashboards, or `ignore_spans` rules that match on the old names or origin.
50+
- The boto3 integration now names spans `<ServiceID>.<Operation>` (for example, `S3.GetObject` or `DynamoDB.GetItem`), following OpenTelemetry semantic conventions. Previously, spans were named `aws.<service-id>.<Operation>` (for example, `aws.s3.GetObject`). Its spans, including the span for reading a streamed response body, now also have the origin `auto.aws.boto3` instead of `auto.http.boto3`. SQS and SNS messaging calls are the exception: SQS `SendMessage` and `SendMessageBatch` are named `send <queue name>`, `ReceiveMessage` is named `receive <queue name>`, and `DeleteMessage` and `DeleteMessageBatch` are named `settle <queue name>`; SNS `Publish` and `PublishBatch` are named `send <topic name>`. Update any alerts, dashboards, or `ignore_spans` rules that match on the old names or origin.
5151
- Enabling an AI agent integration (LangChain, OpenAI Agents, or Pydantic AI) no longer disables the OpenAI, Anthropic, and Google GenAI integrations. Instead, those integrations don't create chat spans for requests made from within an agent framework's chat span, but still create other spans, such as embedding spans. The LangChain integration no longer instruments embeddings directly; embedding spans are now created by the integration of the underlying client library.
5252
- Whether the MCP integration records tool arguments, tool results, and prompt contents is now controlled by `data_collection`'s new `mcp` setting (`{"inputs": bool, "outputs": bool}`, both `True` by default) instead of the `gen_ai` setting.
5353
- With `handled_tool_call_exceptions=True` (the default), the Pydantic AI integration now reports an error for every failed tool argument validation attempt, including retries. Previously, only one error was reported per tool call.
@@ -77,7 +77,7 @@ Span ops are now a smaller, framework-neutral set.
7777
- The Django integration now emits `view.render` instead of `view.response.render`, `view` instead of `view.authenticate`, and `function` instead of `event.django`.
7878
- The Django, Starlette, Starlite, and Litestar integrations now emit `middleware` instead of `middleware.django`, `middleware.starlette`, `middleware.starlette.receive`, `middleware.starlette.send`, `middleware.starlite`, `middleware.starlite.receive`, `middleware.starlite.send`, `middleware.litestar`, `middleware.litestar.receive`, and `middleware.litestar.send`.
7979
- The ARQ, Celery, Django, Dramatiq, Huey, RQ, and Ray integrations now emit `queue.publish` and `queue.process` instead of `queue.submit.arq`, `queue.task.arq`, `queue.submit.celery`, `queue.task.celery`, `queue.submit.django`, `queue.task.dramatiq`, `queue.submit.huey`, `queue.task.huey`, `queue.task.rq`, `queue.submit.ray`, and `queue.task.ray`.
80-
- The Boto3 integration now emits `rpc` instead of `http.client` for AWS API calls. SQS messaging calls emit `queue.publish` (`SendMessage`, `SendMessageBatch`), `queue.receive` (`ReceiveMessage`), and `queue.settle` (`DeleteMessage`, `DeleteMessageBatch`) instead.
80+
- The Boto3 integration now emits `rpc` instead of `http.client` for AWS API calls. SQS messaging calls emit `queue.publish` (`SendMessage`, `SendMessageBatch`), `queue.receive` (`ReceiveMessage`), and `queue.settle` (`DeleteMessage`, `DeleteMessageBatch`) instead, and SNS `Publish` and `PublishBatch` emit `queue.publish`.
8181

8282
#### GenAI span attributes
8383

Collapse file

‎sentry_sdk/consts.py‎

Copy file name to clipboardExpand all lines: sentry_sdk/consts.py
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,12 @@ class SPANDATA:
489489
Example: "https://sqs.us-east-1.amazonaws.com/123456789012/orders"
490490
"""
491491

492+
AWS_SNS_TOPIC_ARN = "aws.sns.topic.arn"
493+
"""
494+
The ARN of the AWS SNS topic the request refers to.
495+
Example: "arn:aws:sns:us-east-1:123456789012:alerts"
496+
"""
497+
492498
CACHE_HIT = "cache.hit"
493499
"""
494500
A boolean indicating whether the requested data was found in the cache.
Collapse file

‎sentry_sdk/integrations/boto3/_services/sns.py‎

Copy file name to clipboard
+107-12Lines changed: 107 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,131 @@
11
from typing import TYPE_CHECKING
22

3+
import sentry_sdk
4+
from sentry_sdk.consts import OP, SPANDATA
35
from sentry_sdk.integrations.boto3._services.base import _ServiceExtension
4-
from sentry_sdk.integrations.boto3._utils import _get_aws_arn_attributes
6+
from sentry_sdk.integrations.boto3._utils import (
7+
_get_aws_arn_attributes,
8+
_get_batch_error_type,
9+
)
10+
from sentry_sdk.traces import SpanStatus
511
from sentry_sdk.utils import capture_internal_exceptions
612

713
if TYPE_CHECKING:
8-
from typing import Any
14+
from typing import Any, Optional
915

1016
from sentry_sdk._types import Attributes
1117
from sentry_sdk.integrations.boto3._context import AwsCallContext
1218
from sentry_sdk.traces import Span
1319

20+
_PUBLISH_OPERATIONS = ("Publish", "PublishBatch")
21+
1422

1523
class _SNSExtension(_ServiceExtension):
24+
def get_span_op(self, ctx: "AwsCallContext") -> "Optional[str]":
25+
if ctx.operation_name in _PUBLISH_OPERATIONS:
26+
return OP.QUEUE_PUBLISH
27+
# defaults to `rpc` for other operations.
28+
return None
29+
30+
def get_span_name(
31+
self, ctx: "AwsCallContext", attributes: "Attributes"
32+
) -> "Optional[str]":
33+
if ctx.operation_name not in _PUBLISH_OPERATIONS:
34+
return None
35+
36+
destination = attributes.get(SPANDATA.MESSAGING_DESTINATION_NAME)
37+
if destination is None and SPANDATA.SERVER_ADDRESS in attributes:
38+
destination = f"{attributes[SPANDATA.SERVER_ADDRESS]}:{attributes[SPANDATA.SERVER_PORT]}"
39+
40+
# for example: `send <topic name>` when `messaging.operation.type=send` (always send).
41+
# https://opentelemetry.io/docs/specs/semconv/messaging/messaging-spans/#span-name
42+
return f"send {destination}" if destination else "send"
43+
1644
def get_request_attributes(self, ctx: "AwsCallContext") -> "Attributes":
1745
attributes: "Attributes" = {}
46+
47+
# botocore validates params after this hook, so a malformed value must only
48+
# lose the attributes read from it, not the span.
49+
target_arn = ctx.params.get("TargetArn")
50+
endpoint_arn = ctx.params.get("EndpointArn")
51+
topic_arn = None
1852
with capture_internal_exceptions():
53+
# `TargetArn` can be either a topic or a platform endpoint; a topic ARN
54+
# should never contain ":endpoint/".
55+
if target_arn and ":endpoint/" in target_arn:
56+
endpoint_arn, target_arn = target_arn, None
57+
58+
# `TopicArn` and `ResourceArn` are always topic ARNs.
59+
topic_arn = (
60+
ctx.params.get("TopicArn")
61+
or ctx.params.get("ResourceArn")
62+
or target_arn
63+
)
64+
65+
if topic_arn:
66+
attributes[SPANDATA.AWS_SNS_TOPIC_ARN] = topic_arn
67+
# `arn:aws:sns:eu-north-1:123456789012:alerts` -> `alerts`
68+
topic_name = topic_arn.split(":")[-1]
69+
attributes[SPANDATA.MESSAGING_DESTINATION_NAME] = topic_name
70+
elif ctx.operation_name == "CreateTopic" and "Name" in ctx.params:
71+
attributes[SPANDATA.MESSAGING_DESTINATION_NAME] = ctx.params["Name"]
72+
73+
if ctx.operation_name in _PUBLISH_OPERATIONS:
1974
attributes.update(
20-
_get_aws_arn_attributes(
21-
(
22-
ctx.params.get("EndpointArn"),
23-
ctx.params.get("PlatformApplicationArn"),
24-
ctx.params.get("SubscriptionArn"),
25-
ctx.params.get("TargetArn"),
26-
ctx.params.get("TopicArn"),
27-
),
28-
("sns",),
29-
)
75+
{
76+
SPANDATA.SENTRY_KIND: "producer",
77+
SPANDATA.MESSAGING_SYSTEM: "aws.sns",
78+
SPANDATA.MESSAGING_OPERATION_TYPE: "send",
79+
SPANDATA.MESSAGING_OPERATION_NAME: "publish",
80+
}
3081
)
82+
83+
# phone numbers and device endpoints are PII.
84+
if "PhoneNumber" in ctx.params or endpoint_arn:
85+
attributes[SPANDATA.MESSAGING_DESTINATION_NAME] = "[Filtered]"
86+
if "PublishBatchRequestEntries" in ctx.params:
87+
with capture_internal_exceptions():
88+
attributes[SPANDATA.MESSAGING_BATCH_MESSAGE_COUNT] = len(
89+
ctx.params["PublishBatchRequestEntries"]
90+
)
91+
92+
# if scrubbing fails, drop all ARN attributes rather than send a raw
93+
# endpoint or subscription ARN.
94+
with capture_internal_exceptions():
95+
# endpoints and subscriptions identify a single device or subscriber.
96+
subscription_arn = ctx.params.get("SubscriptionArn")
97+
if not sentry_sdk.get_client().options["data_collection"]["user_info"]:
98+
if endpoint_arn:
99+
endpoint_arn = endpoint_arn.rsplit("/", 1)[0].replace(
100+
":endpoint/", ":app/", 1
101+
)
102+
if subscription_arn:
103+
subscription_arn = subscription_arn.rsplit(":", 1)[0]
104+
105+
arns = (
106+
ctx.params.get("PlatformApplicationArn"),
107+
topic_arn,
108+
endpoint_arn,
109+
subscription_arn,
110+
)
111+
attributes.update(_get_aws_arn_attributes(arns, ("sns",)))
31112
return attributes
32113

33114
def on_success_response(
34115
self, ctx: "AwsCallContext", response: "Any", span: "Span"
35116
) -> None:
117+
attributes: "Attributes" = {}
118+
119+
# the call already succeeded; an unexpected response shape, e.g. from a
120+
# `Stubber` or an SNS-compatible service, must only lose these attributes.
121+
with capture_internal_exceptions():
122+
if ctx.operation_name == "Publish" and "MessageId" in response:
123+
attributes[SPANDATA.MESSAGING_MESSAGE_ID] = response["MessageId"]
124+
125+
error_type = _get_batch_error_type(response)
126+
if error_type is not None:
127+
span.status = SpanStatus.ERROR
128+
attributes[SPANDATA.ERROR_TYPE] = error_type
129+
130+
span.set_attributes(attributes)
36131
span.end()

0 commit comments

Comments
0 (0)
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.