Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d8b77e7
fix(core): Make enable-flag warnings visible
adinauer Aug 13, 2026
8eeaffb
ref(logging): Rename Logs opt-ins
adinauer Aug 14, 2026
c77cc48
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
28e36f7
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
498279d
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
6ed8b5a
chore(stack): Merge preceding stack changes
adinauer Sep 29, 2026
6bdb01e
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
8a28b66
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
672bb4a
test(logback): Use renamed Logs option
adinauer Sep 30, 2026
84c81d5
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
9182ef3
fix(spring): Use renamed Logs option in Log4j2 wiring
adinauer Sep 30, 2026
fcf586d
chore(stack): Merge preceding stack changes
adinauer Sep 30, 2026
10c76e2
test(jul): Use renamed Logs option in regression test
adinauer Sep 30, 2026
7ce04f5
chore(stack): Merge preceding stack changes
adinauer Oct 1, 2026
9bb89b8
ref(android): Clarify automatic log capture option names
adinauer Oct 1, 2026
599bc3e
ref(logging)!: Add opt-in flags to existing constructors
adinauer Oct 1, 2026
e1d35f2
chore(stack): Merge preceding stack changes
adinauer Oct 1, 2026
5bf5511
fix(samples): Use Spring logging Logs option
adinauer Oct 2, 2026
215754d
docs(changelog): Clarify Logs and Metrics migration
adinauer Oct 2, 2026
ba9bccc
ref(timber)!: Require explicit Logs opt-in
adinauer Oct 2, 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
18 changes: 9 additions & 9 deletions .cursor/rules/options.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Allows setting options via `AndroidManifest.xml` `<meta-data>` tags.
- Add a `static final String` constant for the key
- Read it in `applyMetadata()` using `readBool(metadata, logger, CONSTANT, defaultValue)`
- Apply automatic-source options directly, for example
`options.setEnableLogcatLogs(...)` for `io.sentry.logcat.logs.enabled`
`options.setLogcatLogCaptureEnabled(...)` 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.

Expand All @@ -89,8 +89,8 @@ Allows setting options via `AndroidManifest.xml` `<meta-data>` tags.

`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
namespace instead. For example, `SentryProperties.Logging.logsEnabled` binds to
`sentry.logging.logs-enabled` and controls Logs forwarding from the auto-configured Logback
appender. `sentry.logging.enabled` separately controls whether that appender is installed.

Do not add or restore `sentry.logs.enabled` or `sentry.metrics.enabled`; those aggregate properties
Expand All @@ -110,12 +110,12 @@ They capture whenever their scopes are enabled, then apply signal behavior such

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`
- Logback: appender `logsEnabled`
- Log4j2: appender `logsEnabled`
- JUL: handler `logsEnabled`
- Spring Boot Logback: `sentry.logging.logs-enabled`
- Timber: `timberLogCaptureEnabled` / `io.sentry.timber.logs.enabled`
- Logcat: `logcatLogCaptureEnabled` / `io.sentry.logcat.logs.enabled`

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

Expand Down
28 changes: 26 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,34 @@

## Unreleased

### Breaking Changes

