feat(data-collection): create DataCollection option in client#6702
feat(data-collection): create DataCollection option in client#6702ericapisani wants to merge 20 commits into
5 issues
code-review: Found 5 issues (1 medium, 4 low)
Medium
`_kvcb_from_value` raises `AttributeError` instead of a descriptive error for non-dict inputs - `sentry_sdk/data_collection.py:168-169`
If a user passes a non-dict value for cookies or query_params (e.g. data_collection={"cookies": "off"}), val.get("mode", "deny_list") raises AttributeError: 'str' object has no attribute 'get' with no guidance on what went wrong. Consider adding an isinstance(val, dict) guard with a clear TypeError or ValueError.
Also found at:
sentry_sdk/consts.py:1282sentry_sdk/consts.py:1451-1454sentry_sdk/data_collection.py:254
Low
`graphql.document` docstring contradicts implementation in `_map_from_send_default_pii` - `sentry_sdk/client.py:27`
The docstring for _map_from_send_default_pii states that graphql.document "stays True" regardless of send_default_pii, while only graphql.variables and database.query_params follow it. The implementation instead sets graphql.document to send_default_pii, so it becomes False when PII is disabled. This is either a documentation error or a behavioral bug: if the spec intends the GraphQL query structure (document, not the PII-bearing variables) to always be collected, then gating it on send_default_pii is wrong. At minimum the contradiction will mislead maintainers about intended PII behavior. Worth confirming against the data-collection spec whether graphql.document should be gated on PII.
DeprecationWarning for `send_default_pii` points to internal SDK code instead of user callsite - `sentry_sdk/consts.py:1282`
The stacklevel=2 in resolve_data_collection (data_collection.py:253) points the warning to _get_options in client.py rather than the user's sentry_sdk.init() call. The actual call depth is: user → _init → Client.__init__ → _get_options → resolve_data_collection → warnings.warn, so a larger stacklevel is needed to surface the correct file/line in user code.
Also found at:
sentry_sdk/consts.py:1438-1440sentry_sdk/data_collection.py:252
`_http_headers_from_value` uses substring `in` on str values, masking malformed input and risking AttributeError - `sentry_sdk/data_collection.py:186-196`
_http_headers_from_value is typed to receive a dict but is fed d.get("http_headers", {}) with no type check. It uses "request" in val / "response" in val, which for a string performs a substring search rather than a key lookup. The test at test_http_headers_collection_defaults documents passing the str "off" as an invalid option and relies on this accident (neither "request" nor "response" is a substring of "off", so both fields silently fall back to deny_list). If a user instead passes a string that contains "request" or "response" (e.g. "incoming request"), the condition becomes True and val["request"] returns a single character, which is passed to _kvcb_from_value(...) and raises an unhelpful AttributeError (str has no .get). Adding an isinstance(val, dict) guard would make malformed input fail cleanly (or fall back to defaults) instead of silently masking it. Impact is limited to unsupported/malformed configuration input.
Also found at:
tests/test_data_collection.py:31-36
No test for `TypeError` when `data_collection` receives a non-dict value - `tests/test_data_collection.py:12-13`
The resolve_data_collection function explicitly raises TypeError when data_collection is not a dict, but there is no test exercising this path — unlike test_kvcb_invalid_mode which covers the ValueError for invalid modes.
⏱ 10m 35s · 4.1M in / 135.1k out · $5.30
Annotations
Check warning on line 169 in sentry_sdk/data_collection.py
sentry-warden / warden: code-review
`_kvcb_from_value` raises `AttributeError` instead of a descriptive error for non-dict inputs
If a user passes a non-dict value for `cookies` or `query_params` (e.g. `data_collection={"cookies": "off"}`), `val.get("mode", "deny_list")` raises `AttributeError: 'str' object has no attribute 'get'` with no guidance on what went wrong. Consider adding an `isinstance(val, dict)` guard with a clear `TypeError` or `ValueError`.
Check warning on line 1282 in sentry_sdk/consts.py
sentry-warden / warden: code-review
[TTU-25E] `_kvcb_from_value` raises `AttributeError` instead of a descriptive error for non-dict inputs (additional location)
If a user passes a non-dict value for `cookies` or `query_params` (e.g. `data_collection={"cookies": "off"}`), `val.get("mode", "deny_list")` raises `AttributeError: 'str' object has no attribute 'get'` with no guidance on what went wrong. Consider adding an `isinstance(val, dict)` guard with a clear `TypeError` or `ValueError`.
Check warning on line 1454 in sentry_sdk/consts.py
sentry-warden / warden: code-review
[TTU-25E] `_kvcb_from_value` raises `AttributeError` instead of a descriptive error for non-dict inputs (additional location)
If a user passes a non-dict value for `cookies` or `query_params` (e.g. `data_collection={"cookies": "off"}`), `val.get("mode", "deny_list")` raises `AttributeError: 'str' object has no attribute 'get'` with no guidance on what went wrong. Consider adding an `isinstance(val, dict)` guard with a clear `TypeError` or `ValueError`.
Check warning on line 254 in sentry_sdk/data_collection.py
sentry-warden / warden: code-review
[TTU-25E] `_kvcb_from_value` raises `AttributeError` instead of a descriptive error for non-dict inputs (additional location)
If a user passes a non-dict value for `cookies` or `query_params` (e.g. `data_collection={"cookies": "off"}`), `val.get("mode", "deny_list")` raises `AttributeError: 'str' object has no attribute 'get'` with no guidance on what went wrong. Consider adding an `isinstance(val, dict)` guard with a clear `TypeError` or `ValueError`.