Skip to content

Support for Python SDK 3.0.0 #92011

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f5010ee
Update requirements
antonpirker May 20, 2025
109670e
Remove propagate_hub because it is not needed because its the default…
antonpirker May 21, 2025
d1c81fb
Removed metrics_noop because there are no metrics anymore and thus no…
antonpirker May 21, 2025
4cbadbc
Merge branch 'master' into antonpirker/code-changes-for-sdk-3.0.0
antonpirker May 21, 2025
2a204f4
Make tests run locally until pytest-sentry is 3.0 compatible
antonpirker May 21, 2025
f3d56a1
Replace .set_data with .set_attribute
antonpirker May 21, 2025
fcc75ac
changed add_attachment
antonpirker May 21, 2025
b75ec43
Changed start_transaction to start_span and custom_sampling_context t…
antonpirker May 21, 2025
420b0e8
Changed continue_trace to use context manager
antonpirker May 21, 2025
4896797
Removed set_measurements helper function because it is not used in co…
antonpirker May 21, 2025
47401ba
oops
antonpirker May 21, 2025
ea9f446
marked places where dict-attributes are
antonpirker May 21, 2025
58062aa
Replaced with
antonpirker May 21, 2025
9ac4468
one more comment
antonpirker May 21, 2025
20c7098
more comments
antonpirker May 21, 2025
ee2cd8e
Merge branch 'master' into antonpirker/code-changes-for-sdk-3.0.0
antonpirker May 21, 2025
5d23052
Merge branch 'master' into antonpirker/code-changes-for-sdk-3.0.0
antonpirker May 21, 2025
e8212a0
Merge branch 'master' into antonpirker/code-changes-for-sdk-3.0.0
antonpirker May 23, 2025
22bfae5
Merge branch 'master' into antonpirker/code-changes-for-sdk-3.0.0
antonpirker May 23, 2025
d72b7c3
bump pytest-sentry
antonpirker May 23, 2025
cbc0ab5
:snowflake: re-freeze requirements
getsantry[bot] May 23, 2025
6a67a42
trigger ci
antonpirker May 23, 2025
6be5d4f
update pytest-sentry
antonpirker May 23, 2025
fbb5794
Replaced .transaction with .root_span
antonpirker May 23, 2025
262d7ec
Always use top level api to get scope
antonpirker May 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ filterwarnings = [

# pytest has not yet implemented the replacement for this yet
"ignore:The --looponfail command line argument.*",

# TODO-anton: just for testing locally, remove before merging
"ignore::DeprecationWarning:setuptools._distutils.version",
"ignore::DeprecationWarning:redis.connection"
]
looponfailroots = ["src", "tests"]

Expand Down
2 changes: 1 addition & 1 deletion requirements-base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ sentry-ophio>=1.1.3
sentry-protos==0.2.0
sentry-redis-tools>=0.5.0
sentry-relay>=0.9.9
sentry-sdk[http2]>=2.29.1
sentry-sdk[http2]==3.0.0a1
slack-sdk>=3.27.2
snuba-sdk>=3.0.43
simplejson>=3.17.6
Expand Down
10 changes: 8 additions & 2 deletions requirements-dev-frozen.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ cryptography==44.0.1
cssselect==1.0.3
cssutils==2.9.0
datadog==0.49.1
deprecated==1.2.18
devservices==1.1.6
distlib==0.3.8
distro==1.8.0
Expand Down Expand Up @@ -82,6 +83,7 @@ httpx==0.25.2
hyperframe==6.1.0
identify==2.6.1
idna==3.7
importlib-metadata==8.6.1
inflection==0.5.1
iniconfig==1.1.1
iso3166==2.1.1
Expand Down Expand Up @@ -114,6 +116,9 @@ openapi-core==0.18.2
openapi-pydantic==0.4.0
openapi-schema-validator==0.6.2
openapi-spec-validator==0.7.1
opentelemetry-api==1.33.1
opentelemetry-sdk==1.33.1
opentelemetry-semantic-conventions==0.54b1
orjson==3.10.10
outcome==1.2.0
packaging==24.1
Expand Down Expand Up @@ -151,7 +156,7 @@ pytest-fail-slow==0.3.0
pytest-json-report==1.5.0
pytest-metadata==3.1.1
pytest-rerunfailures==15.0
pytest-sentry==0.3.0
pytest-sentry==0.4.1
pytest-workaround-12888==1.0.0
pytest-xdist==3.0.2
python-dateutil==2.9.0.post0
Expand Down Expand Up @@ -190,7 +195,7 @@ sentry-ophio==1.1.3
sentry-protos==0.2.0
sentry-redis-tools==0.5.0
sentry-relay==0.9.9
sentry-sdk==2.29.1
sentry-sdk==3.0.0a1
sentry-usage-accountant==0.0.10
simplejson==3.17.6
six==1.17.0
Expand Down Expand Up @@ -246,6 +251,7 @@ wheel==0.38.4
wrapt==1.17.0
wsproto==1.1.0
xmlsec==1.3.14
zipp==3.21.0
zstandard==0.18.0

