Skip to content

Commit 451a51c

Browse files
Merge branch '9.x.x' into sync/main-to-9.x.x-2026-11-03
Co-Authored-By: Roman Zavarnitsyn <roman.zavarnitsyn@sentry.io> # Conflicts: # .cursor/rules/options.mdc # CHANGELOG.md # build-logic/build.gradle.kts # sentry-apache-http-client-5/build.gradle.kts # sentry-async-profiler/build.gradle.kts # sentry-graphql-22/build.gradle.kts # sentry-graphql-core/build.gradle.kts # sentry-graphql/build.gradle.kts # sentry-jcache/build.gradle.kts # sentry-jdbc/build.gradle.kts # sentry-jul/build.gradle.kts # sentry-kafka/build.gradle.kts # sentry-launchdarkly-server/build.gradle.kts # sentry-log4j2/build.gradle.kts # sentry-logback/build.gradle.kts # sentry-openfeature/build.gradle.kts # sentry-openfeign/build.gradle.kts # sentry-opentelemetry/sentry-opentelemetry-agentless/build.gradle.kts # sentry-quartz/build.gradle.kts # sentry-servlet-jakarta/build.gradle.kts # sentry-servlet/build.gradle.kts # sentry-spring-boot/build.gradle.kts # sentry-spring/build.gradle.kts # sentry/src/main/java/io/sentry/SentryOptions.java # sentry/src/test/java/io/sentry/SentryTest.kt
2 parents 229b6d4 + bd51fe5 commit 451a51c

271 files changed

Lines changed: 1784 additions & 6962 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.craft.yml‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,6 @@ targets:
9999
packageUrl: https://central.sonatype.com/artifact/io.sentry/sentry-jul
100100
mainDocsUrl: https://docs.sentry.io/platforms/java/guides/jul/
101101
apiDocsUrl: https://javadoc.io/doc/io.sentry
102-
maven:io.sentry:sentry-apache-http-client-5:
103-
name: io.sentry:sentry-apache-http-client-5
104-
packageUrl: https://central.sonatype.com/artifact/io.sentry/sentry-apache-http-client-5
105-
mainDocsUrl: https://docs.sentry.io/platforms/java/
106-
apiDocsUrl: https://javadoc.io/doc/io.sentry
107102
maven:io.sentry:sentry-android:
108103
name: io.sentry:sentry-android
109104
packageUrl: https://central.sonatype.com/artifact/io.sentry/sentry-android

