Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
aeb796b
collection: logs and metrics enable flags
adinauer Aug 12, 2026
ae1f43a
feat(logback): Add Logs opt-in
adinauer Aug 12, 2026
7419f01
changelog
adinauer Aug 12, 2026
8b994c1
feat(log4j2): Add Logs opt-in
adinauer Aug 12, 2026
11568c0
changelog
adinauer Aug 12, 2026
abe6ede
feat(jul): Add Logs opt-in
adinauer Aug 12, 2026
17f0881
changelog
adinauer Aug 12, 2026
dd174d9
feat(android): Add Timber Logs opt-in
adinauer Aug 12, 2026
4f677fb
changelog
adinauer Aug 12, 2026
6a65f6f
feat(android): Add Logcat Logs opt-in
adinauer Aug 12, 2026
c432ec5
changelog
adinauer Aug 12, 2026
ae8f804
feat(spring): Add logging Logs opt-in
adinauer Aug 12, 2026
381242f
changelog
adinauer Aug 12, 2026
6a22345
feat(core): Remove Logs enable flag
adinauer Aug 12, 2026
2121c08
changelog
adinauer Aug 12, 2026
fcb8040
feat(android): Warn for legacy Logs metadata
adinauer Aug 12, 2026
50dc84e
feat(core): Warn for legacy Logs configuration
adinauer Aug 13, 2026
419986b
feat(spring): Warn for legacy Logs property
adinauer Aug 13, 2026
fb91733
perf(core): Avoid unused Logs worker thread
adinauer Aug 13, 2026
0a41b97
feat(core): Remove Metrics enable flag
adinauer Aug 13, 2026
01b74ec
feat(android): Warn for legacy Metrics metadata
adinauer Aug 13, 2026
5f068d3
feat(core): Warn for legacy Metrics configuration
adinauer Aug 13, 2026
61f485a
feat(spring): Warn for legacy Metrics property
adinauer Aug 13, 2026
170abc9
perf(core): Start Metrics batch worker on first use
adinauer Aug 13, 2026
6f13618
fix(jul): Preserve null-message events and breadcrumbs
adinauer Aug 13, 2026
b9d76ce
fix(samples): Remove obsolete Logback Logs option
adinauer Aug 13, 2026
4ed5fd2
Merge branch 'feat/remove-logs-enable-flag' into feat/warn-legacy-log…
adinauer Aug 13, 2026
8a414c2
Merge branch 'feat/warn-legacy-logs-manifest' into feat/warn-legacy-l…
adinauer Aug 13, 2026
ea02b63
Merge branch 'feat/warn-legacy-logs-external' into feat/warn-legacy-l…
adinauer Aug 13, 2026
d61869d
Merge branch 'feat/warn-legacy-logs-spring' into perf/logs-batch-thre…
adinauer Aug 13, 2026
be088e4
Merge branch 'perf/logs-batch-thread-first-use' into feat/remove-metr…
adinauer Aug 13, 2026
def8c18
Merge branch 'feat/remove-metrics-enable-flag' into feat/warn-legacy-…
adinauer Aug 13, 2026
35c93b5
Merge branch 'feat/warn-legacy-metrics-manifest' into feat/warn-legac…
adinauer Aug 13, 2026
9545c0c
Merge branch 'feat/warn-legacy-metrics-external' into feat/warn-legac…
adinauer Aug 13, 2026
53c1405
Merge branch 'feat/warn-legacy-metrics-spring' into perf/metrics-batc…
adinauer Aug 13, 2026
831e343
Merge branch 'perf/metrics-batch-thread-first-use' into fix/jul-null-…
adinauer Aug 13, 2026
b87e331
fix(core): Keep Metrics test constructor internal
adinauer Aug 13, 2026
937e886
Merge branch 'perf/metrics-batch-thread-first-use' into fix/jul-null-…
adinauer Aug 13, 2026
3b52f01
docs: Update options guidance for Logs and Metrics
adinauer Aug 13, 2026
6e791e5
fix(android): Read Timber Logs option after configuration
adinauer Aug 13, 2026
8c2f35f
fix(spring): Warn after SDK initialization
adinauer Aug 13, 2026
86bc036
Merge branch 'feat/warn-legacy-logs-spring' into perf/logs-batch-thre…
adinauer Aug 13, 2026
ab38817
Merge branch 'perf/logs-batch-thread-first-use' into feat/remove-metr…
adinauer Aug 13, 2026
281f533
Merge branch 'feat/remove-metrics-enable-flag' into feat/warn-legacy-…
adinauer Aug 13, 2026
57aee1b
Merge branch 'feat/warn-legacy-metrics-manifest' into feat/warn-legac…
adinauer Aug 13, 2026
532ecf2
Merge branch 'feat/warn-legacy-metrics-external' into feat/warn-legac…
adinauer Aug 13, 2026
78f04f7
Merge branch 'feat/warn-legacy-metrics-spring' into perf/metrics-batc…
adinauer Aug 13, 2026
3f9466a
Merge branch 'perf/metrics-batch-thread-first-use' into fix/jul-null-…
adinauer Aug 13, 2026
85c3a58
Merge branch 'fix/jul-null-log-message' into docs/update-options-guid…
adinauer Aug 13, 2026
4d120ff
Merge branch 'docs/update-options-guidance' into fix/timber-lazy-logs…
adinauer Aug 13, 2026
cd8fe1f
chore(stack): Merge 9.x.x into collection branch
adinauer Sep 29, 2026
ed6ddae
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
c30da7d
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
9285b4c
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
f0d4297
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
228fb0e
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
4037818
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
cd831b8
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
12bd9e7
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
6492416
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
b2d5569
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
6a54fd8
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
a313cc3
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
fb24f93
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
d0923b2
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
ec1a6e2
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
9583935
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
9c2e78e
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
1ef2a3b
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
3370b99
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
56278c8
fix(android): Use manifest metadata lookup helper
adinauer Sep 29, 2026
c61b7f7
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
8df8eca
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
785afd0
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
818d660
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
5ebb4c6
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
8cf1b6a
fix(android): Use metadata helper for legacy Metrics option
adinauer Sep 29, 2026
809fd1f
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
59221c9
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
cafd4d2
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
020d5b8
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
3400991
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
f80efed
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
0b37db6
ref(core): Remove legacy Logs warning inputs
adinauer Sep 30, 2026
fbd4440
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
3f987ba
ref(android): Remove legacy Logs metadata warnings
adinauer Sep 30, 2026
cacf0ab
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
95e50e2
ref(core): Remove legacy Logs configuration warnings
adinauer Sep 30, 2026
e726a81
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
4f318e5
ref(spring): Remove legacy Logs property warnings
adinauer Sep 30, 2026
d8a1618
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
136a434
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
81e86e1
ref(core): Remove legacy Metrics warning inputs
adinauer Sep 30, 2026
2a2032f
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
06ebc5c
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
687862f
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
58989ab
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
d45fe8e
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
8a94edb
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
e6be758
docs: Remove legacy enable-flag warning guidance
adinauer Sep 30, 2026
3086653
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
2293fcd
fix(spring): Forward Logs option to Log4j2 appender
adinauer Sep 30, 2026
7896054
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
2bf0043
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
7918934
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
02c5be6
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
855d289
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
862c778
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
d603a85
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
8a070f8
fix(jul): Handle null messages with resource bundles
adinauer Sep 30, 2026
cb65d6e
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
aaaae31
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
f4afe79
docs(options): Clarify conditional signal options
adinauer Oct 1, 2026
8a9b284
chore(stack): Merge preceding stack changes
adinauer Oct 1, 2026
c32509e
fix(timber): Keep lazy logs constructor internal
adinauer Oct 1, 2026
c44b851
Merge pull request #5940 from getsentry/feat/logs-opt-in-logback
adinauer Oct 9, 2026
15f4197
Merge pull request #5941 from getsentry/feat/logs-opt-in-log4j2
adinauer Oct 9, 2026
46a0ae4
Merge pull request #5942 from getsentry/feat/logs-opt-in-jul
adinauer Oct 9, 2026
1c7e8e6
Merge pull request #5943 from getsentry/feat/logs-opt-in-timber
adinauer Oct 9, 2026
cbfbab8
Merge pull request #5945 from getsentry/feat/logs-opt-in-logcat
adinauer Oct 9, 2026
df083ba
Merge pull request #5946 from getsentry/feat/logs-opt-in-spring-boot
adinauer Oct 9, 2026
67e11cc
ref(logging): Remove unused no-op Logs processor
adinauer Oct 9, 2026
e870503
chore(stack): Merge preceding stack changes
adinauer Oct 9, 2026
81f1310
chore(stack): Merge preceding stack changes
adinauer Oct 9, 2026
a1e848a
ref(metrics): Remove unused no-op batch processor
adinauer Oct 9, 2026
481c394
chore(stack): Merge preceding stack changes
adinauer Oct 9, 2026
1a948e4
chore(stack): Merge preceding stack changes
adinauer Oct 9, 2026
7d3fb89
chore(stack): Merge preceding stack changes
adinauer Oct 9, 2026
c05ab4a
chore(stack): Merge preceding stack changes
adinauer Oct 9, 2026
3a3da5c
Merge pull request #5947 from getsentry/feat/remove-logs-enable-flag
adinauer Oct 9, 2026
79e962f
Merge pull request #5952 from getsentry/perf/logs-batch-thread-first-use
adinauer Oct 9, 2026
98074e6
Merge pull request #5953 from getsentry/feat/remove-metrics-enable-flag
adinauer Oct 9, 2026
1f9fc8a
Merge pull request #5957 from getsentry/perf/metrics-batch-thread-fir…
adinauer Oct 9, 2026
dc0c03f
Merge pull request #5960 from getsentry/fix/jul-null-log-message
adinauer Oct 9, 2026
16b4e67
Merge pull request #5961 from getsentry/docs/update-options-guidance
adinauer Oct 9, 2026
7cd057f
Merge pull request #5964 from getsentry/fix/timber-lazy-logs-option
adinauer Oct 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 50 additions & 29 deletions .cursor/rules/options.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,24 @@ description: Adding and modifying SDK options
---
# Adding Options to the SDK

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

