feat(data-collection): create DataCollection option in client#6702
Conversation
Codecov Results 📊✅ 90435 passed | ⏭️ 6302 skipped | Total: 96737 | Pass Rate: 93.49% | Execution Time: 315m 59s 📊 Comparison with Base Branch
All tests are passing successfully. ✅ Patch coverage is 98.18%. Project has 2439 uncovered lines. Files with missing lines (1)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
+ Coverage 89.74% 89.79% +0.05%
==========================================
Files 192 193 +1
Lines 23823 23878 +55
Branches 8226 8244 +18
==========================================
+ Hits 21378 21439 +61
- Misses 2445 2439 -6
- Partials 1349 1351 +2Generated by Codecov Action |
…ssors Replace the class-based DataCollection/KeyValueCollectionBehavior/ GenAICollection/HttpHeadersCollection API with plain TypedDicts (DataCollection, DataCollectionUserOptions, and per-category *CollectionBehaviour/*UserOptions types) defined in _types.py. Collection mode strings move from camelCase (denyList/allowList) to snake_case (deny_list/allow_list) to match Python convention, since this is a Python-only deviation from the spec that is never serialized to Sentry. Drop the should_collect_user_info/should_collect_gen_ai_inputs/ should_collect_gen_ai_outputs accessor methods and their module-level shortcuts in favor of reading data_collection fields directly, and drop the public sentry_sdk.DataCollection/GenAICollection/ HttpHeadersCollection/KeyValueCollectionBehavior exports. Revert the Unreleased CHANGELOG entry and README example for the prior class-based API.
1d30c98 to
8b9dedb
Compare
|
bugbot run |
alexander-alderman-webb
left a comment
There was a problem hiding this comment.
Just did a quick pass, not a proper review.
Can we add underscores to everything we don't want users to access? 🙏
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 15c21c0. Configure here.
| include_local_variables=self.options["include_local_variables"] | ||
| is not False, | ||
| include_source_context=self.options["include_source_context"] | ||
| is not False, |
There was a problem hiding this comment.
Spotlight frame flags disagree
Medium Severity
In DSN-less Spotlight mode, re-derived data_collection uses include_local_variables is not False (and the same for include_source_context), while _resolve_data_collection treats those options with bool(value) when they are not None. Falsy non-boolean values such as 0 resolve to disabled frame settings initially but become enabled after the Spotlight override.
Reviewed by Cursor Bugbot for commit 15c21c0. Configure here.
| @property | ||
| def data_collection(self) -> "DataCollection": | ||
| return _DISABLED_DATA_COLLECTION_CONFIG | ||
|
|
There was a problem hiding this comment.
Unpickled client missing data_collection
Low Severity
_Client.__setstate__ restores options from pickled state and calls _init_impl without ensuring a resolved data_collection entry exists. Clients pickled before this option was added have no data_collection key, so DSN-less Spotlight setup or the new data_collection property can raise KeyError.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 15c21c0. Configure here.
…s - we don't currently support gating on that today within the Python SDK
|
Moving back to draft while I investigate the bot comments |
sentrivana
left a comment
There was a problem hiding this comment.
LGTM. Left a few comments.
| class HttpHeadersCollectionBehaviour(TypedDict): | ||
| request: "KeyValueCollectionBehaviour" | ||
|
|
||
| class DataCollectionUserOptions(TypedDict, total=False): |
There was a problem hiding this comment.
For my understanding, we have these type pairs (UserOptions and Behaviour) so that users don't need to specify all options (total=False on the UserOptions types), but also so that the materialized DataCollection that we'll use internally won't nag us about an option potentially being None, because it has to be fully filled out with default values in case any are missing, right?
I see why we have it like this but I'm afraid the two might drift eventually because we forget to update one of them.
It's not like I have better ideas 😀 The complexity we introduce with the config needs to be dealt with someplace, and I guess this is an ok place.
There was a problem hiding this comment.
For my understanding, we have these type pairs (UserOptions and Behaviour) so that users don't need to specify all options (total=False on the UserOptions types), but also so that the materialized DataCollection that we'll use internally won't nag us about an option potentially being None, because it has to be fully filled out with default values in case any are missing, right?
Yup, you've got it! I wanted to spare us from all the extra code we'd have to write to satisfy the typechecker when performing the checks within the integrations 😅
I agree with you about the risk of drift. I thought it'd be worth it in this case because after the data collection spec is implemented and settled, the amount of updates we'd need to do here would likely be minimal.
If we think of anything better throughout the implementation of the spec though, happy to come back and change the approach! 😄


Support more granular PII controls via the
data_collectionoption as seen in the spec.These changes:
send_default_pii(which will eventually be legacy) was set.They don't currently hook up to anything in order to keep the size of this pull request somewhat sane.
Some high-level design decisions to call out:
This was done so that, once we've received the config from the user and have set defaults for values that weren't provided, we can avoid needing to constantly check if the value is
Nonewithin the SDK.provided_by_userproperty within theDataCollectiontypeThis is mainly to deal with spotlight-related logic within the client, which you can see here.
Fixes PY-2570
Fixes #6700