|
18 | 18 | _get_request_data,
|
19 | 19 | _get_url,
|
20 | 20 | )
|
| 21 | +from sentry_sdk.integrations._wsgi_common import ( |
| 22 | + DEFAULT_HTTP_METHODS_TO_CAPTURE, |
| 23 | + nullcontext, |
| 24 | +) |
21 | 25 | from sentry_sdk.sessions import track_session
|
22 | 26 | from sentry_sdk.tracing import (
|
23 | 27 | SOURCE_FOR_STYLE,
|
@@ -89,17 +93,19 @@ class SentryAsgiMiddleware:
|
89 | 93 | "transaction_style",
|
90 | 94 | "mechanism_type",
|
91 | 95 | "span_origin",
|
| 96 | + "http_methods_to_capture", |
92 | 97 | )
|
93 | 98 |
|
94 | 99 | def __init__(
|
95 | 100 | self,
|
96 |
| - app, |
97 |
| - unsafe_context_data=False, |
98 |
| - transaction_style="endpoint", |
99 |
| - mechanism_type="asgi", |
100 |
| - span_origin="manual", |
| 101 | + app, # type: Any |
| 102 | + unsafe_context_data=False, # type: bool |
| 103 | + transaction_style="endpoint", # type: str |
| 104 | + mechanism_type="asgi", # type: str |
| 105 | + span_origin="manual", # type: str |
| 106 | + http_methods_to_capture=DEFAULT_HTTP_METHODS_TO_CAPTURE, # type: Tuple[str, ...] |
101 | 107 | ):
|
102 |
| - # type: (Any, bool, str, str, str) -> None |
| 108 | + # type: (...) -> None |
103 | 109 | """
|
104 | 110 | Instrument an ASGI application with Sentry. Provides HTTP/websocket
|
105 | 111 | data to sent events and basic handling for exceptions bubbling up
|
@@ -134,6 +140,7 @@ def __init__(
|
134 | 140 | self.mechanism_type = mechanism_type
|
135 | 141 | self.span_origin = span_origin
|
136 | 142 | self.app = app
|
| 143 | + self.http_methods_to_capture = http_methods_to_capture |
137 | 144 |
|
138 | 145 | if _looks_like_asgi3(app):
|
139 | 146 | self.__call__ = self._run_asgi3 # type: Callable[..., Any]
|
@@ -185,52 +192,59 @@ async def _run_app(self, scope, receive, send, asgi_version):
|
185 | 192 | scope,
|
186 | 193 | )
|
187 | 194 |
|
188 |
| - if ty in ("http", "websocket"): |
189 |
| - transaction = continue_trace( |
190 |
| - _get_headers(scope), |
191 |
| - op="{}.server".format(ty), |
192 |
| - name=transaction_name, |
193 |
| - source=transaction_source, |
194 |
| - origin=self.span_origin, |
195 |
| - ) |
196 |
| - logger.debug( |
197 |
| - "[ASGI] Created transaction (continuing trace): %s", |
198 |
| - transaction, |
199 |
| - ) |
200 |
| - else: |
201 |
| - transaction = Transaction( |
202 |
| - op=OP.HTTP_SERVER, |
203 |
| - name=transaction_name, |
204 |
| - source=transaction_source, |
205 |
| - origin=self.span_origin, |
206 |
| - ) |
| 195 | + method = scope.get("method", "").upper() |
| 196 | + transaction = None |
| 197 | + if method in self.http_methods_to_capture: |
| 198 | + if ty in ("http", "websocket"): |
| 199 | + transaction = continue_trace( |
| 200 | + _get_headers(scope), |
| 201 | + op="{}.server".format(ty), |
| 202 | + name=transaction_name, |
| 203 | + source=transaction_source, |
| 204 | + origin=self.span_origin, |
| 205 | + ) |
| 206 | + logger.debug( |
| 207 | + "[ASGI] Created transaction (continuing trace): %s", |
| 208 | + transaction, |
| 209 | + ) |
| 210 | + else: |
| 211 | + transaction = Transaction( |
| 212 | + op=OP.HTTP_SERVER, |
| 213 | + name=transaction_name, |
| 214 | + source=transaction_source, |
| 215 | + origin=self.span_origin, |
| 216 | + ) |
| 217 | + logger.debug( |
| 218 | + "[ASGI] Created transaction (new): %s", transaction |
| 219 | + ) |
| 220 | + |
| 221 | + transaction.set_tag("asgi.type", ty) |
207 | 222 | logger.debug(
|
208 |
| - "[ASGI] Created transaction (new): %s", transaction |
| 223 | + "[ASGI] Set transaction name and source on transaction: '%s' / '%s'", |
| 224 | + transaction.name, |
| 225 | + transaction.source, |
209 | 226 | )
|
210 | 227 |
|
211 |
| - transaction.set_tag("asgi.type", ty) |
212 |
| - logger.debug( |
213 |
| - "[ASGI] Set transaction name and source on transaction: '%s' / '%s'", |
214 |
| - transaction.name, |
215 |
| - transaction.source, |
216 |
| - ) |
217 |
| - |
218 |
| - with sentry_sdk.start_transaction( |
219 |
| - transaction, |
220 |
| - custom_sampling_context={"asgi_scope": scope}, |
| 228 | + with ( |
| 229 | + sentry_sdk.start_transaction( |
| 230 | + transaction, |
| 231 | + custom_sampling_context={"asgi_scope": scope}, |
| 232 | + ) |
| 233 | + if transaction is not None |
| 234 | + else nullcontext() |
221 | 235 | ):
|
222 | 236 | logger.debug("[ASGI] Started transaction: %s", transaction)
|
223 | 237 | try:
|
224 | 238 |
|
225 | 239 | async def _sentry_wrapped_send(event):
|
226 | 240 | # type: (Dict[str, Any]) -> Any
|
227 |
| - is_http_response = ( |
228 |
| - event.get("type") == "http.response.start" |
229 |
| - and transaction is not None |
230 |
| - and "status" in event |
231 |
| - ) |
232 |
| - if is_http_response: |
233 |
| - transaction.set_http_status(event["status"]) |
| 241 | + if transaction is not None: |
| 242 | + is_http_response = ( |
| 243 | + event.get("type") == "http.response.start" |
| 244 | + and "status" in event |
| 245 | + ) |
| 246 | + if is_http_response: |
| 247 | + transaction.set_http_status(event["status"]) |
234 | 248 |
|
235 | 249 | return await send(event)
|
236 | 250 |
|
|
0 commit comments