Skip to content

Commit 16b4e67

Browse files
authored
Merge pull request #5961 from getsentry/docs/update-options-guidance
docs: [Logs and Metrics Enable Flags 12] Update options guidance
2 parents dc0c03f + 7d3fb89 commit 16b4e67

1 file changed

Lines changed: 50 additions & 29 deletions

File tree

‎.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.setEnableLogcatLogs(...)` for `io.sentry.logcat.logs.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.enableLogs` binds to
93+
`sentry.logging.enable-logs` 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 `enableLogs`
114+
- Log4j2: appender `enableLogs`
115+
- JUL: handler `enableLogs`
116+
- Spring Boot Logback: `sentry.logging.enable-logs`
117+
- Timber: `enableTimberLogs` / `io.sentry.timber.logs.enabled`
118+
- Logcat: `enableLogcatLogs` / `io.sentry.logcat.logs.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 apiDump` — 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 apiDump`

0 commit comments

Comments
 (0)