Skip to content

Commit ec6fd01

Browse files
committed
req body
1 parent 9b53439 commit ec6fd01

3 files changed

Lines changed: 65 additions & 8 deletions

File tree

sentry_sdk/consts.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,12 @@ class SPANDATA:
404404
Example: template.cache.some_item.867da7e2af8e6b2f3aa7213a4080edb3
405405
"""
406406

407+
CLIENT_ADDRESS = "client.address"
408+
"""
409+
Client address of the network connection - IP address or Unix domain socket name.
410+
Example: "10.1.2.80"
411+
"""
412+
407413
CODE_FILEPATH = "code.filepath"
408414
"""
409415
.. deprecated::
@@ -819,12 +825,25 @@ class SPANDATA:
819825
Example: GET
820826
"""
821827

828+
HTTP_REQUEST_HEADER = "http.request.header"
829+
"""
830+
Prefix for HTTP request header attributes. The header name (lowercased) is
831+
appended to form the full attribute key.
832+
Example: "http.request.header.content-type"
833+
"""
834+
822835
HTTP_REQUEST_METHOD = "http.request.method"
823836
"""
824837
The HTTP method used.
825838
Example: GET
826839
"""
827840

841+
HTTP_REQUEST_BODY_DATA = "http.request.body.data"
842+
"""
843+
The HTTP request body data as string.
844+
Example: "[{\"role\": \"user\", \"message\": \"hello\"}]"
845+
"""
846+
828847
HTTP_QUERY = "http.query"
829848
"""
830849
The Query string present in the URL.
@@ -863,6 +882,12 @@ class SPANDATA:
863882
The messaging system's name, e.g. `kafka`, `aws_sqs`
864883
"""
865884

885+
NETWORK_PROTOCOL_NAME = "network.protocol.name"
886+
"""
887+
The application layer protocol name used for the network connection.
888+
Example: "http", "https"
889+
"""
890+
866891
NETWORK_PEER_ADDRESS = "network.peer.address"
867892
"""
868893
Peer address of the network connection - IP address or Unix domain socket name.
@@ -942,6 +967,12 @@ class SPANDATA:
942967
Example: "MainThread"
943968
"""
944969

970+
USER_IP_ADDRESS = "user.ip_address"
971+
"""
972+
The IP address of the user that triggered the request.
973+
Example: "10.1.2.80"
974+
"""
975+
945976
URL_FULL = "url.full"
946977
"""
947978
The URL of the resource that was fetched.

sentry_sdk/integrations/tornado.py

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@
1010
RequestExtractor,
1111
_filter_headers,
1212
_is_json_content_type,
13+
request_body_within_bounds,
1314
)
1415
from sentry_sdk.integrations.logging import ignore_logger
1516
from sentry_sdk.scope import should_send_default_pii
16-
from sentry_sdk.traces import SegmentSource, StreamedSpan
17+
from sentry_sdk.traces import NoOpStreamedSpan, SegmentSource, StreamedSpan
1718
from sentry_sdk.tracing import TransactionSource
1819
from sentry_sdk.tracing_utils import has_span_streaming_enabled
1920
from sentry_sdk.utils import (
2021
CONTEXTVARS_ERROR_MESSAGE,
2122
HAS_REAL_CONTEXTVARS,
23+
AnnotatedValue,
2224
capture_internal_exceptions,
2325
ensure_integration_enabled,
2426
event_from_exception,
@@ -155,14 +157,16 @@ def _handle_request_impl(self: "RequestHandler") -> "Generator[None, None, None]
155157
)
156158

157159
with span_ctx as span:
158-
if isinstance(span, StreamedSpan):
160+
if isinstance(span, StreamedSpan) and not isinstance(
161+
span, NoOpStreamedSpan
162+
):
159163
with capture_internal_exceptions():
160164
for attr, value in _get_request_attributes(self.request).items():
161165
span.set_attribute(attr, value)
162166

163167
method = getattr(self, self.request.method.lower(), None)
164168
if method is not None:
165-
span_name = transaction_from_function(method) or ""
169+
span_name = transaction_from_function(method)
166170
if span_name:
167171
span.name = span_name
168172
span.set_attribute(
@@ -173,7 +177,9 @@ def _handle_request_impl(self: "RequestHandler") -> "Generator[None, None, None]
173177
try:
174178
yield
175179
finally:
176-
if isinstance(span, StreamedSpan):
180+
if isinstance(span, StreamedSpan) and not isinstance(
181+
span, NoOpStreamedSpan
182+
):
177183
with capture_internal_exceptions():
178184
status_int = self.get_status()
179185
span.set_attribute(SPANDATA.HTTP_STATUS_CODE, status_int)
@@ -188,7 +194,7 @@ def _get_request_attributes(request: "Any") -> "Dict[str, Any]":
188194

189195
headers = _filter_headers(dict(request.headers), use_annotated_value=False)
190196
for header, value in headers.items():
191-
attributes[f"http.request.header.{header.lower()}"] = value
197+
attributes[f"{SPANDATA.HTTP_REQUEST_HEADER}.{header.lower()}"] = value
192198

193199
if request.query:
194200
attributes[SPANDATA.HTTP_QUERY] = request.query
@@ -200,15 +206,34 @@ def _get_request_attributes(request: "Any") -> "Dict[str, Any]":
200206
)
201207

202208
if request.protocol:
203-
attributes["network.protocol.name"] = request.protocol
209+
attributes[SPANDATA.NETWORK_PROTOCOL_NAME] = request.protocol
204210

205211
if should_send_default_pii() and request.remote_ip:
206-
attributes["client.address"] = request.remote_ip
207-
attributes["user.ip_address"] = request.remote_ip
212+
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_ip
213+
attributes[SPANDATA.USER_IP_ADDRESS] = request.remote_ip
214+
215+
with capture_internal_exceptions():
216+
raw_data = _get_tornado_request_data(request)
217+
body_data = raw_data.value if isinstance(raw_data, AnnotatedValue) else raw_data
218+
if body_data is not None:
219+
attributes[SPANDATA.HTTP_REQUEST_BODY_DATA] = body_data
208220

209221
return attributes
210222

211223

224+
def _get_tornado_request_data(
225+
request: "Any",
226+
) -> "Union[Optional[str], AnnotatedValue]":
227+
body = request.body
228+
if not body:
229+
return None
230+
231+
if not request_body_within_bounds(sentry_sdk.get_client(), len(body)):
232+
return AnnotatedValue.substituted_because_over_size_limit()
233+
234+
return body.decode("utf-8", "replace")
235+
236+
212237
@ensure_integration_enabled(TornadoIntegration)
213238
def _capture_exception(ty: type, value: BaseException, tb: "Any") -> None:
214239
if isinstance(value, HTTPError):

tests/integrations/tornado/test_tornado.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ def test_transactions(
176176
assert server_segment["name"] == expected_handler
177177
assert server_segment["attributes"]["sentry.span.source"] == "component"
178178
assert server_segment["attributes"]["http.request.method"] == "POST"
179+
assert server_segment["attributes"]["http.request.body.data"] == "heyoo"
179180
assert server_segment["attributes"]["http.response.status_code"] == code
180181
assert server_segment["status"] == ("ok" if code == 200 else "error")
181182
assert client_segment["trace_id"] == server_segment["trace_id"]

0 commit comments

Comments
 (0)