Skip to content

feat(core): Data Collection - #5759

Draft
adinauer wants to merge 1 commit into
mainfrom
feat/data-collection
Draft

feat(core): Data Collection#5759
adinauer wants to merge 1 commit into
mainfrom
feat/data-collection

Conversation

@adinauer

@adinauer adinauer commented Jul 14, 2026

Copy link
Copy Markdown
Member

PR Stack (Data Collection)


📜 Description

Collection PR for the Data Collection stack. The individual PRs add the configuration model, resolution and compatibility bridge, external configuration, filtering, and integration enforcement.

Squash-merge this PR into main only after every stack PR has been merged into this branch using merge commits.

💡 Motivation and Context

Introduce the specification-defined dataCollection configuration while preserving existing sendDefaultPii behavior for users who do not opt into the new namespace.

Refs #5666

💚 How did you test it?

This collection branch contains only an empty commit. Each stack PR carries its own tests.

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

Merge the Data Collection stack into this branch in order, then squash-merge this PR into main.

#skip-changelog

@github-actions

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against dd4bdfc

@sentry

sentry Bot commented Jul 14, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.48.0 (1) release

⚙️ sentry-android Build Distribution Settings

@sentry-junior sentry-junior Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the full Data Collection stack tip (fix/data-collection-opentelemetry-span-description) against data-collection 0.11.0 and the landed/in-flight peers (JS, Python, Cocoa, Ruby, Go).

What looks solid

  • Config surface matches the required core: userInfo, cookies / httpHeaders / urlQueryParams key-value modes, directional httpBodies, graphQL, databaseQueryData.
  • Explicit-namespace resolution matches peers: once any dataCollection field is set (or an empty DataCollection is assigned), omitted fields take spec defaults, not sendDefaultPii. That matches JS resolveDataCollectionOptions and Go/Ruby “opt into defaults”.
  • Built-in sensitive terms match the denylist; partial case-insensitive matching and [Filtered] substitution look correct in HttpUtils.
  • Integration wiring for Spring/Servlet/OkHttp/Ktor/Apollo/GraphQL is real and tested; Replay kept independent (spec 0.10.0); Android installation ID restored as non-userInfo identity (pragmatic, well motivated).
  • Span descriptions stripping queries (Ktor/OTel) matches the structuring-data rule.

Please fix before merge

1. Legacy path still ships sensitive query values (and dual-path bypasses the denylist)

Spec: sensitive key-value data MUST be replaced with [Filtered] under automatic collection. Peers always run collection through a resolved policy (JS bridges sendDefaultPiiurlQueryParams: true / deny-with-PII-snippets, then filters; Go/Python/Cocoa same idea).

Java does not:

// UrlUtils.filterQueryParams
return resolver.isDataCollectionConfigured()
    ? HttpUtils.filterQueryParams(query, resolver.getUrlQueryParams())
    : query; // raw, including token=secret

This is covered as intentional in UrlUtilsTest (preserve legacy query values), and HTTP integrations fork the same way (isDataCollectionConfigured → new filter, else sendDefaultPii / old header drop). With default options (dataCollection absent, sendDefaultPii=false), request/span/breadcrumb query strings still attach token=secret whenever a query is collected.

Same dual-path issue on cookies: e.g. OkHttp legacy sendDefaultPii=true returns the raw cookie string with no sensitive denylist pass (Spring at least runs filterOutSecurityCookies*).

Fix shape: always resolve an effective KeyValueCollectionBehavior (spec default deny-list, or a legacy bridge like JS defaultPiiToCollectionOptions) and run all query/cookie/header collection through HttpUtils.filter*. Keep category on/off and PII-term bridges in the resolver; do not bypass scrubbing when the namespace is unset.

2. Public databaseQueryData is a no-op

DataCollection / DataCollectionResolver.isDatabaseQueryData() are public and tested, but tip-of-stack has zero JDBC/SQLite (or other) call sites. #5801’s enforcement was dropped (Preserve query descriptions), so users can set the option with no effect.

Spec note: databaseQueryData gates bound params / payloads / results, not necessarily sanitized db.query.text. If Java cannot separate literals safely, either:

  • drop the public option until there is a real consumer, or
  • document + enforce a concrete policy in sentry-jdbc / sentry-android-sqlite (and only suppress what the option is defined to control).

3. Non-Spring config surfaces still only know send-default-pii

