feat(core): Add configurable IScopesStorageFactory to SentryOptions#5199
feat(core): Add configurable IScopesStorageFactory to SentryOptions#5199
Conversation
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>
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨
Internal Changes 🔧Deps
🤖 This preview updates automatically when you update the PR. |
Instructions and example for changelogPlease add an entry to 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 |
Sentry Build Distribution
|
Performance metrics 🚀
|
| 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" This reverts commit a0d77eb.
|
|
||
| /** Factory for creating custom {@link IScopesStorage} implementations. */ | ||
| @ApiStatus.Experimental | ||
| public interface IScopesStorageFactory { |
There was a problem hiding this comment.
Opted to keep this separate from ScopesStorageFactory since passing LoadClass and ILogger doesn't seem necessary.
| @ApiStatus.Experimental | ||
| public interface IScopesStorageFactory { | ||
| @NotNull | ||
| IScopesStorage create(); |
There was a problem hiding this comment.
Should we be passing in options here?
There was a problem hiding this comment.
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>
📜 Description
Adds a new
IScopesStorageFactoryinterface and a correspondingscopesStorageFactoryoption onSentryOptions. When set, the custom factory takes precedence over the default auto-detection logic inSentry.initScopesStorage().This allows users to provide a custom
IScopesStorageimplementation without reflection hacks, which is needed for frameworks where the defaultThreadLocal-backedDefaultScopesStorageis incompatible (e.g. reactive/non-pinning thread models).Changes:
IScopesStorageFactoryfunctional interface with a singlecreate()methodSentryOptions.getScopesStorageFactory()/setScopesStorageFactory()(marked@Experimental)Sentry.initScopesStorage()checks the custom factory first, then falls back to existing auto-detectionFixes #5193
💡 Motivation and Context
Sentry.initScopesStorage()decides the storage implementation internally with no user-facing override. Users who need a customIScopesStorage(e.g. backed by Vert.x context instead ofThreadLocal) had to use reflection to override the private static field.💚 How did you test it?
SentryOptionsTest— default is null, getter/setter works, can reset to nullSentryTest— custom factory is invoked andinit()called on the result, null factory falls back to default, custom storage is functional end-to-end📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps