From 96d7f26bccb7f091fa3eed52cea969eefed833eb Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Tue, 6 Oct 2026 07:14:43 -0400 Subject: [PATCH 1/9] ref(data-collection)!: Drop `send_default_pii` mapping and `provided_by_user` Remove `_map_from_send_default_pii` and the `provided_by_user` flag from the resolved `DataCollection`. `data_collection` is now always resolved from its explicit options (with spec defaults), so the `send_default_pii` fallback branches are no longer needed. - Delete `has_data_collection_enabled` and read `data_collection` directly in `get_lines_from_file`, `Scope`, outgoing request URL attributes, and the FastAPI and Strawberry integrations. - Drop the DSN-less Spotlight re-derivation of `data_collection`. Fixes PY-2932 Fixes #7882 --- sentry_sdk/_types.py | 1 - sentry_sdk/client.py | 11 - sentry_sdk/data_collection.py | 66 +--- sentry_sdk/integrations/fastapi.py | 20 +- sentry_sdk/integrations/strawberry.py | 18 +- sentry_sdk/scope.py | 6 +- sentry_sdk/tracing_utils.py | 23 +- sentry_sdk/utils.py | 20 +- tests/test_data_collection.py | 423 -------------------------- 9 files changed, 29 insertions(+), 559 deletions(-) diff --git a/sentry_sdk/_types.py b/sentry_sdk/_types.py index aeff75f4c2..e38478cafc 100644 --- a/sentry_sdk/_types.py +++ b/sentry_sdk/_types.py @@ -187,7 +187,6 @@ class DataCollectionUserOptions(TypedDict, total=False): frame_context_lines: int class DataCollection(TypedDict): - provided_by_user: bool user_info: bool cookies: "KeyValueCollectionBehaviour" http_headers: "HttpHeadersCollectionBehaviour" diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index 1380f3ec73..ca0d3c979c 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -19,7 +19,6 @@ ClientConstructor, ) from sentry_sdk.data_collection import ( - _map_from_send_default_pii, _resolve_data_collection, ) from sentry_sdk.envelope import Envelope, Item @@ -366,18 +365,8 @@ def _record_lost_event( self.spotlight = setup_spotlight(self.options) if self.spotlight is not None and not self.options["dsn"]: sample_all = lambda *_args, **_kwargs: 1.0 - self.options["send_default_pii"] = True self.options["error_sampler"] = sample_all self.options["traces_sampler"] = sample_all - # data_collection was resolved in _get_options() before this - # spotlight override flipped send_default_pii on. Re-derive it so - # data_collection agrees with should_send_default_pii() in - # DSN-less spotlight mode (only when the user did not set - # data_collection explicitly). - if not self.options["data_collection"]["provided_by_user"]: - self.options["data_collection"] = _map_from_send_default_pii( - send_default_pii=True - ) self.session_flusher = SessionFlusher(capture_func=_capture_envelope) diff --git a/sentry_sdk/data_collection.py b/sentry_sdk/data_collection.py index fbac357a18..004b5baf84 100644 --- a/sentry_sdk/data_collection.py +++ b/sentry_sdk/data_collection.py @@ -149,36 +149,6 @@ def _apply_key_value_collection_filtering( return result -def _map_from_send_default_pii(*, send_default_pii: bool) -> "DataCollection": - """ - Build a fully-resolved ``DataCollection`` dict that mirrors the data - ``send_default_pii`` collects today. Used when ``data_collection`` is not - provided explicitly. - """ - terms = [] if send_default_pii else ["forwarded", "-ip", "remote-", "via", "-user"] - - return { - "provided_by_user": False, - "user_info": send_default_pii, - "cookies": {"mode": "denylist", "terms": terms}, - # Headers are collected in both PII modes today (sensitive ones filtered - # when PII is off), so this never maps to "off". - "http_headers": { - "request": {"mode": "denylist", "terms": terms}, - }, - # Bodies are collected regardless of PII today, bounded by - # ``max_request_body_size``. - "http_bodies": list(_ALL_HTTP_BODY_TYPES), - "url_query_params": {"mode": "denylist", "terms": terms}, - "graphql": {"document": send_default_pii, "variables": send_default_pii}, - "gen_ai": {"inputs": send_default_pii, "outputs": send_default_pii}, - "database_query_data": send_default_pii, - "queues": send_default_pii, - "stack_frame_variables": True, - "frame_context_lines": _DEFAULT_FRAME_CONTEXT_LINES, - } - - def _resolve_explicit( d: "dict[str, Any]", ) -> "DataCollection": @@ -214,7 +184,6 @@ def _resolve_explicit( ) return { - "provided_by_user": True, "user_info": d.get("user_info", True), "cookies": _kvcb_from_value(d.get("cookies") or {}), "http_headers": _http_headers_from_value(d.get("http_headers") or {}), @@ -280,37 +249,20 @@ def _resolve_data_collection(options: "Dict[str, Any]") -> "DataCollection": """ Resolve the effective ``DataCollection`` dict from client ``options``. - Reads ``data_collection``, ``send_default_pii`` and returns a fully-resolved - dict with concrete values for every field. + Reads ``data_collection`` and returns a fully-resolved dict with concrete values for every field. ``data_collection`` must be a plain ``dict``. Must be called exactly once per options dict, before ``client._get_options`` - overwrites ``options["data_collection"]`` with the resolved result. Feeding an - already-resolved dict back in would flip ``provided_by_user`` to ``True``. + overwrites ``options["data_collection"]`` with the resolved result. """ - from sentry_sdk.utils import deprecation_warning + user_dc = options.get("data_collection", {}) - user_dc = options.get("data_collection") - if user_dc is None: - user_dc = options.get("_experiments", {}).get("data_collection") - - send_default_pii = options.get("send_default_pii") - - if user_dc is not None: - if not isinstance(user_dc, dict): - raise TypeError( - "`data_collection` must be a dict, got {!r}.".format( - type(user_dc).__name__ - ) - ) - if send_default_pii is not None: - deprecation_warning( - "`send_default_pii` is deprecated and ignored when " - "`data_collection` is set.", - ) - return _resolve_explicit( - user_dc, + if not isinstance(user_dc, dict): + raise TypeError( + "`data_collection` must be a dict, got {!r}.".format(type(user_dc).__name__) ) - return _map_from_send_default_pii(send_default_pii=bool(send_default_pii)) + return _resolve_explicit( + user_dc, + ) diff --git a/sentry_sdk/integrations/fastapi.py b/sentry_sdk/integrations/fastapi.py index 95bd6dd0de..80f0cd390c 100644 --- a/sentry_sdk/integrations/fastapi.py +++ b/sentry_sdk/integrations/fastapi.py @@ -12,7 +12,6 @@ get_current_span, ) from sentry_sdk.utils import ( - has_data_collection_enabled, parse_version, ) @@ -116,12 +115,10 @@ def event_processor(event: "Event", hint: "Dict[str, Any]") -> "Event": if "cookies" in info: request_info["cookies"] = info["cookies"] if "data" in info: - attach_request_data = True - if has_data_collection_enabled(client.options): - attach_request_data = ( - "incoming_request" - in client.options["data_collection"]["http_bodies"] - ) + attach_request_data = ( + "incoming_request" + in client.options["data_collection"]["http_bodies"] + ) if attach_request_data: request_info["data"] = info["data"] @@ -142,12 +139,9 @@ def event_processor(event: "Event", hint: "Dict[str, Any]") -> "Event": current_span = get_current_span() if type(current_span) is Span: - attach_request_data = True - if has_data_collection_enabled(client.options): - attach_request_data = ( - "incoming_request" - in client.options["data_collection"]["http_bodies"] - ) + attach_request_data = ( + "incoming_request" in client.options["data_collection"]["http_bodies"] + ) if attach_request_data: request_body = _get_cached_request_body_attribute( diff --git a/sentry_sdk/integrations/strawberry.py b/sentry_sdk/integrations/strawberry.py index a2d19dd2f9..0813640445 100644 --- a/sentry_sdk/integrations/strawberry.py +++ b/sentry_sdk/integrations/strawberry.py @@ -5,13 +5,11 @@ from sentry_sdk.consts import OP from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version from sentry_sdk.integrations.logging import ignore_logger_for_events -from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import SegmentNameSource from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, event_from_exception, - has_data_collection_enabled, logger, package_version, ) @@ -168,11 +166,7 @@ def on_operation(self) -> "Generator[None, None, None]": return additional_attributes: "dict[str, Any]" = {} - if has_data_collection_enabled(client.options): - if client.options["data_collection"]["graphql"]["document"]: - additional_attributes["graphql.document"] = self.execution_context.query - - elif should_send_default_pii(): + if client.options["data_collection"]["graphql"]["document"]: additional_attributes["graphql.document"] = self.execution_context.query if operation_name: @@ -400,13 +394,9 @@ def _make_response_event_processor( def inner(event: "Event", hint: "dict[str, Any]") -> "Event": client_options = sentry_sdk.get_client().options with capture_internal_exceptions(): - if has_data_collection_enabled(client_options): - collect_response = ( - "outgoing_response" - in client_options["data_collection"]["http_bodies"] - ) - else: - collect_response = should_send_default_pii() + collect_response = ( + "outgoing_response" in client_options["data_collection"]["http_bodies"] + ) if collect_response: contexts = event.setdefault("contexts", {}) diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index d9afacbd0c..75fdb8077d 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -43,7 +43,6 @@ event_from_exception, exc_info_from_error, format_attribute, - has_data_collection_enabled, logger, ) @@ -1443,10 +1442,7 @@ def _apply_user_attributes_to_telemetry( attributes = telemetry._attributes client_options = sentry_sdk.get_client().options - if has_data_collection_enabled(client_options): - if not client_options["data_collection"]["user_info"] or self._user is None: - return - elif not should_send_default_pii() or self._user is None: + if not client_options["data_collection"]["user_info"] or self._user is None: return for attribute_name, user_attribute in ( diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index 98684f5b75..8de4daec8d 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -23,7 +23,6 @@ _module_in_list, capture_internal_exceptions, filename_for_module, - has_data_collection_enabled, is_sentry_url, is_valid_sample_rate, logger, @@ -185,26 +184,18 @@ def get_url_attributes_legacy( ) -> "Attributes": """Build the `url.*` span attributes for an outgoing HTTP request. - The query string is only included when the user has opted into collecting - it, either through `data_collection` (in which case the configured - filtering is applied) or through the legacy `send_default_pii`. + The query string is filtered according to `data_collection`. """ attributes: "Attributes" = {} if parsed_url is None: return attributes - query: "Optional[str]" - if has_data_collection_enabled(client.options): - query = None - if parsed_url.query: - query = _apply_data_collection_filtering_to_query_string( - query_string=parsed_url.query, - behaviour=client.options["data_collection"]["url_query_params"], - ) - elif client.should_send_default_pii(): - query = parsed_url.query - else: - return attributes + query: "Optional[str]" = None + if parsed_url.query: + query = _apply_data_collection_filtering_to_query_string( + query_string=parsed_url.query, + behaviour=client.options["data_collection"]["url_query_params"], + ) url_full = parsed_url.url if query: diff --git a/sentry_sdk/utils.py b/sentry_sdk/utils.py index baf383e012..4bbc577ce4 100644 --- a/sentry_sdk/utils.py +++ b/sentry_sdk/utils.py @@ -65,7 +65,6 @@ from sentry_sdk._types import ( AttributeValue, - DataCollection, Event, ExcInfo, Hint, @@ -477,11 +476,7 @@ def get_lines_from_file( ) -> "Tuple[List[Annotated[str]], Optional[Annotated[str]], List[Annotated[str]]]": client_options = sentry_sdk.get_client().options - # This is the default pre-data collection. Should be removed once data collection - # is fully released - context_lines = 5 - if has_data_collection_enabled(client_options): - context_lines = client_options["data_collection"]["frame_context_lines"] + context_lines = client_options["data_collection"]["frame_context_lines"] source = None if loader is not None and hasattr(loader, "get_source"): @@ -1910,19 +1905,6 @@ def serialize_item( return str(data) -def has_data_collection_enabled(options: "Optional[dict[str, Any]]") -> bool: - if options is None: - return False - - data_collection: "Optional[DataCollection]" = options.get("data_collection") - # Client options are resolved as part of client initialization, so `data_collection` - # being None could be that the user just didn't provide it. - # `provided_by_user` is what actually records whether the user actually configured it. - return data_collection is not None and data_collection.get( - "provided_by_user", False - ) - - def get_before_send_log( options: "Optional[dict[str, Any]]", ) -> "Optional[Callable[[Log, Hint], Optional[Log]]]": diff --git a/tests/test_data_collection.py b/tests/test_data_collection.py index fa8b04a571..4759379f90 100644 --- a/tests/test_data_collection.py +++ b/tests/test_data_collection.py @@ -1,22 +1,11 @@ -import warnings - import pytest -import sentry_sdk -from sentry_sdk.data_collection import _ALL_HTTP_BODY_TYPES -from sentry_sdk.utils import has_data_collection_enabled - def test_kvcb_invalid_mode(sentry_init): with pytest.raises(ValueError): sentry_init(data_collection={"cookies": {"mode": "nope"}}) # type: ignore Purposely ignoring to test invalid option -def test_stack_frame_variables_invalid_mode(sentry_init): - with pytest.raises(ValueError): - sentry_init(data_collection={"stack_frame_variables": {"mode": "nope"}}) - - @pytest.mark.parametrize( "value", ["3", -1, [1], 2.5], @@ -30,415 +19,3 @@ def test_stack_frame_variables_invalid_mode(sentry_init): def test_frame_context_lines_invalid_value(sentry_init, value): with pytest.raises(ValueError): sentry_init(data_collection={"frame_context_lines": value}) - - -def test_kvcb_from_dict_defaults_mode(sentry_init): - sentry_init(data_collection={"cookies": {"mode": "denylist", "terms": ["x"]}}) - client = sentry_sdk.get_client() - assert client.options["data_collection"]["cookies"] == { - "mode": "denylist", - "terms": ["x"], - } - - -def test_http_headers_collection_defaults(sentry_init): - default_terms = ["forwarded", "-ip", "remote-", "via", "-user"] - - sentry_init(data_collection={"http_headers": {}}) # type: ignore Purposely ignoring to test invalid option - client = sentry_sdk.get_client() - assert client.options["data_collection"]["http_headers"]["request"] == { - "mode": "denylist" - } - - sentry_init(data_collection={"http_headers": "off"}) # type: ignore Purposely ignoring to test invalid option - client = sentry_sdk.get_client() - assert client.options["data_collection"]["http_headers"]["request"] == { - "mode": "denylist" - } - - sentry_init() - client = sentry_sdk.get_client() - assert client.options["data_collection"]["http_headers"]["request"] == { - "mode": "denylist", - "terms": default_terms, - } - - -def test_http_headers_use_default_in_setting_with_missing_config(sentry_init): - sentry_init( - data_collection={ - "http_headers": { - "request": {"mode": "allowlist", "terms": ["x-id"]}, - } - } - ) - - client = sentry_sdk.get_client() - - assert client.options["data_collection"]["http_headers"]["request"] == { - "mode": "allowlist", - "terms": ["x-id"], - } - - -def _initialize_client_with_config(sentry_init, **options): - sentry_init(**options) - return sentry_sdk.get_client().options["data_collection"] - - -def _get(dc, path): - obj = dc - for part in path.split("."): - obj = obj[part] - return obj - - -@pytest.mark.parametrize( - "options,expected", - [ - pytest.param( - {}, - { - "user_info": False, - "gen_ai.inputs": False, - "gen_ai.outputs": False, - "cookies.mode": "denylist", - "url_query_params.mode": "denylist", - "http_headers.request.mode": "denylist", - "http_bodies": _ALL_HTTP_BODY_TYPES, - "queues": False, - "frame_context_lines": 5, - }, - id="no_options_collects_no_pii", - ), - pytest.param( - {"send_default_pii": True}, - { - "user_info": True, - "gen_ai.inputs": True, - "gen_ai.outputs": True, - "cookies.mode": "denylist", - "url_query_params.mode": "denylist", - "queues": True, - }, - id="send_default_pii_true_collects_pii", - ), - pytest.param( - {"send_default_pii": False}, - {"user_info": False, "cookies.mode": "denylist", "queues": False}, - id="send_default_pii_false_collects_no_pii", - ), - pytest.param( - {"data_collection": {}}, - { - "user_info": True, - "gen_ai.inputs": True, - "gen_ai.outputs": True, - "cookies.mode": "denylist", - "url_query_params.mode": "denylist", - "http_bodies": _ALL_HTTP_BODY_TYPES, - "queues": True, - }, - id="explicit_data_collection_uses_spec_defaults", - ), - pytest.param( - {"data_collection": {"user_info": False, "http_bodies": []}}, - { - "user_info": False, - "http_bodies": [], - "gen_ai.inputs": True, - "cookies.mode": "denylist", - }, - id="explicit_partial_fills_omitted_with_spec_defaults", - ), - pytest.param( - { - "data_collection": { - "cookies": {"mode": "off"}, - "url_query_params": {"mode": "allowlist", "terms": ["page"]}, - "http_headers": {"request": {"mode": "off"}}, - "gen_ai": {"inputs": False, "outputs": True}, - } - }, - { - "cookies.mode": "off", - "url_query_params.mode": "allowlist", - "url_query_params.terms": ["page"], - "http_headers.request.mode": "off", - "gen_ai.inputs": False, - "gen_ai.outputs": True, - }, - id="accepts_dict_with_nested_dicts", - ), - pytest.param( - { - "data_collection": { - "cookies": None, - "http_headers": None, - "url_query_params": None, - "graphql": None, - "gen_ai": None, - } - }, - { - "cookies.mode": "denylist", - "http_headers.request.mode": "denylist", - "url_query_params.mode": "denylist", - "graphql.document": True, - "graphql.variables": True, - "gen_ai.inputs": True, - "gen_ai.outputs": True, - }, - id="none_values_fall_back_to_spec_defaults", - ), - pytest.param( - {"data_collection": {}}, - { - "graphql.document": True, - "graphql.variables": True, - "database_query_data": True, - }, - id="explicit_graphql_database_defaults", - ), - pytest.param( - {"send_default_pii": False}, - { - "graphql.document": False, - "graphql.variables": False, - "database_query_data": False, - "queues": False, - }, - id="legacy_pii_off_gates_graphql_database_and_queues", - ), - pytest.param( - {"send_default_pii": True}, - { - "graphql.document": True, - "graphql.variables": True, - "database_query_data": True, - "queues": True, - }, - id="legacy_pii_on_collects_graphql_database_and_queues", - ), - pytest.param( - {"data_collection": {"graphql": {"variables": False}}}, - {"graphql.document": True, "graphql.variables": False}, - id="explicit_partial_graphql_fills_omitted", - ), - pytest.param( - {"data_collection": {"frame_context_lines": True}}, - {"frame_context_lines": 5}, - id="frame_context_lines_bool_fallback_true", - ), - pytest.param( - {"data_collection": {"frame_context_lines": False}}, - {"frame_context_lines": 0}, - id="frame_context_lines_bool_fallback_false", - ), - pytest.param( - {"data_collection": {"frame_context_lines": 3}}, - {"frame_context_lines": 3}, - id="frame_context_lines_bool_fallback_3", - ), - pytest.param( - {"data_collection": {"frame_context_lines": 0}}, - {"frame_context_lines": 0}, - id="frame_context_lines_bool_fallback_0", - ), - pytest.param( - {"data_collection": {"stack_frame_variables": True}}, - {"stack_frame_variables": True}, - id="stack_frame_variables_explicit_true", - ), - pytest.param( - {"data_collection": {"stack_frame_variables": False}}, - {"stack_frame_variables": False}, - id="stack_frame_variables_explicit_false", - ), - pytest.param( - { - "data_collection": { - "stack_frame_variables": { - "mode": "allowlist", - "terms": ["order_id"], - } - } - }, - { - "stack_frame_variables": { - "mode": "allowlist", - "terms": ["order_id"], - } - }, - id="stack_frame_variables_allowlist_dict", - ), - pytest.param( - {"data_collection": {"stack_frame_variables": {"terms": ["order_id"]}}}, - { - "stack_frame_variables": { - "mode": "denylist", - "terms": ["order_id"], - } - }, - id="stack_frame_variables_dict_defaults_mode_to_denylist", - ), - pytest.param( - {"data_collection": {"stack_frame_variables": {"mode": "off"}}}, - {"stack_frame_variables": {"mode": "off"}}, - id="stack_frame_variables_off_dict_omits_terms", - ), - pytest.param( - {"data_collection": {"stack_frame_variables": "yes"}}, - {"stack_frame_variables": True}, - id="stack_frame_variables_non_bool_truthy_coerces_to_true", - ), - pytest.param( - {"data_collection": {"stack_frame_variables": ""}}, - {"stack_frame_variables": False}, - id="stack_frame_variables_non_bool_falsy_coerces_to_false", - ), - pytest.param( - {"data_collection": {"frame_context_lines": None}}, - {"frame_context_lines": 5}, - id="frame_context_lines_none_falls_back_to_spec_default", - ), - ], -) -def test_initialize_client_data_collection(sentry_init, options, expected): - dc = _initialize_client_with_config(sentry_init, **options) - for path, value in expected.items(): - assert _get(dc, path) == value, f"{path} != {value!r}" - - -def test_initialize_client_data_collection_overrides_send_default_pii_and_warns( - sentry_init, -): - with warnings.catch_warnings(record=True) as caught: - warnings.simplefilter("always") - dc = _initialize_client_with_config( - sentry_init, - send_default_pii=True, - data_collection={"user_info": False}, - ) - assert dc["user_info"] is False # data_collection wins - assert any(issubclass(w.category, DeprecationWarning) for w in caught) - - -@pytest.mark.parametrize( - "init_kwargs,expected", - [ - pytest.param( - {}, - { - "user_info": False, - "provided_by_user": False, - "should_send_default_pii": False, - }, - id="defaults_to_no_pii", - ), - pytest.param( - {"send_default_pii": True}, - {"user_info": True, "provided_by_user": False}, - id="send_default_pii_enables_user_info", - ), - pytest.param( - {"data_collection": {"user_info": False}}, - {"user_info": False, "provided_by_user": True}, - id="explicit_data_collection_overrides_user_info", - ), - pytest.param( - {"spotlight": True}, - {"provided_by_user": False, "user_info": True}, - id="dsnless_spotlight_rederives_data_collection", - ), - pytest.param( - { - "spotlight": True, - "data_collection": {"user_info": False}, - }, - {"provided_by_user": True, "user_info": False}, - id="dsnless_spotlight_respects_explicit_data_collection", - ), - ], -) -def test_client_data_collection_settings(sentry_init, init_kwargs, expected): - sentry_init(**init_kwargs) - client = sentry_sdk.get_client() - for key, value in expected.items(): - if key == "should_send_default_pii": - assert client.should_send_default_pii() is value - else: - assert client.options["data_collection"][key] is value - - -def test_has_data_collection_enabled_gates_on_user_provided_config(): - assert has_data_collection_enabled(None) is False - assert has_data_collection_enabled({}) is False - # An unset/None option is "not provided by the user". - assert has_data_collection_enabled({"data_collection": None}) is False - # Every SDK call site passes post-resolution client options, where - # `data_collection` is always a fully-resolved dict carrying - # `provided_by_user`. That flag -- not the key's presence -- is the gate. - assert ( - has_data_collection_enabled({"data_collection": {"provided_by_user": False}}) - is False - ) - assert ( - has_data_collection_enabled({"data_collection": {"provided_by_user": True}}) - is True - ) - - -@pytest.mark.parametrize( - "init_kwargs, expected", - [ - pytest.param({}, False, id="no_config"), - pytest.param({"send_default_pii": True}, False, id="send_default_pii_true"), - pytest.param({"send_default_pii": False}, False, id="send_default_pii_false"), - pytest.param({"data_collection": {}}, True, id="empty_data_collection"), - pytest.param( - {"data_collection": {"user_info": False}}, - True, - id="partial_data_collection", - ), - ], -) -def test_has_data_collection_enabled_after_resolution( - sentry_init, init_kwargs, expected -): - sentry_init(**init_kwargs) - assert has_data_collection_enabled(sentry_sdk.get_client().options) is expected - - -def test_no_data_collection_values_fall_back_to_send_default_pii_configuration( - sentry_init, -): - sentry_init(send_default_pii=True) - client = sentry_sdk.get_client() - dc = client.options["data_collection"] - assert dc["provided_by_user"] is False - assert dc["user_info"] is True - assert has_data_collection_enabled(client.options) is False - - -def test_data_collection_via_experiments(sentry_init): - sentry_init( - _experiments={"data_collection": {"user_info": True}}, - ) - - dc = sentry_sdk.get_client().options["data_collection"] - assert dc is not None - assert dc["provided_by_user"] is True - assert dc["user_info"] is True - - -def test_top_level_takes_precedence_over_experiments(sentry_init): - sentry_init( - data_collection={"user_info": False}, - _experiments={"data_collection": {"user_info": True}}, - ) - - dc = sentry_sdk.get_client().options["data_collection"] - assert dc is not None - assert dc["provided_by_user"] is True - assert dc["user_info"] is False From 05b2a590115255504f18fb05db3aa1bf36cbcf10 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Tue, 6 Oct 2026 07:35:43 -0400 Subject: [PATCH 2/9] . --- sentry_sdk/data_collection.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sentry_sdk/data_collection.py b/sentry_sdk/data_collection.py index 004b5baf84..9f4fc5357b 100644 --- a/sentry_sdk/data_collection.py +++ b/sentry_sdk/data_collection.py @@ -149,7 +149,7 @@ def _apply_key_value_collection_filtering( return result -def _resolve_explicit( +def _resolve( d: "dict[str, Any]", ) -> "DataCollection": """ @@ -256,13 +256,13 @@ def _resolve_data_collection(options: "Dict[str, Any]") -> "DataCollection": Must be called exactly once per options dict, before ``client._get_options`` overwrites ``options["data_collection"]`` with the resolved result. """ - user_dc = options.get("data_collection", {}) + user_dc = options.get("data_collection") or {} if not isinstance(user_dc, dict): raise TypeError( "`data_collection` must be a dict, got {!r}.".format(type(user_dc).__name__) ) - return _resolve_explicit( + return _resolve( user_dc, ) From f048dde57bc5bed655c87e35d48d36c982efd5a0 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Tue, 6 Oct 2026 08:20:21 -0400 Subject: [PATCH 3/9] ref(data-collection): Default data_collection to an empty dict Update the `data_collection` docstring and move the redis, logs, metrics, scope and tracing-utils tests off `send_default_pii`. Drop tests that asserted the removed `send_default_pii` behaviour. --- sentry_sdk/client.py | 7 +++--- sentry_sdk/consts.py | 10 ++++---- sentry_sdk/data_collection.py | 2 +- .../redis/cluster/test_redis_cluster.py | 23 +++++++++++-------- .../test_redis_cluster_asyncio.py | 23 +++++++++++-------- tests/integrations/redis/test_redis.py | 3 ++- .../redis/test_redis_cache_module.py | 7 +++--- tests/test_logs.py | 4 ++-- tests/test_metrics.py | 4 ++-- tests/test_scope.py | 6 ----- tests/test_tracing_utils.py | 5 ---- 11 files changed, 44 insertions(+), 50 deletions(-) diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index ca0d3c979c..129002b610 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -152,9 +152,10 @@ class BaseClient: spotlight: "Optional[SpotlightClient]" = None def __init__(self, options: "Optional[Dict[str, Any]]" = None) -> None: - self.options: "Dict[str, Any]" = ( - options if options is not None else DEFAULT_OPTIONS - ) + if options is None: + options = dict(DEFAULT_OPTIONS) + options["data_collection"] = _resolve_data_collection(options) + self.options: "Dict[str, Any]" = options self.transport: "Optional[Transport]" = None self.monitor: "Optional[Monitor]" = None diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index 231e87a2c3..8d5055b925 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -1354,7 +1354,7 @@ def __init__( transport_queue_size: int = DEFAULT_QUEUE_SIZE, sample_rate: float = 1.0, send_default_pii: "Optional[bool]" = None, - data_collection: "Optional[DataCollectionUserOptions]" = None, + data_collection: "Optional[DataCollectionUserOptions]" = {}, http_proxy: "Optional[str]" = None, https_proxy: "Optional[str]" = None, ignore_errors: "Sequence[Union[type, str]]" = [], # noqa: B006 @@ -1498,12 +1498,10 @@ def __init__( managing `Sensitive Data `_. :param data_collection: Structured configuration controlling what data integrations collect - automatically, superseding `send_default_pii`. Passing a dict opts into the feature; omitted - fields use their defaults (most categories are collected, with the sensitive denylist - scrubbing values). When it is not set, the SDK derives behaviour from `send_default_pii` so - that upgrading changes nothing. Restrict collection per category (user identity, cookies, + automatically. Omitted fields use their defaults (most categories are collected, with the sensitive denylist + scrubbing values). Restrict collection per category (user identity, cookies, HTTP headers/bodies, query params, generative AI inputs/outputs, stack frame variables, - source context). If `send_default_pii` is also set, `data_collection` takes precedence. + source context). Example:: diff --git a/sentry_sdk/data_collection.py b/sentry_sdk/data_collection.py index 9f4fc5357b..9c86da888c 100644 --- a/sentry_sdk/data_collection.py +++ b/sentry_sdk/data_collection.py @@ -256,7 +256,7 @@ def _resolve_data_collection(options: "Dict[str, Any]") -> "DataCollection": Must be called exactly once per options dict, before ``client._get_options`` overwrites ``options["data_collection"]`` with the resolved result. """ - user_dc = options.get("data_collection") or {} + user_dc = options.get("data_collection") if not isinstance(user_dc, dict): raise TypeError( diff --git a/tests/integrations/redis/cluster/test_redis_cluster.py b/tests/integrations/redis/cluster/test_redis_cluster.py index 2f6072f844..8fd72e5791 100644 --- a/tests/integrations/redis/cluster/test_redis_cluster.py +++ b/tests/integrations/redis/cluster/test_redis_cluster.py @@ -57,23 +57,23 @@ def test_rediscluster_breadcrumb(sentry_init, capture_events): @pytest.mark.parametrize( - "send_default_pii, description", + "data_collection, description", [ - (False, "SET 'bar' [Filtered]"), - (True, "SET 'bar' 1"), + ({"database_query_data": False}, "SET 'bar' [Filtered]"), + ({"database_query_data": True}, "SET 'bar' 1"), ], ) def test_rediscluster_basic( sentry_init, capture_events, capture_items, - send_default_pii, + data_collection, description, ): sentry_init( integrations=[RedisIntegration()], traces_sample_rate=1.0, - send_default_pii=send_default_pii, + data_collection=data_collection, ) items = capture_items("span") @@ -106,23 +106,26 @@ def test_rediscluster_basic( @pytest.mark.parametrize( - "send_default_pii, expected_first_ten", + "data_collection, expected_first_ten", [ - (False, ["GET 'foo'", "SET 'bar' [Filtered]", "SET 'baz' [Filtered]"]), - (True, ["GET 'foo'", "SET 'bar' 1", "SET 'baz' 2"]), + ( + {"database_query_data": False}, + ["GET 'foo'", "SET 'bar' [Filtered]", "SET 'baz' [Filtered]"], + ), + ({"database_query_data": True}, ["GET 'foo'", "SET 'bar' 1", "SET 'baz' 2"]), ], ) def test_rediscluster_pipeline( sentry_init, capture_events, capture_items, - send_default_pii, + data_collection, expected_first_ten, ): sentry_init( integrations=[RedisIntegration()], traces_sample_rate=1.0, - send_default_pii=send_default_pii, + data_collection=data_collection, ) rc = redis.RedisCluster(host="localhost", port=6379) diff --git a/tests/integrations/redis/cluster_asyncio/test_redis_cluster_asyncio.py b/tests/integrations/redis/cluster_asyncio/test_redis_cluster_asyncio.py index adaf968272..ce2e614b3d 100644 --- a/tests/integrations/redis/cluster_asyncio/test_redis_cluster_asyncio.py +++ b/tests/integrations/redis/cluster_asyncio/test_redis_cluster_asyncio.py @@ -62,10 +62,10 @@ async def test_async_breadcrumb(sentry_init, capture_events): @pytest.mark.parametrize( - "send_default_pii, description", + "data_collection, description", [ - (False, "SET 'bar' [Filtered]"), - (True, "SET 'bar' 1"), + ({"database_query_data": False}, "SET 'bar' [Filtered]"), + ({"database_query_data": True}, "SET 'bar' 1"), ], ) @pytest.mark.asyncio @@ -73,13 +73,13 @@ async def test_async_basic( sentry_init, capture_events, capture_items, - send_default_pii, + data_collection, description, ): sentry_init( integrations=[RedisIntegration()], traces_sample_rate=1.0, - send_default_pii=send_default_pii, + data_collection=data_collection, ) connection = cluster.RedisCluster(host="localhost", port=6379) @@ -107,23 +107,26 @@ async def test_async_basic( @pytest.mark.parametrize( - "send_default_pii, expected_first_ten", + "data_collection, expected_first_ten", [ - (False, ["GET 'foo'", "SET 'bar' [Filtered]", "SET 'baz' [Filtered]"]), - (True, ["GET 'foo'", "SET 'bar' 1", "SET 'baz' 2"]), + ( + {"database_query_data": False}, + ["GET 'foo'", "SET 'bar' [Filtered]", "SET 'baz' [Filtered]"], + ), + ({"database_query_data": True}, ["GET 'foo'", "SET 'bar' 1", "SET 'baz' 2"]), ], ) @pytest.mark.asyncio async def test_async_redis_pipeline( sentry_init, capture_items, - send_default_pii, + data_collection, expected_first_ten, ): sentry_init( integrations=[RedisIntegration()], traces_sample_rate=1.0, - send_default_pii=send_default_pii, + data_collection=data_collection, ) connection = cluster.RedisCluster(host="localhost", port=6379) diff --git a/tests/integrations/redis/test_redis.py b/tests/integrations/redis/test_redis.py index db0fa77410..3b0bb00aa1 100644 --- a/tests/integrations/redis/test_redis.py +++ b/tests/integrations/redis/test_redis.py @@ -97,6 +97,7 @@ def test_pii_data_redacted( sentry_init( integrations=[RedisIntegration()], traces_sample_rate=1.0, + data_collection={"database_query_data": False}, ) connection = FakeRedis() @@ -336,5 +337,5 @@ def test_span_origin(sentry_init, capture_items): assert parent_span["name"] == "custom parent" assert parent_span["attributes"]["sentry.origin"] == "manual" assert set_span["attributes"]["sentry.origin"] == "auto.db.redis" - assert set_span["attributes"][SPANDATA.DB_QUERY_TEXT] == "SET 'somekey' [Filtered]" + assert set_span["attributes"][SPANDATA.DB_QUERY_TEXT] == "SET 'somekey' 'somevalue'" assert pipeline_span["attributes"]["sentry.origin"] == "auto.db.redis" diff --git a/tests/integrations/redis/test_redis_cache_module.py b/tests/integrations/redis/test_redis_cache_module.py index 87984a2fc8..dcef21b6c8 100644 --- a/tests/integrations/redis/test_redis_cache_module.py +++ b/tests/integrations/redis/test_redis_cache_module.py @@ -79,8 +79,7 @@ def test_cache_basic(sentry_init, capture_events, capture_items): assert payloads[3]["attributes"][SPANDATA.DB_OPERATION_NAME] == "SET" assert payloads[4]["attributes"]["sentry.op"] == "cache.put" assert ( - payloads[4]["attributes"][SPANDATA.DB_QUERY_TEXT] - == "SET 'mycachekey1' [Filtered]" + payloads[4]["attributes"][SPANDATA.DB_QUERY_TEXT] == "SET 'mycachekey1' 'bla'" ) # setex: db then cache.put @@ -89,7 +88,7 @@ def test_cache_basic(sentry_init, capture_events, capture_items): assert payloads[6]["attributes"]["sentry.op"] == "cache.put" assert ( payloads[6]["attributes"][SPANDATA.DB_QUERY_TEXT] - == "SETEX 'mycachekey2' [Filtered] [Filtered]" + == "SETEX 'mycachekey2' 10 'blub'" ) # mget: db then cache.get @@ -98,7 +97,7 @@ def test_cache_basic(sentry_init, capture_events, capture_items): assert payloads[8]["attributes"]["sentry.op"] == "cache.get" assert ( payloads[8]["attributes"][SPANDATA.DB_QUERY_TEXT] - == "MGET 'mycachekey1' [Filtered]" + == "MGET 'mycachekey1' 'mycachekey2'" ) assert payloads[9]["name"] == "custom parent" diff --git a/tests/test_logs.py b/tests/test_logs.py index 7a9c90a566..ae107a99c6 100644 --- a/tests/test_logs.py +++ b/tests/test_logs.py @@ -354,8 +354,8 @@ def test_log_user_attributes(sentry_init, capture_items): def test_log_no_user_attributes_if_no_pii(sentry_init, capture_items): - """User attributes are not if PII sending is off.""" - sentry_init(send_default_pii=False) + """User attributes are not sent if `user_info` is off.""" + sentry_init(data_collection={"user_info": False}) sentry_sdk.set_user({"id": "1", "email": "test@example.com", "username": "test"}) items = capture_items("log") diff --git a/tests/test_metrics.py b/tests/test_metrics.py index dab4b60706..ec05fde140 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -82,8 +82,8 @@ def test_metrics_with_user(sentry_init, capture_items): assert metrics[0]["attributes"]["user.name"] == "testuser" -def test_metrics_no_user_if_pii_off(sentry_init, capture_items): - sentry_init(send_default_pii=False) +def test_metrics_no_user_if_user_info_off(sentry_init, capture_items): + sentry_init(data_collection={"user_info": False}) items = capture_items("trace_metric") sentry_sdk.set_user( diff --git a/tests/test_scope.py b/tests/test_scope.py index c9e3653577..559223fb44 100644 --- a/tests/test_scope.py +++ b/tests/test_scope.py @@ -850,12 +850,6 @@ def test_should_send_default_pii_false_with_dsn_and_spotlight(sentry_init): assert should_send_default_pii() is False -def test_should_send_default_pii_true_without_dsn_and_spotlight(sentry_init): - sentry_init(spotlight=True) - - assert should_send_default_pii() is True - - def test_set_tags(): scope = Scope() scope.set_tags({"tag1": "value1", "tag2": "value2"}) diff --git a/tests/test_tracing_utils.py b/tests/test_tracing_utils.py index 5e034d2f90..6942cc6f86 100644 --- a/tests/test_tracing_utils.py +++ b/tests/test_tracing_utils.py @@ -335,11 +335,6 @@ def _get_query_breadcrumb_data( {"db.params": [1, 2], "db.paramstyle": "format"}, id="data_collection_default_records_params", ), - pytest.param( - {}, - {}, - id="no_options_strips_params", - ), ), ) def test_record_sql_queries_data_collection( From 93ff8999fbac086d036d64e37917c92e6ba1ad2c Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Tue, 6 Oct 2026 08:36:35 -0400 Subject: [PATCH 4/9] update aiomysql and starlette tests --- tests/integrations/aiomysql/test_aiomysql.py | 45 +------------------ .../integrations/starlette/test_starlette.py | 1 - 2 files changed, 2 insertions(+), 44 deletions(-) diff --git a/tests/integrations/aiomysql/test_aiomysql.py b/tests/integrations/aiomysql/test_aiomysql.py index 53c2a207de..fe4511624b 100644 --- a/tests/integrations/aiomysql/test_aiomysql.py +++ b/tests/integrations/aiomysql/test_aiomysql.py @@ -203,47 +203,6 @@ async def test_execute_many(sentry_init, capture_events) -> None: (event,) = events - for crumb in event["breadcrumbs"]["values"]: - del crumb["timestamp"] - - assert event["breadcrumbs"]["values"] == [ - CRUMBS_CONNECT, - { - "category": "query", - "data": {"db.executemany": True}, - "message": "INSERT INTO users(name, password, dob) VALUES (%s, %s, %s)", - "type": "default", - }, - ] - - -@pytest.mark.asyncio -async def test_execute_many_record_params_with_data_collection_enabled( - sentry_init, capture_events -) -> None: - sentry_init( - integrations=[AioMySQLIntegration()], - data_collection={"database_query_data": True}, - ) - events = capture_events() - - conn = await aiomysql.connect(**_connect_args()) - - async with conn.cursor() as cur: - await cur.executemany( - "INSERT INTO users(name, password, dob) VALUES (%s, %s, %s)", - [ - ("Bob", "secret_pw", datetime.date(1984, 3, 1)), - ("Alice", "pw", datetime.date(1990, 12, 25)), - ], - ) - - conn.close() - - capture_message("hi") - - (event,) = events - for crumb in event["breadcrumbs"]["values"]: del crumb["timestamp"] @@ -266,12 +225,12 @@ async def test_execute_many_record_params_with_data_collection_enabled( @pytest.mark.asyncio -async def test_execute_many_record_params_with_data_collection_default( +async def test_execute_many_record_params_with_data_collection_enabled( sentry_init, capture_events ) -> None: sentry_init( integrations=[AioMySQLIntegration()], - data_collection={}, + data_collection={"database_query_data": True}, ) events = capture_events() diff --git a/tests/integrations/starlette/test_starlette.py b/tests/integrations/starlette/test_starlette.py index 417dd75781..577f30c0c8 100644 --- a/tests/integrations/starlette/test_starlette.py +++ b/tests/integrations/starlette/test_starlette.py @@ -451,7 +451,6 @@ async def test_formdata_request_body_data_collection_http_bodies_empty( @pytest.mark.parametrize( "data_collection, expect_body", [ - pytest.param(None, True, id="no_data_collection_experiment"), pytest.param({}, True, id="data_collection_http_bodies_default"), pytest.param( {"http_bodies": ["incoming_request"]}, From 7845a8f0a0f02795d147ff2384ec9f5f8614c2df Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Tue, 6 Oct 2026 09:11:01 -0400 Subject: [PATCH 5/9] fix fastapi --- tests/integrations/fastapi/test_fastapi.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integrations/fastapi/test_fastapi.py b/tests/integrations/fastapi/test_fastapi.py index ab8f34d982..05337cd7e0 100644 --- a/tests/integrations/fastapi/test_fastapi.py +++ b/tests/integrations/fastapi/test_fastapi.py @@ -289,7 +289,6 @@ async def test_formdata_request_body_data_collection_http_bodies_empty( @pytest.mark.parametrize( "data_collection, expect_body", [ - pytest.param(None, True, id="no_data_collection_experiment"), pytest.param({}, True, id="data_collection_http_bodies_default"), pytest.param( {"http_bodies": ["incoming_request"]}, From 61fbafc85fc886de55817f82802fb2019f896b7d Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Tue, 6 Oct 2026 09:25:06 -0400 Subject: [PATCH 6/9] . --- tests/integrations/aws_lambda/test_aws_lambda.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrations/aws_lambda/test_aws_lambda.py b/tests/integrations/aws_lambda/test_aws_lambda.py index 2af9432cb7..190d241313 100644 --- a/tests/integrations/aws_lambda/test_aws_lambda.py +++ b/tests/integrations/aws_lambda/test_aws_lambda.py @@ -232,7 +232,7 @@ def test_non_dict_event( if has_request_data: request_data = { - "headers": {"Host": "x1.io", "X-Forwarded-Proto": "[Filtered]"}, + "headers": {"Host": "x1.io", "X-Forwarded-Proto": "https"}, "method": "GET", "url": "https://x1.io/1", "query_string": { From 704c9c2349b292b282b19971ece9a402491ffa16 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Tue, 6 Oct 2026 10:35:09 -0400 Subject: [PATCH 7/9] . --- sentry_sdk/data_collection.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/sentry_sdk/data_collection.py b/sentry_sdk/data_collection.py index 9c86da888c..2baf78dcc2 100644 --- a/sentry_sdk/data_collection.py +++ b/sentry_sdk/data_collection.py @@ -5,21 +5,10 @@ "Data Collection" spec (https://develop.sentry.dev/sdk/foundations/client/data-collection/). -``data_collection`` supersedes the single ``send_default_pii`` boolean with a -structured configuration that lets users enable or restrict automatically +``data_collection`` lets users enable or restrict automatically collected data by category (user identity, cookies, HTTP headers, URL query params, HTTP bodies, generative AI inputs/outputs, stack frame variables, source context). - -Resolution precedence (see :func:`_resolve_data_collection`): - -* ``data_collection`` set, ``send_default_pii`` unset -> honour ``data_collection`` - using the spec defaults for any omitted field. -* ``send_default_pii`` set, ``data_collection`` unset -> derive a - resolved ``DataCollection`` that mirrors what ``send_default_pii`` collects today. -* neither set -> treated as ``send_default_pii=False``. -* both set -> ``data_collection`` wins (it is the single source of truth); a - ``DeprecationWarning`` is emitted for ``send_default_pii``. """ from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Union, cast From 825d38609f9959eec6dbb208fcbe59de92144e69 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Tue, 6 Oct 2026 11:11:31 -0400 Subject: [PATCH 8/9] . --- .../redis/cluster/test_redis_cluster.py | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/tests/integrations/redis/cluster/test_redis_cluster.py b/tests/integrations/redis/cluster/test_redis_cluster.py index 07bbd455be..849e7ed63b 100644 --- a/tests/integrations/redis/cluster/test_redis_cluster.py +++ b/tests/integrations/redis/cluster/test_redis_cluster.py @@ -104,27 +104,10 @@ def test_rediscluster_basic( assert attrs["db.redis.key"] == "bar" -@pytest.mark.parametrize( - "data_collection, expected_first_ten", - [ - ( - {"database_query_data": False}, - ["GET 'foo'", "SET 'bar' [Filtered]", "SET 'baz' [Filtered]"], - ), - ({"database_query_data": True}, ["GET 'foo'", "SET 'bar' 1", "SET 'baz' 2"]), - ], -) -def test_rediscluster_pipeline( - sentry_init, - capture_events, - capture_items, - data_collection, - expected_first_ten, -): +def test_rediscluster_pipeline(sentry_init, capture_items): sentry_init( integrations=[RedisIntegration()], traces_sample_rate=1.0, - data_collection=data_collection, ) rc = redis.RedisCluster(host="localhost", port=6379) From 59aa0c4662cff63ad03374294a791242b553f35c Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Tue, 6 Oct 2026 11:42:42 -0400 Subject: [PATCH 9/9] ref: Remove should_send_default_pii helpers from client and scope (#7892) Drop `BaseClient.should_send_default_pii`, `_Client.should_send_default_pii` and the module-level `scope.should_send_default_pii` shortcut. Fixes PY-2932 Fixes #7882 --- sentry_sdk/client.py | 11 ----------- sentry_sdk/scope.py | 5 ----- 2 files changed, 16 deletions(-) diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index 129002b610..c106373101 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -178,9 +178,6 @@ def dsn(self) -> "Optional[str]": def parsed_dsn(self) -> "Optional[Dsn]": return None - def should_send_default_pii(self) -> bool: - return False - def is_active(self) -> bool: """ .. versionadded:: 2.0.0 @@ -441,14 +438,6 @@ def is_active(self) -> bool: """ return True - def should_send_default_pii(self) -> bool: - """ - .. versionadded:: 2.0.0 - - Returns whether the client should send default PII (Personally Identifiable Information) data to Sentry. - """ - return self.options.get("send_default_pii") or False - @property def dsn(self) -> "Optional[str]": """Returns the configured DSN as string.""" diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index 75fdb8077d..6df27c470f 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -1870,11 +1870,6 @@ def use_isolation_scope(isolation_scope: "Scope") -> "Generator[Scope, None, Non capture_internal_exception(sys.exc_info()) -def should_send_default_pii() -> bool: - """Shortcut for `Scope.get_client().should_send_default_pii()`.""" - return Scope.get_client().should_send_default_pii() - - # Circular imports from sentry_sdk.client import NonRecordingClient