# The following packages are considered to be unsafe in a requirements file:
Expand Down
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pytest-django>=4.9.0
pytest-fail-slow>=0.3.0
pytest-json-report>=1.5.0
pytest-rerunfailures>=15
pytest-sentry>=0.3.0,<0.4.0
pytest-sentry>=0.4.0
pytest-workaround-12888
pytest-xdist>=3
responses>=0.23.1
Expand Down
9 changes: 8 additions & 1 deletion requirements-frozen.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ cryptography==44.0.1
cssselect==1.0.3
cssutils==2.9.0
datadog==0.49.1
deprecated==1.2.18
distro==1.8.0
django==5.2.1
django-crispy-forms==1.14.0
Expand Down Expand Up @@ -67,6 +68,7 @@ httpcore==1.0.2
httpx==0.25.2
hyperframe==6.1.0
idna==3.7
importlib-metadata==8.6.1
inflection==0.5.1
iso3166==2.1.1
isodate==0.6.1
Expand All @@ -82,6 +84,9 @@ mmh3==4.0.0
msgpack==1.1.0
oauthlib==3.1.0
openai==1.3.5
opentelemetry-api==1.33.1
opentelemetry-sdk==1.33.1
opentelemetry-semantic-conventions==0.54b1
orjson==3.10.10
packaging==24.1
parsimonious==0.10.0
Expand Down Expand Up @@ -128,7 +133,7 @@ sentry-ophio==1.1.3
sentry-protos==0.2.0
sentry-redis-tools==0.5.0
sentry-relay==0.9.9
sentry-sdk==2.29.1
sentry-sdk==3.0.0a1
sentry-usage-accountant==0.0.10
simplejson==3.17.6
six==1.17.0
Expand All @@ -154,7 +159,9 @@ urllib3==2.2.2
vine==5.1.0
vroomrs==0.1.4
wcwidth==0.2.13
wrapt==1.17.2
xmlsec==1.3.14
zipp==3.21.0
zstandard==0.18.0

# The following packages are considered to be unsafe in a requirements file:
Expand Down
4 changes: 3 additions & 1 deletion src/sentry/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,9 @@ def dispatch(self, request: Request, *args, **kwargs) -> Response:
op="base.dispatch.sleep",
name=type(self).__name__,
) as span:
span.set_data("SENTRY_API_RESPONSE_DELAY", settings.SENTRY_API_RESPONSE_DELAY)
span.set_attribute(
"SENTRY_API_RESPONSE_DELAY", settings.SENTRY_API_RESPONSE_DELAY
)
time.sleep(settings.SENTRY_API_RESPONSE_DELAY / 1000.0 - duration)