‎.cursor/BUGBOT.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ rule file in [`.cursor/rules/`](rules) for the area the diff touches (`api`, `op
5858

5959
## Java and Android specifics
6060

61-
- The core `sentry` module is Java 8 and must not reference Android or JVM-only APIs. Reach optional
61+
- The core `sentry` module is Java 11 and must not reference Android or JVM-only APIs. Reach optional
6262
platform code through `Platform`, `LoadClass`, or a separate module.
6363
- Android code calling an API newer than `minSdk` must be guarded by
6464
`BuildInfoProvider.getSdkInfoVersion()`.

‎.cursor/rules/api.mdc‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,13 @@ When adding a new method that users can call (e.g. a new scope operation), these
6363
7. `NoOpScope` — no-op stub for `IScope`
6464
8. `NoOpScopes` — no-op stub for `IScopes`
6565
9. `ScopesAdapter` — delegates to `Sentry` static API
66-
10. `HubAdapter` — deprecated bridge from old `IHub` API
67-
11. `HubScopesWrapper` — wraps `IScopes` as `IHub`
6866

6967
### Serialization (if the data is sent to Sentry)
70-
12. Add serialization/deserialization in the relevant data class or create a new one implementing `JsonSerializable` and `JsonDeserializer`
68+
10. Add serialization/deserialization in the relevant data class or create a new one implementing `JsonSerializable` and `JsonDeserializer`
7169

7270
### Tests
73-
13. Write tests for all implementations, especially `Scope`, `Scopes`, `SentryTest`, and any new data classes
74-
14. No-op classes typically don't need separate tests unless they have non-trivial logic
71+
11. Write tests for all implementations, especially `Scope`, `Scopes`, `SentryTest`, and any new data classes
72+
12. No-op classes typically don't need separate tests unless they have non-trivial logic
7573

7674
## Protocol / Data Model Classes
7775

‎.cursor/rules/options.mdc‎

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,24 @@ description: Adding and modifying SDK options
44
---
55
# Adding Options to the SDK
66

7-
New features must be **opt-in by default**. Options control whether a feature is enabled and how it behaves.
7+
New automatic capture features must be **opt-in by default**. Deliberate API calls such as
8+
`Sentry.logger()` and `Sentry.metrics()` capture whenever the SDK is enabled and do not have
9+
aggregate signal enable flags. Options control signal behavior and whether individual automatic
10+
sources are enabled.
811

912
## Namespaced Options
1013

1114
Newer features use namespaced option classes nested inside `SentryOptions`, e.g.:
1215
- `SentryOptions.getLogs()` → `SentryOptions.Logs`
1316
- `SentryOptions.getMetrics()` → `SentryOptions.Metrics`
1417

15-
Each namespaced options class is a `public static final class` inside `SentryOptions` with its own fields, getters/setters, and callbacks (e.g. `BeforeSendLogCallback`, `BeforeSendMetricCallback`).
18+
Each namespaced options class is a `public static final class` inside `SentryOptions` with its own fields, getters/setters, factories, and callbacks (e.g. `BeforeSendLogCallback`, `BeforeSendMetricCallback`).
1619

17-
A typical namespaced options class contains:
18-
- `enabled` boolean (default `false` for opt-in)
19-
- `sampleRate` double (if the feature supports sampling)
20-
- `beforeSend` callback interface (nested inside the options class)
20+
Do not assume that a namespaced signal needs an aggregate `enabled` field. In particular, Logs and
21+
Metrics are available through deliberate API calls whenever the SDK is enabled. Their namespaced
22+
options contain signal-specific behavior such as `beforeSend`, limits, and processor factories. Add
23+
options such as sampling only when the signal supports them. Automatic capture integrations use
24+
source-local enable options that default to `false`.
2125

2226
To add a new namespaced options class:
2327
1. Create the `public static final class` inside `SentryOptions` with fields, getters/setters, and any callback interfaces
@@ -47,21 +51,18 @@ The core options class. Add the field (or nested class) with getter/setter here.
4751
Allows setting options via `sentry.properties` file or system properties. Fields use nullable wrapper types (`@Nullable Boolean`, `@Nullable Double`) since unset means "don't override the default."
4852

4953
**File:** `sentry/src/main/java/io/sentry/ExternalOptions.java`
50-
- Add `@Nullable` fields with getter/setter for each externally configurable option (e.g. `enableMetrics`, `logsSampleRate`)
51-
- Wire them in the static `from(PropertiesProvider)` method:
52-
- Boolean: `propertiesProvider.getBooleanProperty("metrics.enabled")`
53-
- Double: `propertiesProvider.getDoubleProperty("logs.sample-rate")`
54+
- Add `@Nullable` fields with getter/setter for each externally configurable option (e.g. `logsSampleRate`)
55+
- Wire them in the static `from(PropertiesProvider)` method, for example:
56+
`propertiesProvider.getDoubleProperty("logs.sample-rate")`
5457

5558
**File:** `sentry/src/main/java/io/sentry/SentryOptions.java` — `merge()` method
5659
- Add null-check blocks to apply each external option onto the namespaced options class:
5760
```java
58-
if (options.isEnableMetrics() != null) {
59-
getMetrics().setEnabled(options.isEnableMetrics());
60-
}
6161
if (options.getLogsSampleRate() != null) {
6262
getLogs().setSampleRate(options.getLogsSampleRate());
6363
}
6464
```
65+
- Do not add or restore `logs.enabled` or `metrics.enabled`; these aggregate options are obsolete.
6566

6667
**Tests:**
6768
- `sentry/src/test/java/io/sentry/ExternalOptionsTest.kt` — test true/false/null for booleans, valid values and null for doubles
@@ -72,9 +73,12 @@ Allows setting options via `sentry.properties` file or system properties. Fields
7273
Allows setting options via `AndroidManifest.xml` `<meta-data>` tags.
7374

7475
**File:** `sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java`
75-
- Add a `static final String` constant for the key (e.g. `"io.sentry.metrics.enabled"`)
76+
- Add a `static final String` constant for the key
7677
- Read it in `applyMetadata()` using `readBool(metadata, logger, CONSTANT, defaultValue)`
77-
- Apply to the namespaced options, e.g. `options.getMetrics().setEnabled(...)`
78+
- Apply automatic-source options directly, for example
79+
`options.setLogcatLogCaptureEnabled(...)` for `io.sentry.logcat.log-capture.enabled`
80+
- Do not add or restore `io.sentry.logs.enabled` or `io.sentry.metrics.enabled`; those aggregate
81+
keys are obsolete.
7882

7983
**Tests:** `sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt`
8084
- Test default value preserved when not in manifest
@@ -83,21 +87,37 @@ Allows setting options via `AndroidManifest.xml` `<meta-data>` tags.
8387

8488
### 4. Spring Boot Properties (Spring Boot only)
8589

86-
`SentryProperties` extends `SentryOptions`, so namespaced options (nested classes) are automatically available as Spring Boot properties without extra code. For example, `SentryOptions.Logs` is automatically mapped to `sentry.logs.enabled` in `application.properties`.
90+
`SentryProperties` extends `SentryOptions`, so bindable namespaced behavior options are available
91+
through the `SentryOptions` class hierarchy. Spring-owned integration controls belong to a Spring
92+
namespace instead. For example, `SentryProperties.Logging.logsEnabled` binds to
93+
`sentry.logging.logs-enabled` and controls Logs forwarding from the auto-configured Logback
94+
appender. `sentry.logging.enabled` separately controls whether that appender is installed.
8795

88-
No additional code is needed for namespaced options — Spring Boot auto-configuration handles this via property binding on the `SentryOptions` class hierarchy.
96+
Do not add or restore `sentry.logs.enabled` or `sentry.metrics.enabled`; those aggregate properties
97+
are obsolete.
8998

9099
**Tests:** `sentry-spring-boot*/src/test/kotlin/.../SentryAutoConfigurationTest.kt`
91-
- Add the property (e.g. `"sentry.logs.enabled=true"`) to the existing `resolves all properties` test
100+
- Add the new property to the existing binding test
92101
- Assert the value is set on the resolved `SentryProperties` bean
102+
- Test default, explicit `true`, explicit `false`, and propagation into the owning integration
93103
- There are three Spring Boot modules with separate test files: `sentry-spring-boot`, `sentry-spring-boot-jakarta`, `sentry-spring-boot-4`
94104

95105
### 5. Reading Options at Runtime
96106

97-
Features check their options at usage time. For namespaced features the check typically happens in the feature's API class (e.g. `LoggerApi`, `MetricsApi`):
98-
- Check `options.getLogs().isEnabled()` early and return if disabled
99-
- Apply sampling via `options.getLogs().getSampleRate()` if applicable
100-
- Apply `beforeSend` callback in `SentryClient` before sending
107+
Deliberate APIs such as `LoggerApi` and `MetricsApi` do not check aggregate signal enable flags.
108+
They capture whenever their scopes are enabled, then apply signal behavior such as sampling and
109+
`beforeSend`.
110+
111+
Automatic integrations must check their source-local opt-in without affecting their existing event
112+
or breadcrumb paths. Current Logs controls are:
113+
- Logback: appender `logsEnabled`
114+
- Log4j2: appender `logsEnabled`
115+
- JUL: handler `logsEnabled`
116+
- Spring Boot Logback: `sentry.logging.logs-enabled`
117+
- Timber: `timberLogCaptureEnabled` / `io.sentry.timber.log-capture.enabled`
118+
- Logcat: `logcatLogCaptureEnabled` / `io.sentry.logcat.log-capture.enabled`
119+
120+
All source-local options default to `false` and gate only Sentry Logs forwarding.
101121

102122
When a feature has its own capture path (e.g. `captureLog`), the relevant classes are:
103123
- `ISentryClient` — add the capture method signature
@@ -106,10 +126,11 @@ When a feature has its own capture path (e.g. `captureLog`), the relevant classe
106126

107127
## Checklist for Adding a New Namespaced Option
108128

109-
1. `SentryOptions.java` — nested options class + getter/setter on `SentryOptions`
110-
2. `ExternalOptions.java` — `@Nullable` fields + wiring in `from()`
111-
3. `SentryOptions.java` `merge()` — apply external options to namespaced class
112-
4. `ManifestMetadataReader.java` — Android manifest support (if Android-relevant)
113-
5. `SentryAutoConfigurationTest.kt` — Spring Boot property binding tests (all three Spring Boot modules)
114-
6. Tests for all of the above (`SentryOptionsTest`, `ExternalOptionsTest`, `ManifestMetadataReaderTest`)
115-
7. Run `./gradlew updateKotlinAbi` — the nested class and its methods appear in `sentry.api`
129+
1. Decide whether the option controls deliberate API behavior or an automatic capture source
130+
2. `SentryOptions.java` — nested behavior option + getter/setter where core ownership is appropriate
131+
3. `ExternalOptions.java` and `SentryOptions.merge()` — add external support if applicable
132+
4. `ManifestMetadataReader.java` — add Android support if applicable
133+
5. Spring properties — use the owning integration namespace and test all three Spring Boot modules
134+
6. Test defaults and every supported configuration layer
135+
7. Verify automatic-source opt-ins default to `false` and do not gate events or breadcrumbs
136+
8. Run `./gradlew spotlessApply updateKotlinAbi`

‎.cursor/rules/scopes.mdc‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ Data itself is stored on `Scope` instances.
1414
## `Hub`
1515

1616
Up until major version 7 of the Java SDK the `IHub` interface was a central part of the SDK.
17-
In major version 8 we replaced the `IHub` interface with `IScopes`. `IHub` has been deprecated.
18-
While there is some bridging code in place to allow for easier migration, we are planning to remove it in an upcoming major.
17+
In major version 8 we replaced the `IHub` interface with `IScopes` and deprecated the Hub compatibility APIs.
18+
Those compatibility APIs were removed in major version 9.
1919

2020
## Scope Types
2121

@@ -79,7 +79,7 @@ There were several implementations of the `IHub` interface:
7979
`HubAdapter` has been replaced by `ScopesAdapter`
8080
`Hub.clone` should be replaced by using `pushScope` or `pushIsolationScope`
8181
`Sentry.getCurrentHub` has been replaced by `Sentry.getCurrentScopes`
82-
`Sentry.popScope` has been deprecated. Instead `close` should be called on the `ISentryLifecycleToken` returned e.g. by `pushScope`. This can also be done in a `try-with-resource` block.
82+
`Sentry.popScope` was deprecated in version 8 and removed in version 9. Instead, `close` should be called on the `ISentryLifecycleToken` returned e.g. by `pushScope`. This can also be done in a `try-with-resources` block.
8383

8484
## `globalHubMode`
8585
The SDK has a `globalHubMode` option which affects forking behaviour of the SDK.
@@ -93,8 +93,8 @@ For JVM Backend applications (servers) we discourage enabling `globalHubMode` si
9393
If `globalHubMode` is enabled, the SDK avoids forking scopes _implicitly_.
9494

9595
This means, retrieving current scopes on a thread where specific scopes do not exist yet for the thread, the root scopes are not forked but returned directly.
96-
`Sentry.pushScope`, `Sentry.pushIsolationScope` and `Sentry.popScope` are no-ops.
97-
They are unbalanced API: the caller may never restore the previous scopes, or restore them on a different thread, which would corrupt the globally shared scopes.
96+
`Sentry.pushScope` and `Sentry.pushIsolationScope` are no-ops and return no-op lifecycle tokens.
97+
Implicit forking is suppressed because callers could otherwise fail to restore the previous scopes, or restore them on a different thread, which would corrupt the globally shared scopes.
9898

9999
`Sentry.withScope` and `Sentry.withIsolationScope` do fork, also when `globalHubMode` is enabled.
100100
They are balanced by construction and always restore the previous scopes before returning, so they cannot corrupt the shared scopes.

‎.github/ISSUE_TEMPLATE/bug_report_java.yml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ body:
3939
- sentry-openfeign
4040
- sentry-openfeature
4141
- sentry-launchdarkly-server
42-
- sentry-apache-http-client-5
4342
- sentry-okhttp
4443
- sentry-reactor
4544
- other

‎.github/file-filters.yml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ high_risk_code: &high_risk_code
66
- "sentry/src/main/java/io/sentry/transport/HttpConnection.java"
77
- "sentry/src/main/java/io/sentry/transport/QueuedThreadPoolExecutor.java"
88
- "sentry/src/main/java/io/sentry/transport/RateLimiter.java"
9-
- "sentry-apache-http-client-5/src/main/java/io/sentry/transport/apache/ApacheHttpClientTransport.java"
109

1110
# Class used by hybrid SDKs
1211
- "sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java"

‎AGENTS.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ The repository is organized into multiple modules:
9696
### Integration Modules
9797
- **Spring Framework**: `sentry-spring*`, `sentry-spring-boot*`
9898
- **Logging**: `sentry-logback`, `sentry-log4j2`, `sentry-jul`, `sentry-android-timber`
99-
- **Web**: `sentry-servlet*`, `sentry-okhttp`, `sentry-openfeign`, `sentry-apache-http-client-5`
99+
- **Web**: `sentry-servlet*`, `sentry-okhttp`, `sentry-openfeign`
100100
- **GraphQL**: `sentry-graphql*`, `sentry-apollo*`
101101
- **Android UI**: `sentry-android-fragment`, `sentry-android-navigation`, `sentry-android-navigation3`, `sentry-compose`
102102
- **Session Replay**: `sentry-android-replay`
@@ -123,7 +123,7 @@ The repository is organized into multiple modules:
123123
## Development Guidelines
124124

125125
### Code Style
126-
- **Languages**: Java 8+ and Kotlin
126+
- **Languages**: Java 11+ and Kotlin
127127
- **Formatting**: Enforced via Spotless
128128
- **API Compatibility**: Binary compatibility is enforced. `.api` files are generated, never hand-edited
129129

0 commit comments

Comments
 (0)