Spring Boot binding works via SentryProperties extends SentryOptions + mutable KeyValueCollectionBehavior (#5834). ExternalOptions / sentry.properties and Android ManifestMetadataReader still only map send-default-pii. Peers expose dataCollection on their primary config path. At least property-file (and ideally manifest) keys for the new namespace should land with the stack, or the gap should be explicit in the PR/docs so hybrid and non-Spring users are not stuck on the legacy flag.

Spec / peer deltas (non-blocking, track explicitly)

Area Java stack Spec / peers
genAI, queues, stackFrameVariables, frameContextLines omitted required where platform collects that data; OK to defer if unused
graphql naming getGraphql() spec graphQL; Ruby/Python also snake/lower — fine if documented
Boolean shorthand for key-value (true/false) modes + factories only JS/Ruby accept bool shorthand — nice-to-have
Docs / wizard opt-out snippet not in stack spec MUST for init snippets
Major-version default flip stay on sendDefaultPii until explicit dataCollection same staged approach as JS pre-v11 / Cocoa v10

Bottom line

Architecture and explicit-namespace behavior are in good shape and aligned with other SDKs. I would not merge until (1) sensitive scrubbing cannot be skipped on the legacy path, and (2) databaseQueryData is either enforced or removed from the public API. (3) is strongly preferred in the same release train as the feature.

Happy to re-review after those land on the tip branch.

@sentry-junior
sentry-junior Bot dismissed their stale review September 1, 2026 13:09

Reframing as non-blocking comment per author request (minor release keeps legacy behavior until dataCollection opt-in).

@sentry-junior sentry-junior Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-posted as a non-blocking comment (dismissed the earlier changes-requested) so this does not block merge.

Reviewed the full Data Collection stack tip (fix/data-collection-opentelemetry-span-description) against data-collection 0.11.0 and the landed/in-flight peers (JS, Python, Cocoa, Ruby, Go).

Minor-release constraint acknowledged: until users opt into dataCollection, preserving current sendDefaultPii behavior is the right call. The notes below are tracking items / polish, not merge blockers for a minor.

What looks solid

  • Config surface matches the required core: userInfo, cookies / httpHeaders / urlQueryParams key-value modes, directional httpBodies, graphQL, databaseQueryData.
  • Explicit-namespace resolution matches peers: once any dataCollection field is set (or an empty DataCollection is assigned), omitted fields take spec defaults, not sendDefaultPii. That matches JS resolveDataCollectionOptions and Go/Ruby “opt into defaults”.
  • Built-in sensitive terms match the denylist; partial case-insensitive matching and [Filtered] substitution look correct in HttpUtils.
  • Integration wiring for Spring/Servlet/OkHttp/Ktor/Apollo/GraphQL is real and tested; Replay kept independent (spec 0.10.0); Android installation ID restored as non-userInfo identity (pragmatic, well motivated).
  • Span descriptions stripping queries (Ktor/OTel) matches the structuring-data rule.
  • Dual-path design (isDataCollectionConfigured → new filters, else legacy sendDefaultPii) is a deliberate compat bridge for a minor — same staged approach as JS pre-v11.

Non-blocking notes

1. Legacy path intentionally skips the new denylist until opt-in

UrlUtils.filterQueryParams returns raw query when the namespace is unset, and HTTP integrations fork the same way. That matches “keep doing what we did unless opted into data collection.” Spec-full scrubbing (and peer always-resolved policies) apply on the explicit path; full default flip is a major-version concern, not this minor.

Worth documenting clearly for users/hybrid SDKs so the dual path is not mistaken for incomplete wiring. Optional later hardening (major or opt-in-only): always resolve an effective KeyValueCollectionBehavior like JS defaultPiiToCollectionOptions once you are ready to change legacy defaults.

Cookie dual-path is slightly uneven today (OkHttp legacy sendDefaultPii=true can return raw cookies; Spring still runs filterOutSecurityCookies*) — pre-existing-ish, fine to leave for a follow-up unless you touch those call sites anyway.

2. Public databaseQueryData is currently a no-op

DataCollection / DataCollectionResolver.isDatabaseQueryData() are public and tested, but tip-of-stack has zero JDBC/SQLite (or other) call sites after #5801 dropped enforcement. Spec note: the option gates bound params / payloads / results, not necessarily sanitized db.query.text.

Suggestion when convenient: drop the public option until there is a real consumer, or wire a concrete policy in sentry-jdbc / sentry-android-sqlite and document the Java-specific literal limitation.

3. Non-Spring config surfaces still only know send-default-pii

Spring Boot binding works via SentryProperties extends SentryOptions + mutable KeyValueCollectionBehavior (#5834). ExternalOptions / sentry.properties and Android ManifestMetadataReader still only map send-default-pii. Fine for a first minor if programmatic + Spring are the supported opt-in paths — call out the gap in release notes so property-file / manifest users know they need code or Spring binding.

Spec / peer deltas (track explicitly)

Area Java stack Spec / peers
genAI, queues, stackFrameVariables, frameContextLines omitted OK to defer if platform does not collect that data yet
graphql naming getGraphql() spec graphQL; other SDKs also localize names
Boolean shorthand for key-value modes + factories only JS/Ruby accept bool shorthand — nice-to-have
Docs / wizard opt-out snippet not in stack spec MUST for init snippets when docs land
Major-version default flip stay on sendDefaultPii until explicit dataCollection aligned with JS pre-v11 / Cocoa staged rollout

Bottom line

Architecture and explicit-namespace behavior look good and aligned with other SDKs for a minor opt-in. No merge block from me — treat the items above as follow-ups / docs clarity rather than required changes for this train.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant