Skip to content

Commit

Permalink
Merge branch 'potel-base' into potel-base-run-all-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sentrivana authored Nov 15, 2024
2 parents cc6bb7c + 571c5cd commit 74bd4c8
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 17 deletions.
16 changes: 15 additions & 1 deletion MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,27 @@ 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 on the scope, if available, are accessible as follows:
- The `sampling_context` argument of `traces_sampler` doesn't contain the `wsgi_environ` object anymore for WSGI frameworks. Instead, the individual properties of the environment are accessible, if available, as follows:

| Env property | Sampling context key(s) |
| ----------------- | ------------------------------------------------- |
| `PATH_INFO` | `url.path` |
| `QUERY_STRING` | `url.query` |
| `REQUEST_METHOD` | `http.request.method` |
| `SERVER_NAME` | `server.address` |
| `SERVER_PORT` | `server.port` |
| `SERVER_PROTOCOL` | `server.protocol.name`, `server.protocol.version` |
| `wsgi.url_scheme` | `url.scheme` |
| full URL | `url.full` |

- The `sampling_context` argument of `traces_sampler` doesn't contain the `asgi_scope` object anymore for ASGI frameworks. Instead, the individual properties of the scope, if available, are accessible as follows:

| Scope property | Sampling context key(s) |
| -------------- | ------------------------------- |
| `type` | `network.protocol.name` |
| `scheme` | `url.scheme` |
| `path` | `url.path` |
| `query` | `url.query` |
| `http_version` | `network.protocol.version` |
| `method` | `http.request.method` |
| `server` | `server.address`, `server.port` |
Expand Down
1 change: 1 addition & 0 deletions sentry_sdk/integrations/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ def _prepopulate_attributes(scope):
full_url = _get_url(scope)
query = _get_query(scope)
if query:
attributes["url.query"] = query
full_url = f"{full_url}?{query}"

attributes["url.full"] = full_url
Expand Down
39 changes: 38 additions & 1 deletion sentry_sdk/integrations/wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ def __call__(self, status, response_headers, exc_info=None): # type: ignore

DEFAULT_TRANSACTION_NAME = "generic WSGI request"

ENVIRON_TO_ATTRIBUTE = {
"PATH_INFO": "url.path",
"QUERY_STRING": "url.query",
"REQUEST_METHOD": "http.request.method",
"SERVER_NAME": "server.address",
"SERVER_PORT": "server.port",
"wsgi.url_scheme": "url.scheme",
}


def wsgi_decoding_dance(s, charset="utf-8", errors="replace"):
# type: (str, str, str) -> str
Expand Down Expand Up @@ -120,7 +129,9 @@ def __call__(self, environ, start_response):
name=DEFAULT_TRANSACTION_NAME,
source=TRANSACTION_SOURCE_ROUTE,
origin=self.span_origin,
custom_sampling_context={"wsgi_environ": environ},
attributes=_prepopulate_attributes(
environ, self.use_x_forwarded_for
),
)
if should_trace
else nullcontext()
Expand Down Expand Up @@ -309,3 +320,29 @@ def event_processor(event, hint):
return event

return event_processor


def _prepopulate_attributes(wsgi_environ, use_x_forwarded_for=False):
"""Extract span attributes from the WSGI environment."""
attributes = {}

for property, attr in ENVIRON_TO_ATTRIBUTE.items():
if wsgi_environ.get(property) is not None:
attributes[attr] = wsgi_environ[property]

if wsgi_environ.get("SERVER_PROTOCOL") is not None:
try:
proto, version = wsgi_environ["SERVER_PROTOCOL"].split("/")
attributes["network.protocol.name"] = proto
attributes["network.protocol.version"] = version
except Exception:
attributes["network.protocol.name"] = wsgi_environ["SERVER_PROTOCOL"]

try:
url = get_request_url(wsgi_environ, use_x_forwarded_for)
query = wsgi_environ.get("QUERY_STRING")
attributes["url.full"] = f"{url}?{query}"
except Exception:
pass

return attributes
1 change: 1 addition & 0 deletions tests/integrations/asgi/test_asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,7 @@ async def test_asgi_scope_in_traces_sampler(sentry_init, asgi3_app):
def dummy_traces_sampler(sampling_context):
assert sampling_context["url.path"] == "/test"
assert sampling_context["url.scheme"] == "http"
assert sampling_context["url.query"] == "hello=there"
assert sampling_context["url.full"] == "/test?hello=there"
assert sampling_context["http.request.method"] == "GET"
assert sampling_context["network.protocol.version"] == "1.1"
Expand Down
26 changes: 11 additions & 15 deletions tests/integrations/wsgi/test_wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,25 +334,21 @@ def app(environ, start_response):
start_response("200 OK", [])
return ["Go get the ball! Good dog!"]

traces_sampler = mock.Mock(return_value=True)
def traces_sampler(sampling_context):
assert sampling_context["http.request.method"] == "GET"
assert sampling_context["url.path"] == "/dogs/are/great/"
assert sampling_context["url.query"] == "cats=too"
assert sampling_context["url.scheme"] == "http"
assert (
sampling_context["url.full"] == "http://localhost/dogs/are/great/?cats=too"
)
return True

sentry_init(send_default_pii=True, traces_sampler=traces_sampler)
app = SentryWsgiMiddleware(app)
client = Client(app)

client.get("/dogs/are/great/")

traces_sampler.assert_any_call(
DictionaryContaining(
{
"wsgi_environ": DictionaryContaining(
{
"PATH_INFO": "/dogs/are/great/",
"REQUEST_METHOD": "GET",
},
),
}
)
)
client.get("/dogs/are/great/?cats=too")


def test_session_mode_defaults_to_request_mode_in_wsgi_handler(
Expand Down

0 comments on commit 74bd4c8

Please sign in to comment.