- Add a `logsEnabled` argument to the preferred Log4j2 `SentryAppender` constructor and
`createAppender` factory. Pass `true` to opt in to Sentry Logs capture or `false` to keep it
disabled. ([#5941](https://github.com/getsentry/sentry-java/pull/5941))
- Require a `logsEnabled` argument when manually constructing `SentryTimberIntegration` or
`SentryTimberTree`. Replace `SentryTimberIntegration()` with
`SentryTimberIntegration(logsEnabled = false)` in Kotlin or `new SentryTimberIntegration(false)`
in Java to keep Sentry Logs disabled. ([#5943](https://github.com/getsentry/sentry-java/pull/5943))
- Remove the obsolete aggregate Sentry Metrics options `metrics.enabled` and
`options.getMetrics().setEnabled(...)`. Direct `Sentry.metrics()` calls continue to capture
Metrics whenever the SDK is enabled. ([#5953](https://github.com/getsentry/sentry-java/pull/5953))
- Remove the obsolete aggregate Sentry Logs options `logs.enabled` and
`options.getLogs().setEnabled(...)`. ([#5947](https://github.com/getsentry/sentry-java/pull/5947))
Direct `Sentry.logger()` calls continue to capture Logs whenever the SDK is enabled. Sentry Logs
capture is disabled by default for every automatic logging integration. Set the applicable
integration-specific option to `true` to opt in:
- Logback appender: `logsEnabled`
- Log4j2 appender: `logsEnabled`
- JUL handler: `io.sentry.jul.SentryHandler.logsEnabled`
- Spring Boot logging auto-configuration: `sentry.logging.logs-enabled`
- Auto-installed Timber integration: `timberLogCaptureEnabled` or
`io.sentry.timber.logs.enabled` manifest metadata
- Manually installed Timber integration: `logsEnabled` constructor argument
- Logcat: `logcatLogCaptureEnabled` or `io.sentry.logcat.logs.enabled` manifest metadata

### 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))
Expand Down
8 changes: 4 additions & 4 deletions sentry-android-core/api/sentry-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -429,12 +429,14 @@ public final class io/sentry/android/core/SentryAndroidOptions : io/sentry/Sentr
public fun getBeforeViewHierarchyCaptureCallback ()Lio/sentry/android/core/SentryAndroidOptions$BeforeCaptureCallback;
public fun getDebugImagesLoader ()Lio/sentry/android/core/IDebugImagesLoader;
public fun getFrameMetricsCollector ()Lio/sentry/android/core/internal/util/SentryFrameMetricsCollector;
public fun getLogcatLogCaptureEnabled ()Z
public fun getMonotonicTicker ()Lio/sentry/time/MonotonicTicker;
public fun getNativeSdkName ()Ljava/lang/String;
public fun getNdkAppHangTimeoutIntervalMillis ()J
public fun getNdkHandlerStrategy ()I
public fun getScreenshot ()Lio/sentry/android/core/SentryScreenshotOptions;
public fun getStartupCrashDurationThresholdMillis ()J
public fun getTimberLogCaptureEnabled ()Z
public fun getTombstoneMergeTimeThresholdMillis ()J
public fun isAnrEnabled ()Z
public fun isAnrProfilingEnabled ()Z
Expand All @@ -453,7 +455,6 @@ 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 @@ -463,7 +464,6 @@ 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 @@ -490,7 +490,6 @@ 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 @@ -500,15 +499,16 @@ 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 setLogcatLogCaptureEnabled (Z)V
public fun setMemoryLimiterEnabled (Z)V
public fun setNativeHandlerStrategy (Lio/sentry/android/core/NdkHandlerStrategy;)V
public fun setNativeSdkName (Ljava/lang/String;)V
public fun setNdkAppHangTimeoutIntervalMillis (J)V
public fun setReportHistoricalAnrs (Z)V
public fun setReportHistoricalMemoryLimiterExits (Z)V
public fun setReportHistoricalTombstones (Z)V
public fun setTimberLogCaptureEnabled (Z)V
public fun setTombstoneEnabled (Z)V
public fun setTombstoneMergeTimeThresholdMillis (J)V
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,8 @@ static void installDefaultIntegrations(
}

if (isTimberAvailable) {
options.addIntegration(new SentryTimberIntegration(() -> options.isEnableTimberLogs()));
options.addIntegration(
new SentryTimberIntegration(() -> options.getTimberLogCaptureEnabled()));
}
options.addIntegration(new AppComponentsBreadcrumbsIntegration(context));
options.addIntegration(new SystemEventsBreadcrumbsIntegration(context));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -750,11 +750,11 @@ static void applyMetadata(
}
}

options.setEnableTimberLogs(
readBool(metadata, logger, ENABLE_TIMBER_LOGS, options.isEnableTimberLogs()));
options.setTimberLogCaptureEnabled(
readBool(metadata, logger, ENABLE_TIMBER_LOGS, options.getTimberLogCaptureEnabled()));

options.setEnableLogcatLogs(
readBool(metadata, logger, ENABLE_LOGCAT_LOGS, options.isEnableLogcatLogs()));
options.setLogcatLogCaptureEnabled(
readBool(metadata, logger, ENABLE_LOGCAT_LOGS, options.getLogcatLogCaptureEnabled()));

final @NotNull SentryFeedbackOptions feedbackOptions = options.getFeedbackOptions();
feedbackOptions.setNameRequired(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ public final class SentryAndroidOptions extends SentryOptions {
private boolean enableNetworkEventBreadcrumbs = true;

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

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

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

public boolean isEnableTimberLogs() {
return enableTimberLogs;
public boolean getTimberLogCaptureEnabled() {
return timberLogCaptureEnabled;
}

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

public boolean isEnableLogcatLogs() {
return enableLogcatLogs;
public boolean getLogcatLogCaptureEnabled() {
return logcatLogCaptureEnabled;
}

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

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ private static void addAsLog(
final @NotNull ScopesAdapter scopes = ScopesAdapter.getInstance();
final @NotNull SentryOptions options = scopes.getOptions();
if (!(options instanceof SentryAndroidOptions)
|| !((SentryAndroidOptions) options).isEnableLogcatLogs()) {
|| !((SentryAndroidOptions) options).getLogcatLogCaptureEnabled()) {
return;
}
final @Nullable String trMessage = tr != null ? tr.getMessage() : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -709,18 +709,18 @@ class AndroidOptionsInitializerTest {
val actual =
fixture.sentryOptions.integrations.firstOrNull { it is SentryTimberIntegration }
as SentryTimberIntegration
assertFalse(actual.enableLogs)
assertFalse(actual.logsEnabled)
}

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

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

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2176,52 +2176,52 @@ class ManifestMetadataReaderTest {
}

@Test
fun `applyMetadata keeps Timber logs disabled if not found`() {
fun `applyMetadata keeps Timber log capture disabled if not found`() {
val context = fixture.getContext()

ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)

assertFalse(fixture.options.isEnableTimberLogs)
assertFalse(fixture.options.timberLogCaptureEnabled)
}

@Test
fun `applyMetadata reads Timber logs enabled to options`() {
fun `applyMetadata reads Timber log capture enabled to options`() {
val bundle = bundleOf(ManifestMetadataReader.ENABLE_TIMBER_LOGS to true)
val context = fixture.getContext(metaData = bundle)

ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)

assertTrue(fixture.options.isEnableTimberLogs)
assertTrue(fixture.options.timberLogCaptureEnabled)
}

@Test
fun `applyMetadata keeps Logcat logs disabled if not found`() {
fun `applyMetadata keeps Logcat log capture disabled if not found`() {
val context = fixture.getContext()

ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)

assertThat(fixture.options.isEnableLogcatLogs).isFalse()
assertThat(fixture.options.logcatLogCaptureEnabled).isFalse()
}

@Test
fun `applyMetadata reads Logcat logs enabled to options`() {
fun `applyMetadata reads Logcat log capture enabled to options`() {
val bundle = bundleOf(ManifestMetadataReader.ENABLE_LOGCAT_LOGS to true)
val context = fixture.getContext(metaData = bundle)

ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)

assertThat(fixture.options.isEnableLogcatLogs).isTrue()
assertThat(fixture.options.logcatLogCaptureEnabled).isTrue()
}

@Test
fun `applyMetadata reads Logcat logs disabled to options`() {
fixture.options.isEnableLogcatLogs = true
fun `applyMetadata reads Logcat log capture disabled to options`() {
fixture.options.logcatLogCaptureEnabled = true
val bundle = bundleOf(ManifestMetadataReader.ENABLE_LOGCAT_LOGS to false)
val context = fixture.getContext(metaData = bundle)

ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)

assertThat(fixture.options.isEnableLogcatLogs).isFalse()
assertThat(fixture.options.logcatLogCaptureEnabled).isFalse()
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,31 +95,31 @@ class SentryAndroidOptionsTest {
}

@Test
fun `Timber logs are disabled by default`() {
fun `Timber log capture is disabled by default`() {
val sentryOptions = SentryAndroidOptions()

assertFalse(sentryOptions.isEnableTimberLogs)
assertFalse(sentryOptions.timberLogCaptureEnabled)
}

@Test
fun `Timber logs can be enabled`() {
fun `Timber log capture can be enabled`() {
val sentryOptions = SentryAndroidOptions()
sentryOptions.isEnableTimberLogs = true
sentryOptions.timberLogCaptureEnabled = true

assertTrue(sentryOptions.isEnableTimberLogs)
assertTrue(sentryOptions.timberLogCaptureEnabled)
}

@Test
fun `Logcat logs are disabled by default`() {
assertThat(SentryAndroidOptions().isEnableLogcatLogs).isFalse()
fun `Logcat log capture is disabled by default`() {
assertThat(SentryAndroidOptions().logcatLogCaptureEnabled).isFalse()
}

@Test
fun `Logcat logs can be enabled`() {
fun `Logcat log capture can be enabled`() {
val sentryOptions = SentryAndroidOptions()
sentryOptions.isEnableLogcatLogs = true
sentryOptions.logcatLogCaptureEnabled = true

assertThat(sentryOptions.isEnableLogcatLogs).isTrue()
assertThat(sentryOptions.logcatLogCaptureEnabled).isTrue()
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,10 @@ class SentryAndroidTest {
}

@Test
fun `auto-installed Timber integration uses Logs option set in configuration callback`() {
fun `auto-installed Timber integration uses log capture option set in configuration callback`() {
val logs = mutableListOf<SentryLogEvent>()
fixture.initSut { options ->
options.isEnableTimberLogs = true
options.timberLogCaptureEnabled = true
options.logs.beforeSend =
SentryOptions.Logs.BeforeSendLogCallback { log ->
logs.add(log)
Expand All @@ -268,7 +268,7 @@ class SentryAndroidTest {
val logs = mutableListOf<SentryLogEvent>()

initForTest(mockContext) { options ->
options.isEnableTimberLogs = false
options.timberLogCaptureEnabled = false
options.logs.beforeSend =
SentryOptions.Logs.BeforeSendLogCallback { log ->
logs.add(log)
Expand All @@ -286,7 +286,13 @@ class SentryAndroidTest {
fixture.initSut(autoInit = true) {
it.addIntegration(FragmentLifecycleIntegration(ApplicationProvider.getApplicationContext()))

it.addIntegration(SentryTimberIntegration(minEventLevel = FATAL, minBreadcrumbLevel = DEBUG))
it.addIntegration(
SentryTimberIntegration(
minEventLevel = FATAL,
minBreadcrumbLevel = DEBUG,
logsEnabled = false,
)
)

it.addIntegration(
SystemEventsBreadcrumbsIntegration(
Expand Down
Loading
Loading