## Namespaced Options

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

Each namespaced options class is a `public static final class` inside `SentryOptions` with its own fields, getters/setters, and callbacks (e.g. `BeforeSendLogCallback`, `BeforeSendMetricCallback`).
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`).

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

To add a new namespaced options class:
1. Create the `public static final class` inside `SentryOptions` with fields, getters/setters, and any callback interfaces
Expand Down Expand Up @@ -47,21 +51,18 @@ The core options class. Add the field (or nested class) with getter/setter here.
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."

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

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

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

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

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

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

`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`.
`SentryProperties` extends `SentryOptions`, so bindable namespaced behavior options are available
through the `SentryOptions` class hierarchy. Spring-owned integration controls belong to a Spring
namespace instead. For example, `SentryProperties.Logging.enableLogs` binds to
`sentry.logging.enable-logs` and controls Logs forwarding from the auto-configured Logback
appender. `sentry.logging.enabled` separately controls whether that appender is installed.

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

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

### 5. Reading Options at Runtime

Features check their options at usage time. For namespaced features the check typically happens in the feature's API class (e.g. `LoggerApi`, `MetricsApi`):
- Check `options.getLogs().isEnabled()` early and return if disabled
- Apply sampling via `options.getLogs().getSampleRate()` if applicable
- Apply `beforeSend` callback in `SentryClient` before sending
Deliberate APIs such as `LoggerApi` and `MetricsApi` do not check aggregate signal enable flags.
They capture whenever their scopes are enabled, then apply signal behavior such as sampling and
`beforeSend`.

Automatic integrations must check their source-local opt-in without affecting their existing event
or breadcrumb paths. Current Logs controls are:
- Logback: appender `enableLogs`
- Log4j2: appender `enableLogs`
- JUL: handler `enableLogs`
- Spring Boot Logback: `sentry.logging.enable-logs`
- Timber: `enableTimberLogs` / `io.sentry.timber.logs.enabled`
- Logcat: `enableLogcatLogs` / `io.sentry.logcat.logs.enabled`

All source-local options default to `false` and gate only Sentry Logs forwarding.

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

## Checklist for Adding a New Namespaced Option

1. `SentryOptions.java` — nested options class + getter/setter on `SentryOptions`
2. `ExternalOptions.java` — `@Nullable` fields + wiring in `from()`
3. `SentryOptions.java` `merge()` — apply external options to namespaced class
4. `ManifestMetadataReader.java` — Android manifest support (if Android-relevant)
5. `SentryAutoConfigurationTest.kt` — Spring Boot property binding tests (all three Spring Boot modules)
6. Tests for all of the above (`SentryOptionsTest`, `ExternalOptionsTest`, `ManifestMetadataReaderTest`)
7. Run `./gradlew apiDump` — the nested class and its methods appear in `sentry.api`
1. Decide whether the option controls deliberate API behavior or an automatic capture source
2. `SentryOptions.java` — nested behavior option + getter/setter where core ownership is appropriate
3. `ExternalOptions.java` and `SentryOptions.merge()` — add external support if applicable
4. `ManifestMetadataReader.java` — add Android support if applicable
5. Spring properties — use the owning integration namespace and test all three Spring Boot modules
6. Test defaults and every supported configuration layer
7. Verify automatic-source opt-ins default to `false` and do not gate events or breadcrumbs
8. Run `./gradlew spotlessApply apiDump`
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

### Features

- Remove the aggregate Sentry Metrics enable flag; `Sentry.metrics()` calls now capture Metrics by default ([#5953](https://github.com/getsentry/sentry-java/pull/5953))
- Remove the aggregate Sentry Logs enable flag; manual `Sentry.logger()` calls now capture Logs by default ([#5947](https://github.com/getsentry/sentry-java/pull/5947))
- Add an explicit Logs opt-in to Spring Boot logging auto-configuration ([#5946](https://github.com/getsentry/sentry-java/pull/5946))
- Add an explicit Logs opt-in to the Android Logcat integration ([#5945](https://github.com/getsentry/sentry-java/pull/5945))
- Add an explicit Logs opt-in to the Android Timber integration ([#5943](https://github.com/getsentry/sentry-java/pull/5943))
- Add an explicit Logs opt-in to the JUL handler ([#5942](https://github.com/getsentry/sentry-java/pull/5942))
- Add an explicit Logs opt-in to the Log4j2 appender ([#5941](https://github.com/getsentry/sentry-java/pull/5941))
- Add an explicit Logs opt-in to the Logback appender ([#5940](https://github.com/getsentry/sentry-java/pull/5940))
- Deprecate `sendDefaultPii` in favor of `dataCollection` ahead of its removal in 9.0 ([#6158](https://github.com/getsentry/sentry-java/pull/6158))
- Make the tombstone merge time threshold configurable via `SentryAndroidOptions.setTombstoneMergeTimeThresholdMillis` and the `io.sentry.tombstone.merge-time-threshold-millis` manifest option ([#6154](https://github.com/getsentry/sentry-java/pull/6154))

Expand Down
4 changes: 4 additions & 0 deletions sentry-android-core/api/sentry-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
public fun isEnableAutoActivityLifecycleTracing ()Z
public fun isEnableAutoTraceIdGeneration ()Z
public fun isEnableFramesTracking ()Z
public fun isEnableLogcatLogs ()Z
public fun isEnableNdk ()Z
public fun isEnableNdkAppHangTracking ()Z
public fun isEnableNetworkEventBreadcrumbs ()Z
Expand All @@ -462,6 +463,7 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
public fun isEnableStandaloneAppStartTracing ()Z
public fun isEnableSystemEventBreadcrumbs ()Z
public fun isEnableSystemEventBreadcrumbsExtras ()Z
public fun isEnableTimberLogs ()Z
public fun isMemoryLimiterEnabled ()Z
public fun isReportHistoricalAnrs ()Z
public fun isReportHistoricalMemoryLimiterExits ()Z
Expand All @@ -488,6 +490,7 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
public fun setEnableAutoActivityLifecycleTracing (Z)V
public fun setEnableAutoTraceIdGeneration (Z)V
public fun setEnableFramesTracking (Z)V
public fun setEnableLogcatLogs (Z)V
public fun setEnableNdk (Z)V
public fun setEnableNdkAppHangTracking (Z)V
public fun setEnableNetworkEventBreadcrumbs (Z)V
Expand All @@ -497,6 +500,7 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
public fun setEnableStandaloneAppStartTracing (Z)V
public fun setEnableSystemEventBreadcrumbs (Z)V
public fun setEnableSystemEventBreadcrumbsExtras (Z)V
public fun setEnableTimberLogs (Z)V
public fun setFrameMetricsCollector (Lio/sentry/android/core/internal/util/SentryFrameMetricsCollector;)V
public fun setMemoryLimiterEnabled (Z)V
public fun setNativeHandlerStrategy (Lio/sentry/android/core/NdkHandlerStrategy;)V
Expand Down
2 changes: 1 addition & 1 deletion sentry-android-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ dependencies {
testImplementation(projects.sentrySpotlight)
testImplementation(projects.sentryAndroidFragment)
testImplementation(projects.sentryAndroidTimber)
testImplementation(libs.timber)
testImplementation(projects.sentryAndroidReplay)
testImplementation(projects.sentryCompose)
testImplementation(projects.sentryAndroidNdk)
Expand All @@ -136,5 +137,4 @@ dependencies {
testImplementation(libs.androidx.compose.foundation.layout)
testImplementation(libs.androidx.compose.material3)
testRuntimeOnly(libs.androidx.fragment.ktx)
testRuntimeOnly(libs.timber)
}
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ static void installDefaultIntegrations(
}

if (isTimberAvailable) {
options.addIntegration(new SentryTimberIntegration());
options.addIntegration(new SentryTimberIntegration(() -> options.isEnableTimberLogs()));
}
options.addIntegration(new AppComponentsBreadcrumbsIntegration(context));
options.addIntegration(new SystemEventsBreadcrumbsIntegration(context));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,9 @@ final class ManifestMetadataReader {

static final String IN_APP_EXCLUDES = "io.sentry.in-app-excludes";

static final String ENABLE_LOGS = "io.sentry.logs.enabled";
static final String ENABLE_TIMBER_LOGS = "io.sentry.timber.logs.enabled";

static final String ENABLE_METRICS = "io.sentry.metrics.enabled";
static final String ENABLE_LOGCAT_LOGS = "io.sentry.logcat.logs.enabled";

static final String ENABLE_AUTO_TRACE_ID_GENERATION =
"io.sentry.traces.enable-auto-id-generation";
Expand Down Expand Up @@ -750,14 +750,11 @@ static void applyMetadata(
}
}

options
.getLogs()
.setEnabled(readBool(metadata, logger, ENABLE_LOGS, options.getLogs().isEnabled()));
options.setEnableTimberLogs(
readBool(metadata, logger, ENABLE_TIMBER_LOGS, options.isEnableTimberLogs()));

options
.getMetrics()
.setEnabled(
readBool(metadata, logger, ENABLE_METRICS, options.getMetrics().isEnabled()));
options.setEnableLogcatLogs(
readBool(metadata, logger, ENABLE_LOGCAT_LOGS, options.isEnableLogcatLogs()));

final @NotNull SentryFeedbackOptions feedbackOptions = options.getFeedbackOptions();
feedbackOptions.setNameRequired(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ public final class SentryAndroidOptions extends SentryOptions {
/** Enable or disable automatic breadcrumbs for Network Events Using NetworkCallback */
private boolean enableNetworkEventBreadcrumbs = true;

/** Enable or disable automatic Sentry Logs capture from Timber. Default is disabled. */
private boolean enableTimberLogs = false;

/** Enable or disable automatic Sentry Logs capture from Logcat. Default is disabled. */
private boolean enableLogcatLogs = false;

/**
* Enables the Auto instrumentation for Activity lifecycle tracing.
*
Expand Down Expand Up @@ -505,6 +511,22 @@ public void setEnableNetworkEventBreadcrumbs(boolean enableNetworkEventBreadcrum
this.enableNetworkEventBreadcrumbs = enableNetworkEventBreadcrumbs;
}

public boolean isEnableTimberLogs() {
return enableTimberLogs;
}

public void setEnableTimberLogs(boolean enableTimberLogs) {
this.enableTimberLogs = enableTimberLogs;
}

public boolean isEnableLogcatLogs() {
return enableLogcatLogs;
}

public void setEnableLogcatLogs(boolean enableLogcatLogs) {
this.enableLogcatLogs = enableLogcatLogs;
}

/**
* Enable or disable all the automatic breadcrumbs
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.sentry.Sentry;
import io.sentry.SentryLevel;
import io.sentry.SentryLogLevel;
import io.sentry.SentryOptions;
import io.sentry.logger.SentryLogParameters;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -52,8 +53,9 @@ private static void addAsLog(
@Nullable final String msg,
@Nullable final Throwable tr) {
final @NotNull ScopesAdapter scopes = ScopesAdapter.getInstance();
// Check if logs are enabled before doing expensive operations
if (!scopes.getOptions().getLogs().isEnabled()) {
final @NotNull SentryOptions options = scopes.getOptions();
if (!(options instanceof SentryAndroidOptions)
|| !((SentryAndroidOptions) options).isEnableLogcatLogs()) {
return;
}
final @Nullable String trMessage = tr != null ? tr.getMessage() : null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package io.sentry.android.core

import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import io.sentry.ISentryClient
import io.sentry.SentryLogEvent
import io.sentry.SentryLogLevel
import io.sentry.SentryOptions
import io.sentry.protocol.SentryId
import io.sentry.test.ImmediateExecutorService
import io.sentry.test.getProperty
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Test
Expand All @@ -15,6 +18,7 @@ import kotlin.test.assertTrue
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

Expand Down Expand Up @@ -55,6 +59,16 @@ class AndroidLoggerBatchProcessorTest {
assertNotNull(AppState.getInstance().lifecycleObserver)
}

@Test
fun `onBackground does not flush before first accepted item`() {
val sut = fixture.getSut(useImmediateExecutor = true)

sut.onBackground()

assertThat(sut.getProperty<AtomicBoolean>("hasScheduled").get()).isFalse()
verify(fixture.client, never()).captureBatchedLogEvents(any())
}

@Test
fun `onBackground schedules flush`() {
val sut = fixture.getSut(useImmediateExecutor = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package io.sentry.android.core

import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import io.sentry.ISentryClient
import io.sentry.SentryMetricsEvent
import io.sentry.SentryOptions
import io.sentry.protocol.SentryId
import io.sentry.test.ImmediateExecutorService
import io.sentry.test.getProperty
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Test
Expand All @@ -14,6 +17,7 @@ import kotlin.test.assertTrue
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

Expand Down Expand Up @@ -54,6 +58,16 @@ class AndroidMetricsBatchProcessorTest {
assertNotNull(AppState.getInstance().lifecycleObserver)
}

@Test
fun `onBackground does not flush before first accepted item`() {
val sut = fixture.getSut(useImmediateExecutor = true)

sut.onBackground()

assertThat(sut.getProperty<AtomicBoolean>("hasScheduled").get()).isFalse()
verify(fixture.client, never()).captureBatchedMetricsEvents(any())
}

@Test
fun `onBackground schedules flush`() {
val sut = fixture.getSut(useImmediateExecutor = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -706,8 +706,21 @@ class AndroidOptionsInitializerTest {
fun `SentryTimberIntegration added to the integration list if available on classpath`() {
fixture.initSutWithClassLoader(isTimberAvailable = true)

val actual = fixture.sentryOptions.integrations.firstOrNull { it is SentryTimberIntegration }
assertNotNull(actual)
val actual =
fixture.sentryOptions.integrations.firstOrNull { it is SentryTimberIntegration }
as SentryTimberIntegration
assertFalse(actual.enableLogs)
}

@Test
fun `SentryTimberIntegration receives Timber logs option`() {
fixture.sentryOptions.isEnableTimberLogs = true
fixture.initSutWithClassLoader(isTimberAvailable = true)

val actual =
fixture.sentryOptions.integrations.firstOrNull { it is SentryTimberIntegration }
as SentryTimberIntegration
assertTrue(actual.enableLogs)
}

@Test
Expand Down
Loading