8000 Unpack custom_sampling_context into attributes in ASGI by sentrivana · Pull Request #3764 · getsentry/sentry-python · GitHub
[go: up one dir, main page]

Skip to content

Unpack custom_sampling_context into attributes in ASGI #3764

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

Merged
merged 26 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
18103bc
Remove custom_sampling_context
sentrivana Nov 7, 2024
68402ff
confusing wording
sentrivana Nov 7, 2024
70d02cc
Merge branch 'potel-base' into ivana/sampling-context
sentrivana Nov 7, 2024
fa5d0ba
keep old format (why not)
sentrivana Nov 7, 2024
5df9ccc
.
sentrivana Nov 7, 2024
472ab5c
add attrs
sentrivana Nov 7, 2024
f893f12
.
sentrivana Nov 7, 2024
fff9f16
.
sentrivana Nov 7, 2024
ce815e8
more removals
sentrivana Nov 7, 2024
d307fe1
Merge branch 'potel-base' into ivana/sampling-context
sentrivana Nov 12, 2024
747ecc6
more readme
sentrivana Nov 12, 2024
7ae6745
more info
sentrivana Nov 12, 2024
09d247e
comment
sentrivana Nov 12, 2024
1aeeb68
small change
sentrivana Nov 12, 2024
786bb9e
.
sentrivana Nov 12, 2024
80427c6
dont do everything in this pr
sentrivana Nov 12, 2024
2acef08
get rid of none attributes
sentrivana Nov 12, 2024
eb2df70
dropped result too
sentrivana Nov 12, 2024
2cee373
Replace custom_sampling_context with attributes in ASGI
sentrivana Nov 12, 2024
f6fb9a9
add source too
sentrivana Nov 12, 2024
86c6373
Merge branch 'potel-base' into ivana/custom-sampling-context-integrat…
sentrivana Nov 12, 2024
4002f38
fix starlette tests
sentrivana Nov 12, 2024
dbc8ba2
fix fastapi
sentrivana Nov 12, 2024
52f918a
remove middleware spans toggle
sentrivana Nov 13, 2024
6b063cf
Merge branch 'potel-base' into ivana/custom-sampling-context-integrat…
sentrivana Nov 13, 2024
530fa4f
Merge branch 'potel-base' into ivana/custom-sampling-context-integrat…
sentrivana Nov 14, 2024
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
1 change: 1 addition & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh
- clickhouse-driver integration: The query is now available under the `db.query.text` span attribute (only if `send_default_pii` is `True`).
- `sentry_sdk.init` now returns `None` instead of a context manager.
- The `sampling_context` argument of `traces_sampler` now additionally contains all span attributes known at span start.
- The `sampling_context` argument of `traces_sampler` doesn't contain the `asgi_scope` object anymore for ASGI frameworks. Instead, the individual properties, if available, are accessible as `asgi_scope.endpoint`, `asgi_scope.path`, `asgi_scope.root_path`, `asgi_scope.route`, `asgi_scope.scheme`, `asgi_scope.server` and `asgi_scope.type`.

### Removed

Expand Down
15 changes: 14 additions & 1 deletion sentry_sdk/integrations/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ async def _run_app(self, scope, receive, send, asgi_version):
name=transaction_name,
source=transaction_source,
origin=self.span_origin,
custom_sampling_context={"asgi_scope": scope},
attributes=_prepopulate_attributes(scope),
)
if should_trace
else nullcontext()
Expand Down Expand Up @@ -324,3 +324,16 @@ def _get_transaction_name_and_source(self, transaction_style, asgi_scope):
return name, source

return name, source


def _prepopulate_attributes(scope):
# type: (Any) -> dict[str, Any]
"""Unpack asgi_scope into serializable attributes."""
scope = scope or {}

attributes = {}
for attr in ("endpoint", "path", "root_path", "route", "scheme", "server", "type"):
if scope.get(attr):
attributes[f"asgi_scope.{attr}"] = scope[attr]

return attributes
1 change: 1 addition & 0 deletions sentry_sdk/integrations/opentelemetry/sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ def should_sample(
"transaction_context": {
"name": name,
"op": attributes.get(SentrySpanAttribute.OP),
"source": attributes.get(SentrySpanAttribute.SOURCE),
},
"parent_sampled": get_parent_sampled(parent_span_context, trace_id),
}
Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,7 @@ def __init__(
# Prepopulate some attrs so that they're accessible in traces_sampler
attributes = attributes or {}
attributes[SentrySpanAttribute.OP] = op
attributes[SentrySpanAttribute.SOURCE] = source
if sampled is not None:
attributes[SentrySpanAttribute.CUSTOM_SAMPLED] = sampled

Expand All @@ -1260,7 +1261,6 @@ def __init__(
self.origin = origin or DEFAULT_SPAN_ORIGIN
self.description = description
self.name = span_name
self.source = source

if status is not None:
self.set_status(status)
Expand Down
17 changes: 17 additions & 0 deletions tests/integrations/asgi/test_asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,3 +721,20 @@ async def test_custom_transaction_name(
assert transaction_event["type"] == "transaction"
assert transaction_event["transaction"] == "foobar"
assert transaction_event["transaction_info"] == {"source": "custom"}


@pytest.mark.asyncio
async def test_asgi_scope_in_traces_sampler(sentry_init, asgi3_app):
def dummy_traces_sampler(sampling_context):
assert sampling_context["asgi_scope.path"] == "/test"
assert sampling_context["asgi_scope.scheme"] == "http"

sentry_init(
traces_sampler=dummy_traces_sampler,
traces_sample_rate=1.0,
)

app = SentryAsgiMiddleware(asgi3_app)

async with TestClient(app) as client:
await client.get("/test")
Loading
0