|
10 | 10 | from sentry_sdk.tracing import TransactionSource |
11 | 11 | from sentry_sdk.tracing_utils import has_span_streaming_enabled |
12 | 12 | from sentry_sdk.utils import ( |
| 13 | + AnnotatedValue, |
13 | 14 | HAS_REAL_CONTEXTVARS, |
14 | 15 | CONTEXTVARS_ERROR_MESSAGE, |
15 | 16 | ensure_integration_enabled, |
16 | 17 | event_from_exception, |
17 | 18 | capture_internal_exceptions, |
| 19 | + serialize_request_body_data, |
18 | 20 | transaction_from_function, |
19 | 21 | ) |
20 | 22 | from sentry_sdk.integrations import _check_minimum_version, Integration, DidNotEnable |
21 | 23 | from sentry_sdk.integrations._wsgi_common import ( |
22 | 24 | RequestExtractor, |
23 | 25 | _filter_headers, |
24 | 26 | _is_json_content_type, |
| 27 | + request_body_within_bounds, |
25 | 28 | ) |
26 | 29 | from sentry_sdk.integrations.logging import ignore_logger |
27 | 30 |
|
@@ -169,7 +172,7 @@ def _handle_request_impl(self: "RequestHandler") -> "Generator[None, None, None] |
169 | 172 |
|
170 | 173 | method = getattr(self, self.request.method.lower(), None) |
171 | 174 | if method is not None: |
172 | | - span_name = transaction_from_function(method) or "" |
| 175 | + span_name = transaction_from_function(method) |
173 | 176 | if span_name: |
174 | 177 | span.name = span_name |
175 | 178 | span.set_attribute( |
@@ -213,9 +216,37 @@ def _get_request_attributes(request: "Any") -> "Dict[str, Any]": |
213 | 216 | attributes["client.address"] = request.remote_ip |
214 | 217 | attributes["user.ip_address"] = request.remote_ip |
215 | 218 |
|
| 219 | + with capture_internal_exceptions(): |
| 220 | + body_data = _extract_request_body_data(request) |
| 221 | + if body_data is not None: |
| 222 | + attributes["http.request.body.data"] = serialize_request_body_data( |
| 223 | + body_data |
| 224 | + ) |
| 225 | + |
216 | 226 | return attributes |
217 | 227 |
|
218 | 228 |
|
| 229 | +def _extract_request_body_data(request: "Any") -> "Any": |
| 230 | + client = sentry_sdk.get_client() |
| 231 | + extractor = TornadoRequestExtractor(request) |
| 232 | + content_length = extractor.content_length() |
| 233 | + |
| 234 | + if not content_length: |
| 235 | + return None |
| 236 | + |
| 237 | + if not request_body_within_bounds(client, content_length): |
| 238 | + return AnnotatedValue.removed_because_over_size_limit() |
| 239 | + |
| 240 | + parsed_body = extractor.parsed_body() |
| 241 | + if parsed_body is not None: |
| 242 | + return parsed_body |
| 243 | + |
| 244 | + if extractor.raw_data(): |
| 245 | + return AnnotatedValue.removed_because_raw_data() |
| 246 | + |
| 247 | + return None |
| 248 | + |
| 249 | + |
219 | 250 | @ensure_integration_enabled(TornadoIntegration) |
220 | 251 | def _capture_exception(ty: type, value: BaseException, tb: "Any") -> None: |
221 | 252 | if isinstance(value, HTTPError): |
|
0 commit comments