# Only enforced in dev environment
Expand Down
4 changes: 2 additions & 2 deletions src/sentry/api/bases/organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ def get_projects(

with sentry_sdk.start_span(op="fetch_organization_projects") as span:
projects = list(qs)
span.set_data("Project Count", len(projects))
span.set_attribute("Project Count", len(projects))

filter_by_membership = not bool(ids) and not bool(slugs)
filtered_projects = self._filter_projects_by_permissions(
Expand All @@ -434,7 +434,7 @@ def _filter_projects_by_permissions(
include_all_accessible: bool = False,
) -> list[Project]:
with sentry_sdk.start_span(op="apply_project_permissions") as span:
span.set_data("Project Count", len(projects))
span.set_attribute("Project Count", len(projects))
if force_global_perms:
span.set_tag("mode", "force_global_perms")
return projects
Expand Down
5 changes: 3 additions & 2 deletions src/sentry/api/endpoints/group_current_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ def get(self, request: Request, group) -> Response:
environments = get_environments(request, group.project.organization)

with sentry_sdk.start_span(op="CurrentReleaseEndpoint.get.current_release") as span:
span.set_data("Environment Count", len(environments))
span.set_data(
span.set_attribute("Environment Count", len(environments))
# TODO-anton: split dict into multiple attributes
span.set_attribute(
"Raw Parameters",
{
"group.id": group.id,
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/api/endpoints/organization_events_facets.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def data_fn(offset, limit):
)

with sentry_sdk.start_span(op="discover.endpoint", name="populate_results") as span:
span.set_data("facet_count", len(facets or []))
span.set_attribute("facet_count", len(facets or []))
resp: dict[str, _KeyTopValues]
resp = defaultdict(lambda: {"key": "", "topValues": []})
for row in facets:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ def query_tag_data(
Returns None if query was not successful which causes the endpoint to return early
"""
with sentry_sdk.start_span(op="discover.discover", name="facets.filter_transform") as span:
span.set_data("query", filter_query)
span.set_attribute("query", filter_query)
tag_query = DiscoverQueryBuilder(
dataset=Dataset.Discover,
params={},
Expand Down Expand Up @@ -391,7 +391,7 @@ def query_facet_performance(
tag_key_limit = limit if tag_key else 1

with sentry_sdk.start_span(op="discover.discover", name="facets.filter_transform") as span:
span.set_data("query", filter_query)
span.set_attribute("query", filter_query)
tag_query = DiscoverQueryBuilder(
dataset=Dataset.Discover,
params={},
Expand All @@ -417,8 +417,8 @@ def query_facet_performance(
)

with sentry_sdk.start_span(op="discover.discover", name="facets.aggregate_tags"):
span.set_data("sample_rate", sample_rate)
span.set_data("target_sample", target_sample)
span.set_attribute("sample_rate", sample_rate)
span.set_attribute("target_sample", target_sample)
aggregate_comparison = transaction_aggregate * 1.005 if transaction_aggregate else 0
aggregate_column = Function("avg", [translated_aggregate_column], "aggregate")
tag_query.where.append(excluded_tags)
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/api/endpoints/organization_events_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def get(self, request: Request, organization) -> Response:

with sentry_sdk.start_span(op="discover.endpoint", name="serialize_results") as span:
results = list(results_cursor)
span.set_data("result_length", len(results))
span.set_attribute("result_length", len(results))
context = serialize(
results,
request.user,
Expand Down
3 changes: 2 additions & 1 deletion src/sentry/api/endpoints/organization_events_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ def get(self, request: Request, organization: Organization) -> Response:
query_source = self.get_request_source(request)

with sentry_sdk.start_span(op="discover.endpoint", name="filter_params") as span:
span.set_data("organization", organization)
# TODO-anton: split dict into multiple attributes
span.set_attribute("organization", organization)

top_events = 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ def get_comparison_delta(self, request: Request) -> timedelta | None:

def get(self, request: Request, organization: Organization) -> Response:
with sentry_sdk.start_span(op="discover.endpoint", name="filter_params") as span:
span.set_data("organization", organization)
# TODO-anton: split dict into multiple attributes
span.set_attribute("organization", organization)

top_events = self.get_top_events(request)
comparison_delta = self.get_comparison_delta(request)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ def get(self, request: Request, organization: Organization) -> Response:
return Response({"detail": "missing required parameter yAxis"}, status=400)

with sentry_sdk.start_span(op="discover.metrics.endpoint", name="get_full_metrics") as span:
span.set_data("organization", organization)
# TODO-anton: split dict into multiple attributes
span.set_attribute("organization", organization)

try:
# the discover stats
Expand Down
4 changes: 2 additions & 2 deletions src/sentry/api/endpoints/organization_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ def get(self, request: Request, organization) -> Response:

organization_members = list(qs)

span.set_data("Project Count", len(projects))
span.set_data("Member Count", len(organization_members))
span.set_attribute("Project Count", len(projects))
span.set_attribute("Member Count", len(organization_members))

return Response(
serialize(
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/api/serializers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def serialize(
else:
return objects
with sentry_sdk.start_span(op="serialize", name=type(serializer).__name__) as span:
span.set_data("Object Count", len(objects))
span.set_attribute("Object Count", len(objects))

with sentry_sdk.start_span(op="serialize.get_attrs", name=type(serializer).__name__):
attrs = serializer.get_attrs(
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/api/serializers/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ def get_attrs(
) -> dict[Project, dict[str, Any]]:
def measure_span(op_tag):
span = sentry_sdk.start_span(op=f"serialize.get_attrs.project.{op_tag}")
span.set_data("Object Count", len(item_list))
span.set_attribute("Object Count", len(item_list))
return span

with measure_span("preamble"):
Expand Down
8 changes: 4 additions & 4 deletions src/sentry/auth/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,8 @@ def project_ids_with_team_membership(self) -> frozenset[int]:
.distinct()
.values_list("id", flat=True)
)
span.set_data("Project Count", len(projects))
span.set_data("Team Count", len(teams))
span.set_attribute("Project Count", len(projects))
span.set_attribute("Team Count", len(teams))

return projects

Expand Down Expand Up @@ -353,7 +353,7 @@ def has_any_project_scope(self, project: Project, scopes: Collection[str]) -> bo
]
span.set_tag("organization", self._member.organization.id)
span.set_tag("organization.slug", self._member.organization.slug)
span.set_data("membership_count", len(memberships))
span.set_attribute("membership_count", len(memberships))

for membership in memberships:
team_scopes = membership.get_scopes()
Expand Down Expand Up @@ -564,7 +564,7 @@ def has_any_project_scope(self, project: Project, scopes: Collection[str]) -> bo
span.set_tag(
"organization.slug", self.rpc_user_organization_context.organization.slug
)
span.set_data("membership_count", len(orgmember_teams))
span.set_attribute("membership_count", len(orgmember_teams))

for member_team in orgmember_teams:
if not member_team.role:
Expand Down
6 changes: 3 additions & 3 deletions src/sentry/cache/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ def _mark_transaction(self, op):
if not self.is_default_cache:
return

scope = sentry_sdk.Scope.get_current_scope()
scope = sentry_sdk.get_current_scope()
# Do not set this tag if we're in the global scope (which roughly
# equates to having a transaction).
if scope.transaction:
# equates to having a root span).
if scope.root_span:
sentry_sdk.set_tag(f"{op}_default_cache", "true")
sentry_sdk.set_tag("used_default_cache", "true")
2 changes: 1 addition & 1 deletion src/sentry/consumers/validate_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ def submit(self, message: Message[KafkaPayload]) -> None:
now = time.time()
if self.__last_record_time is None or self.__last_record_time + 1.0 < now:
with sentry_sdk.isolation_scope() as scope:
scope.add_attachment(bytes=message.payload.value, filename="message.txt")
scope.set_tag("topic", self.__topic)
sentry_sdk.add_attachment(bytes=message.payload.value, filename="message.txt")

if self.__codec is None:
logger.warning("No validator configured for topic")
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/data_export/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ def merge_export_blobs(data_export_id, **kwargs):


def _set_data_on_scope(data_export):
scope = sentry_sdk.Scope.get_isolation_scope()
scope = sentry_sdk.get_isolation_scope()
if data_export.user_id:
user = dict(id=data_export.user_id)
scope.set_user(user)
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/debug_files/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def find_missing_chunks(organization_id: int, chunks: set[str]):
"""Returns a list of chunks which are missing for an org."""
with sentry_sdk.start_span(op="find_missing_chunks") as span:
span.set_tag("organization_id", organization_id)
span.set_data("chunks_size", len(chunks))
span.set_attribute("chunks_size", len(chunks))

if not chunks:
return []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,8 @@ def on_release_boosted() -> None:
"dynamic_sampling.observe_release_status",
"(release, environment) pair observed and boosted",
)
span.set_data("release", release.id)
span.set_data("environment", environment)
span.set_attribute("release", release.id)
span.set_attribute("environment", environment)

schedule_invalidate_project_config(
project_id=project.id,
Expand Down
8 changes: 4 additions & 4 deletions src/sentry/features/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,17 +114,17 @@ def has_for_batch(
name=f"{type(handler).__name__} ({name})",
) as span:
batch_size = len(remaining)
span.set_data("Batch Size", batch_size)
span.set_data("Feature Name", name)
span.set_data("Handler Type", type(handler).__name__)
span.set_attribute("Batch Size", batch_size)
span.set_attribute("Feature Name", name)
span.set_attribute("Handler Type", type(handler).__name__)

batch = FeatureCheckBatch(self, name, organization, remaining, actor)
handler_result = handler.has_for_batch(batch)
for obj, flag in handler_result.items():
if flag is not None:
remaining.remove(obj)
result[obj] = flag
span.set_data("Flags Found", batch_size - len(remaining))
span.set_attribute("Flags Found", batch_size - len(remaining))

default_flag = settings.SENTRY_FEATURES.get(name, False)
for obj in remaining:
Expand Down
4 changes: 2 additions & 2 deletions src/sentry/hybridcloud/models/outbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,8 @@ def process_coalesced(
def _set_span_data_for_coalesced_message(self, span: Span, message: OutboxBase) -> None:
tag_for_outbox = OutboxScope.get_tag_name(message.shard_scope)
span.set_tag(tag_for_outbox, message.shard_identifier)
span.set_data("outbox_id", message.id)
span.set_data("outbox_shard_id", message.shard_identifier)
span.set_attribute("outbox_id", message.id)
span.set_attribute("outbox_shard_id", message.shard_identifier)
span.set_tag("outbox_category", OutboxCategory(message.category).name)
span.set_tag("outbox_scope", OutboxScope(message.shard_scope).name)

Expand Down
2 changes: 1 addition & 1 deletion src/sentry/hybridcloud/rpc/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ def _remote_exception(self, message: str) -> RpcRemoteException:

def _raise_from_response_status_error(self, response: requests.Response) -> NoReturn:
rpc_method = f"{self.service_name}.{self.method_name}"
scope = sentry_sdk.Scope.get_isolation_scope()
scope = sentry_sdk.get_isolation_scope()
scope.set_tag("rpc_method", rpc_method)
scope.set_tag("rpc_status_code", response.status_code)

Expand Down
Loading
Loading