Skip to content

feat(core): Add configurable IScopesStorageFactory to SentryOptions#5199

Draft
adinauer wants to merge 5 commits intomainfrom
feat/configurable-scopes-storage-factory
Draft

feat(core): Add configurable IScopesStorageFactory to SentryOptions#5199
adinauer wants to merge 5 commits intomainfrom
feat/configurable-scopes-storage-factory

Conversation

@adinauer
Copy link
Member

📜 Description

Adds a new IScopesStorageFactory interface and a corresponding scopesStorageFactory option on SentryOptions. When set, the custom factory takes precedence over the default auto-detection logic in Sentry.initScopesStorage().

This allows users to provide a custom IScopesStorage implementation without reflection hacks, which is needed for frameworks where the default ThreadLocal-backed DefaultScopesStorage is incompatible (e.g. reactive/non-pinning thread models).

Changes:

  • New IScopesStorageFactory functional interface with a single create() method
  • SentryOptions.getScopesStorageFactory() / setScopesStorageFactory() (marked @Experimental)
  • Sentry.initScopesStorage() checks the custom factory first, then falls back to existing auto-detection

Fixes #5193

💡 Motivation and Context

Sentry.initScopesStorage() decides the storage implementation internally with no user-facing override. Users who need a custom IScopesStorage (e.g. backed by Vert.x context instead of ThreadLocal) had to use reflection to override the private static field.

💚 How did you test it?

  • Unit tests in SentryOptionsTest — default is null, getter/setter works, can reset to null
  • Unit tests in SentryTest — custom factory is invoked and init() called on the result, null factory falls back to default, custom storage is functional end-to-end

📝 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

  • Document how to use this for Quarkus/Vert.x reactive applications

Allow users to provide a custom IScopesStorage factory via
SentryOptions.setScopesStorageFactory(). When set, the custom factory
takes precedence over the default auto-detection logic.

Fixes #5193

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Contributor

Semver Impact of This PR

🟡 Minor (new features)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

  • (core) Add configurable IScopesStorageFactory to SentryOptions by adinauer in #5199

Internal Changes 🔧

Deps

  • Update Native SDK to v0.13.2 by github-actions in #5181
  • Bump github/codeql-action from 4.32.4 to 4.32.6 by dependabot in #5170
  • Bump dorny/paths-filter from 3.0.2 to 4.0.1 by dependabot in #5195
  • Bump actions/create-github-app-token from 2.2.1 to 3.0.0 by dependabot in #5196
  • Bump getsentry/craft from 2.23.1 to 2.24.1 by dependabot in #5197
  • Bump reactivecircus/android-emulator-runner from 2.35.0 to 2.37.0 by dependabot in #5194

🤖 This preview updates automatically when you update the PR.

@github-actions
Copy link
Contributor

Fails
🚫 Please consider adding a changelog entry for the next release.
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Instructions and example for changelog

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Example:

## Unreleased

### Features

- Add configurable IScopesStorageFactory to SentryOptions ([#5199](https://github.com/getsentry/sentry-java/pull/5199))

If none of the above apply, you can opt out of this check by adding #skip-changelog to the PR description or adding a skip-changelog label.

Generated by 🚫 dangerJS against 516865d

@sentry
Copy link

sentry bot commented Mar 16, 2026

Sentry Build Distribution

App Name App ID Version Configuration Install Page
SDK Size io.sentry.tests.size 8.35.0 (1) release Install Build

@github-actions
Copy link
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 314.00 ms 344.60 ms 30.60 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
f064536 327.04 ms 405.35 ms 78.31 ms
cf708bd 408.35 ms 458.98 ms 50.63 ms
d15471f 294.13 ms 399.49 ms 105.36 ms
9fbb112 361.43 ms 427.57 ms 66.14 ms
2387c2c 317.04 ms 354.60 ms 37.56 ms
806307f 357.85 ms 424.64 ms 66.79 ms
b193867 331.08 ms 397.06 ms 65.98 ms
dc4cc7a 361.10 ms 439.53 ms 78.43 ms
694d587 379.62 ms 400.80 ms 21.18 ms
17a0955 372.53 ms 446.70 ms 74.17 ms

App size

Revision Plain With Sentry Diff
f064536 1.58 MiB 2.20 MiB 633.90 KiB
cf708bd 1.58 MiB 2.11 MiB 539.71 KiB
d15471f 1.58 MiB 2.13 MiB 559.54 KiB
9fbb112 1.58 MiB 2.11 MiB 539.18 KiB
2387c2c 1.58 MiB 2.13 MiB 559.54 KiB
806307f 1.58 MiB 2.10 MiB 533.42 KiB
b193867 1.58 MiB 2.19 MiB 620.00 KiB
dc4cc7a 1.58 MiB 2.19 MiB 619.28 KiB
694d587 1.58 MiB 2.19 MiB 620.06 KiB
17a0955 1.58 MiB 2.10 MiB 533.20 KiB

Add LoadClass and ILogger parameters to IScopesStorageFactory.create()
so custom factories have access to class loading utilities.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

/** Factory for creating custom {@link IScopesStorage} implementations. */
@ApiStatus.Experimental
public interface IScopesStorageFactory {
Copy link
Member Author

Choose a reason for hiding this comment

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

Opted to keep this separate from ScopesStorageFactory since passing LoadClass and ILogger doesn't seem necessary.

@ApiStatus.Experimental
public interface IScopesStorageFactory {
@NotNull
IScopesStorage create();
Copy link
Member Author

Choose a reason for hiding this comment

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

Should we be passing in options here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Probably not necessary as long as it has to be configured in options callback of Sentry.init anyways. May make more sense if/when we support SPI.

SPI-discovered factory implementations are instantiated via ServiceLoader
with no-arg constructors, so they need access to options like logger and
DSN at creation time. Change the interface method signature to accept
SentryOptions as a parameter.

Co-Authored-By: Claude <noreply@anthropic.com>
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.

Provide a way to set IScopesStorage using SentryOptions

1 participant