Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 28 additions & 7 deletions sentry_sdk/integrations/tornado.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,16 @@ def _handle_request_impl(self: "RequestHandler") -> "Generator[None, None, None]
sentry_sdk.traces.continue_trace(dict(headers))
scope.set_custom_sampling_context({"tornado_request": self.request})

if should_send_default_pii() and self.request.remote_ip:
scope.set_attribute(SPANDATA.USER_IP_ADDRESS, self.request.remote_ip)
if self.request.remote_ip:
if has_data_collection_enabled(client.options):
if client.options["data_collection"]["user_info"]:
scope.set_attribute(
SPANDATA.USER_IP_ADDRESS, self.request.remote_ip
)
elif should_send_default_pii():
scope.set_attribute(
SPANDATA.USER_IP_ADDRESS, self.request.remote_ip
)

span_ctx = sentry_sdk.traces.start_span(
name=_DEFAULT_ROOT_SPAN_NAME,
Expand Down Expand Up @@ -218,19 +226,23 @@ def _get_request_attributes(request: "Any") -> "Dict[str, Any]":
f"{parsed_url.url}?{filtered_query}" if filtered_query else parsed_url.url
)

if request.remote_ip:
if client_options["data_collection"]["user_info"]:
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_ip

elif should_send_default_pii():
attributes[SPANDATA.URL_FULL] = request.full_url()
attributes["url.path"] = request.path

if request.query:
attributes[SPANDATA.URL_QUERY] = request.query

if request.remote_ip:
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_ip

if request.protocol:
attributes[SPANDATA.NETWORK_PROTOCOL_NAME] = request.protocol

if should_send_default_pii() and request.remote_ip:
attributes[SPANDATA.CLIENT_ADDRESS] = request.remote_ip

with capture_internal_exceptions():
raw_data = _get_tornado_request_data(request)
body_data = raw_data.value if isinstance(raw_data, AnnotatedValue) else raw_data
Expand Down Expand Up @@ -282,6 +294,7 @@ def tornado_processor(event: "Event", hint: "dict[str, Any]") -> "Event":
event["transaction"] = transaction_from_function(method) or ""
event["transaction_info"] = {"source": TransactionSource.COMPONENT}

client_options = sentry_sdk.get_client().options
with capture_internal_exceptions():
extractor = TornadoRequestExtractor(request)
extractor.extract_into_event(event)
Expand All @@ -294,7 +307,6 @@ def tornado_processor(event: "Event", hint: "dict[str, Any]") -> "Event":
request.path,
)

client_options = sentry_sdk.get_client().options
if has_data_collection_enabled(client_options):
if request.query:
filtered_query = _apply_data_collection_filtering_to_query_string(
Expand All @@ -310,7 +322,16 @@ def tornado_processor(event: "Event", hint: "dict[str, Any]") -> "Event":
request_info["env"] = {"REMOTE_ADDR": request.remote_ip}
request_info["headers"] = _filter_headers(dict(request.headers))

if should_send_default_pii():
if has_data_collection_enabled(client_options):
if client_options["data_collection"]["user_info"]:
Comment thread
cursor[bot] marked this conversation as resolved.
try:
current_user = handler.current_user
except Exception:
current_user = None

if current_user:
event.setdefault("user", {}).setdefault("is_authenticated", True)
elif should_send_default_pii():
try:
current_user = handler.current_user
except Exception:
Expand Down
65 changes: 61 additions & 4 deletions tests/integrations/tornado/test_tornado.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from sentry_sdk import capture_message, start_transaction
from sentry_sdk._types import SENSITIVE_DATA_SUBSTITUTE
from sentry_sdk.integrations.tornado import TornadoIntegration
from tests.integrations.utils import DATA_COLLECTION_USER_INFO_CASES


@pytest.fixture
Expand Down Expand Up @@ -701,6 +702,32 @@ def get(self):
assert "user" not in event


@pytest.mark.parametrize("init_kwargs, expect_user", DATA_COLLECTION_USER_INFO_CASES)
def test_user_auth_data_collection(
tornado_testcase, sentry_init, capture_events, init_kwargs, expect_user
):
sentry_init(integrations=[TornadoIntegration()], **init_kwargs)
events = capture_events()

class UserHandler(RequestHandler):
def get(self):
1 / 0

def get_current_user(self):
return 42

client = tornado_testcase(Application([(r"/auth", UserHandler)]))

response = client.fetch("/auth")
assert response.code == 500

(event,) = events
if expect_user:
assert event["user"] == {"is_authenticated": True}
else:
assert "is_authenticated" not in event.get("user", {})


def test_formdata(tornado_testcase, sentry_init, capture_events):
sentry_init(integrations=[TornadoIntegration()], send_default_pii=True)
events = capture_events()
Expand Down Expand Up @@ -927,15 +954,15 @@ def test_span_origin(
assert event["contexts"]["trace"]["origin"] == "auto.http.tornado"


@pytest.mark.parametrize("send_default_pii", [True, False])
@pytest.mark.parametrize("init_kwargs, expect_ip", DATA_COLLECTION_USER_INFO_CASES)
def test_user_ip_address_on_all_spans(
tornado_testcase, sentry_init, capture_items, send_default_pii
tornado_testcase, sentry_init, capture_items, init_kwargs, expect_ip
):
sentry_init(
integrations=[TornadoIntegration()],
traces_sample_rate=1.0,
send_default_pii=send_default_pii,
trace_lifecycle="stream",
**init_kwargs,
)

items = capture_items("span")
Expand All @@ -947,9 +974,39 @@ def test_user_ip_address_on_all_spans(

child_span, server_span = [item.payload for item in items]

if send_default_pii:
if expect_ip:
assert server_span["attributes"]["user.ip_address"] == "127.0.0.1"
assert child_span["attributes"]["user.ip_address"] == "127.0.0.1"
else:
assert "user.ip_address" not in server_span["attributes"]
assert "user.ip_address" not in child_span["attributes"]


@pytest.mark.parametrize("init_kwargs, expect_ip", DATA_COLLECTION_USER_INFO_CASES)
def test_client_address_span_attribute_data_collection(
tornado_testcase, sentry_init, capture_items, init_kwargs, expect_ip
):
sentry_init(
integrations=[TornadoIntegration()],
traces_sample_rate=1.0,
trace_lifecycle="stream",
**init_kwargs,
)

items = capture_items("span")

client = tornado_testcase(Application([(r"/hi", ChildSpanHandler)]))
client.fetch("/hi")

sentry_sdk.flush()

(server_span,) = [
item.payload
for item in items
if item.payload["attributes"].get("sentry.origin") == "auto.http.tornado"
]

if expect_ip:
assert server_span["attributes"]["client.address"] == "127.0.0.1"
else:
assert "client.address" not in server_span["attributes"]
Loading