|
5 | 5 | "Data Collection" spec |
6 | 6 | (https://develop.sentry.dev/sdk/foundations/client/data-collection/). |
7 | 7 |
|
8 | | -``data_collection`` supersedes the single ``send_default_pii`` boolean with a |
9 | | -structured configuration that lets users enable or restrict automatically |
| 8 | +``data_collection`` lets users enable or restrict automatically |
10 | 9 | collected data by category (user identity, cookies, HTTP headers, URL query params, |
11 | 10 | HTTP bodies, generative AI inputs/outputs, stack frame variables, source |
12 | 11 | context). |
13 | | -
|
14 | | -Resolution precedence (see :func:`_resolve_data_collection`): |
15 | | -
|
16 | | -* ``data_collection`` set, ``send_default_pii`` unset -> honour ``data_collection`` |
17 | | - using the spec defaults for any omitted field. |
18 | | -* ``send_default_pii`` set, ``data_collection`` unset -> derive a |
19 | | - resolved ``DataCollection`` that mirrors what ``send_default_pii`` collects today. |
20 | | -* neither set -> treated as ``send_default_pii=False``. |
21 | | -* both set -> ``data_collection`` wins (it is the single source of truth); a |
22 | | - ``DeprecationWarning`` is emitted for ``send_default_pii``. |
23 | 12 | """ |
24 | 13 |
|
25 | 14 | from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Union, cast |
@@ -149,37 +138,7 @@ def _apply_key_value_collection_filtering( |
149 | 138 | return result |
150 | 139 |
|
151 | 140 |
|
152 | | -def _map_from_send_default_pii(*, send_default_pii: bool) -> "DataCollection": |
153 | | - """ |
154 | | - Build a fully-resolved ``DataCollection`` dict that mirrors the data |
155 | | - ``send_default_pii`` collects today. Used when ``data_collection`` is not |
156 | | - provided explicitly. |
157 | | - """ |
158 | | - terms = [] if send_default_pii else ["forwarded", "-ip", "remote-", "via", "-user"] |
159 | | - |
160 | | - return { |
161 | | - "provided_by_user": False, |
162 | | - "user_info": send_default_pii, |
163 | | - "cookies": {"mode": "denylist", "terms": terms}, |
164 | | - # Headers are collected in both PII modes today (sensitive ones filtered |
165 | | - # when PII is off), so this never maps to "off". |
166 | | - "http_headers": { |
167 | | - "request": {"mode": "denylist", "terms": terms}, |
168 | | - }, |
169 | | - # Bodies are collected regardless of PII today, bounded by |
170 | | - # ``max_request_body_size``. |
171 | | - "http_bodies": list(_ALL_HTTP_BODY_TYPES), |
172 | | - "url_query_params": {"mode": "denylist", "terms": terms}, |
173 | | - "graphql": {"document": send_default_pii, "variables": send_default_pii}, |
174 | | - "gen_ai": {"inputs": send_default_pii, "outputs": send_default_pii}, |
175 | | - "database_query_data": send_default_pii, |
176 | | - "queues": send_default_pii, |
177 | | - "stack_frame_variables": True, |
178 | | - "frame_context_lines": _DEFAULT_FRAME_CONTEXT_LINES, |
179 | | - } |
180 | | - |
181 | | - |
182 | | -def _resolve_explicit( |
| 141 | +def _resolve( |
183 | 142 | d: "dict[str, Any]", |
184 | 143 | ) -> "DataCollection": |
185 | 144 | """ |
@@ -214,7 +173,6 @@ def _resolve_explicit( |
214 | 173 | ) |
215 | 174 |
|
216 | 175 | return { |
217 | | - "provided_by_user": True, |
218 | 176 | "user_info": d.get("user_info", True), |
219 | 177 | "cookies": _kvcb_from_value(d.get("cookies") or {}), |
220 | 178 | "http_headers": _http_headers_from_value(d.get("http_headers") or {}), |
@@ -280,37 +238,20 @@ def _resolve_data_collection(options: "Dict[str, Any]") -> "DataCollection": |
280 | 238 | """ |
281 | 239 | Resolve the effective ``DataCollection`` dict from client ``options``. |
282 | 240 |
|
283 | | - Reads ``data_collection``, ``send_default_pii`` and returns a fully-resolved |
284 | | - dict with concrete values for every field. |
| 241 | + Reads ``data_collection`` and returns a fully-resolved dict with concrete values for every field. |
285 | 242 |
|
286 | 243 | ``data_collection`` must be a plain ``dict``. |
287 | 244 |
|
288 | 245 | Must be called exactly once per options dict, before ``client._get_options`` |
289 | | - overwrites ``options["data_collection"]`` with the resolved result. Feeding an |
290 | | - already-resolved dict back in would flip ``provided_by_user`` to ``True``. |
| 246 | + overwrites ``options["data_collection"]`` with the resolved result. |
291 | 247 | """ |
292 | | - from sentry_sdk.utils import deprecation_warning |
293 | | - |
294 | 248 | user_dc = options.get("data_collection") |
295 | | - if user_dc is None: |
296 | | - user_dc = options.get("_experiments", {}).get("data_collection") |
297 | 249 |
|
298 | | - send_default_pii = options.get("send_default_pii") |
299 | | - |
300 | | - if user_dc is not None: |
301 | | - if not isinstance(user_dc, dict): |
302 | | - raise TypeError( |
303 | | - "`data_collection` must be a dict, got {!r}.".format( |
304 | | - type(user_dc).__name__ |
305 | | - ) |
306 | | - ) |
307 | | - if send_default_pii is not None: |
308 | | - deprecation_warning( |
309 | | - "`send_default_pii` is deprecated and ignored when " |
310 | | - "`data_collection` is set.", |
311 | | - ) |
312 | | - return _resolve_explicit( |
313 | | - user_dc, |
| 250 | + if not isinstance(user_dc, dict): |
| 251 | + raise TypeError( |
| 252 | + "`data_collection` must be a dict, got {!r}.".format(type(user_dc).__name__) |
314 | 253 | ) |
315 | 254 |
|
316 | | - return _map_from_send_default_pii(send_default_pii=bool(send_default_pii)) |
| 255 | + return _resolve( |
| 256 | + user_dc, |
| 257 | + ) |
0 commit comments