From 0a41b97f83bafbd1d1d2487e78c3e0c4be17d88d Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Thu, 13 Aug 2026 05:53:43 +0200 Subject: [PATCH] feat(core): Remove Metrics enable flag Capture manual Metrics without an aggregate option and always create the configured batch processor. Keep legacy external and Android keys only for subsequent migration warnings. Co-Authored-By: Claude --- CHANGELOG.md | 1 + .../android/core/ManifestMetadataReader.java | 5 --- .../core/ManifestMetadataReaderTest.kt | 39 +++++-------------- sentry/api/sentry.api | 2 - .../src/main/java/io/sentry/SentryClient.java | 9 +---- .../main/java/io/sentry/SentryOptions.java | 25 ------------ .../java/io/sentry/metrics/MetricsApi.java | 9 ----- sentry/src/test/java/io/sentry/ScopesTest.kt | 14 ++++--- .../test/java/io/sentry/SentryClientTest.kt | 7 ++++ .../test/java/io/sentry/SentryOptionsTest.kt | 14 ------- 10 files changed, 28 insertions(+), 97 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7acf5cc301..040701cbb5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### 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)) diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java b/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java index 2aa10e98abc..38ee0c1d347 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java @@ -729,11 +729,6 @@ static void applyMetadata( options.setEnableLogcatLogs( readBool(metadata, logger, ENABLE_LOGCAT_LOGS, options.isEnableLogcatLogs())); - options - .getMetrics() - .setEnabled( - readBool(metadata, logger, ENABLE_METRICS, options.getMetrics().isEnabled())); - final @NotNull SentryFeedbackOptions feedbackOptions = options.getFeedbackOptions(); feedbackOptions.setNameRequired( readBool(metadata, logger, FEEDBACK_NAME_REQUIRED, feedbackOptions.isNameRequired())); diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt index 6a0b17cff70..c2dfa7d544a 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt @@ -11,6 +11,8 @@ import io.sentry.ProfileLifecycle import io.sentry.SentryLevel import io.sentry.SentryReplayOptions import io.sentry.TransactionOptions +import io.sentry.test.createSentryClientMock +import io.sentry.test.createTestScopes import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals @@ -20,6 +22,7 @@ import kotlin.test.assertNull import kotlin.test.assertTrue import org.junit.runner.RunWith import org.mockito.kotlin.any +import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never @@ -2051,41 +2054,17 @@ class ManifestMetadataReaderTest { } @Test - fun `applyMetadata reads metrics enabled and keep default value if not found`() { - // Arrange - val context = fixture.getContext() - - // Act - ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider) - - // Assert - assertTrue(fixture.options.metrics.isEnabled) - } - - @Test - fun `applyMetadata reads metrics enabled to options`() { - // Arrange + fun `legacy metrics metadata does not disable capture`() { val bundle = bundleOf(ManifestMetadataReader.ENABLE_METRICS to false) val context = fixture.getContext(metaData = bundle) + val client = createSentryClientMock() - // Act ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider) + fixture.options.dsn = "https://key@sentry.io/proj" + val scopes = createTestScopes(fixture.options).also { it.bindClient(client) } + scopes.metrics().count("metric name") - // Assert - assertFalse(fixture.options.metrics.isEnabled) - } - - @Test - fun `applyMetadata reads metrics enabled to options when set to true`() { - // Arrange - val bundle = bundleOf(ManifestMetadataReader.ENABLE_METRICS to true) - val context = fixture.getContext(metaData = bundle) - - // Act - ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider) - - // Assert - assertTrue(fixture.options.metrics.isEnabled) + verify(client).captureMetric(any(), anyOrNull(), anyOrNull()) } @Test diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 4f3980b9f7d..5041ecf13f8 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -3976,9 +3976,7 @@ public final class io/sentry/SentryOptions$Metrics { public fun ()V public fun getBeforeSend ()Lio/sentry/SentryOptions$Metrics$BeforeSendMetricCallback; public fun getMetricsBatchProcessorFactory ()Lio/sentry/metrics/IMetricsBatchProcessorFactory; - public fun isEnabled ()Z public fun setBeforeSend (Lio/sentry/SentryOptions$Metrics$BeforeSendMetricCallback;)V - public fun setEnabled (Z)V public fun setMetricsBatchProcessorFactory (Lio/sentry/metrics/IMetricsBatchProcessorFactory;)V } diff --git a/sentry/src/main/java/io/sentry/SentryClient.java b/sentry/src/main/java/io/sentry/SentryClient.java index 04ef439ba6b..b17abf3b17f 100644 --- a/sentry/src/main/java/io/sentry/SentryClient.java +++ b/sentry/src/main/java/io/sentry/SentryClient.java @@ -10,7 +10,6 @@ import io.sentry.hints.TransactionEnd; import io.sentry.logger.ILoggerBatchProcessor; import io.sentry.metrics.IMetricsBatchProcessor; -import io.sentry.metrics.NoOpMetricsBatchProcessor; import io.sentry.protocol.Contexts; import io.sentry.protocol.DebugMeta; import io.sentry.protocol.FeatureFlags; @@ -62,12 +61,8 @@ public SentryClient(final @NotNull SentryOptions options) { final RequestDetailsResolver requestDetailsResolver = new RequestDetailsResolver(options); transport = transportFactory.create(options, requestDetailsResolver.resolve()); loggerBatchProcessor = options.getLogs().getLoggerBatchProcessorFactory().create(options, this); - if (options.getMetrics().isEnabled()) { - metricsBatchProcessor = - options.getMetrics().getMetricsBatchProcessorFactory().create(options, this); - } else { - metricsBatchProcessor = NoOpMetricsBatchProcessor.getInstance(); - } + metricsBatchProcessor = + options.getMetrics().getMetricsBatchProcessorFactory().create(options, this); } private boolean shouldApplyScopeData( diff --git a/sentry/src/main/java/io/sentry/SentryOptions.java b/sentry/src/main/java/io/sentry/SentryOptions.java index aa136d176aa..5394c22e2d2 100644 --- a/sentry/src/main/java/io/sentry/SentryOptions.java +++ b/sentry/src/main/java/io/sentry/SentryOptions.java @@ -3748,10 +3748,6 @@ public void merge(final @NotNull ExternalOptions options) { } } - if (options.isEnableMetrics() != null) { - getMetrics().setEnabled(options.isEnableMetrics()); - } - if (options.getProfileSessionSampleRate() != null) { setProfileSessionSampleRate(options.getProfileSessionSampleRate()); } @@ -4023,9 +4019,6 @@ public interface BeforeSendLogCallback { public static final class Metrics { - /** Whether Sentry Metrics feature is enabled and metrics are sent to Sentry. */ - private boolean enable = true; - /** * This function is called with a metric key and tags and can return false to skip sending the * metric @@ -4035,24 +4028,6 @@ public static final class Metrics { private @NotNull IMetricsBatchProcessorFactory metricsBatchProcessorFactory = new DefaultMetricsBatchProcessorFactory(); - /** - * Whether Sentry Metrics feature is enabled and metrics are sent to Sentry. - * - * @return true if Sentry Metrics should be enabled - */ - public boolean isEnabled() { - return enable; - } - - /** - * Whether Sentry Metrics feature is enabled and metrics are sent to Sentry. - * - * @param enableMetrics true if Sentry Metrics should be enabled - */ - public void setEnabled(final boolean enableMetrics) { - this.enable = enableMetrics; - } - /** * Returns the BeforeSendMetric callback * diff --git a/sentry/src/main/java/io/sentry/metrics/MetricsApi.java b/sentry/src/main/java/io/sentry/metrics/MetricsApi.java index cebcad9735c..d70b4ab5c97 100644 --- a/sentry/src/main/java/io/sentry/metrics/MetricsApi.java +++ b/sentry/src/main/java/io/sentry/metrics/MetricsApi.java @@ -118,15 +118,6 @@ private void captureMetrics( return; } - if (!options.getMetrics().isEnabled()) { - options - .getLogger() - .log( - SentryLevel.WARNING, - "Sentry Metrics is disabled and this 'metrics' call is a no-op."); - return; - } - if (name == null) { return; } diff --git a/sentry/src/test/java/io/sentry/ScopesTest.kt b/sentry/src/test/java/io/sentry/ScopesTest.kt index 9e44c9ae847..980e89353c6 100644 --- a/sentry/src/test/java/io/sentry/ScopesTest.kt +++ b/sentry/src/test/java/io/sentry/ScopesTest.kt @@ -3290,11 +3290,15 @@ class ScopesTest { } @Test - fun `when metrics is not enabled, do nothing`() { - val (sut, mockClient) = getEnabledScopes { it.metrics.isEnabled = false } + fun `legacy external metrics configuration does not disable capture`() { + val (sut, mockClient) = + getEnabledScopes { options -> + options.merge(ExternalOptions().also { it.isEnableMetrics = false }) + } sut.metrics().count("metric name") - verify(mockClient, never()).captureMetric(any(), anyOrNull(), anyOrNull()) + + verify(mockClient).captureMetric(any(), anyOrNull(), anyOrNull()) } @Test @@ -4226,7 +4230,7 @@ class ScopesTest { @Test fun `metric event has spanId from active span`() { - val (sut, mockClient) = getEnabledScopes { it.metrics.isEnabled = true } + val (sut, mockClient) = getEnabledScopes() val transaction = sut.startTransaction( @@ -4253,7 +4257,7 @@ class ScopesTest { @Test fun `metric event has spanId from propagation context when no active span`() { - val (sut, mockClient) = getEnabledScopes { it.metrics.isEnabled = true } + val (sut, mockClient) = getEnabledScopes() var propagationContext: PropagationContext? = null sut.configureScope { propagationContext = it.propagationContext } diff --git a/sentry/src/test/java/io/sentry/SentryClientTest.kt b/sentry/src/test/java/io/sentry/SentryClientTest.kt index 008597b428e..6376a216b98 100644 --- a/sentry/src/test/java/io/sentry/SentryClientTest.kt +++ b/sentry/src/test/java/io/sentry/SentryClientTest.kt @@ -153,6 +153,13 @@ class SentryClientTest { assertTrue(sut.isEnabled) } + @Test + fun `when client is created, metrics batch processor is created`() { + val sut = fixture.getSut() + + verify(fixture.metricsBatchProcessorFactory).create(fixture.sentryOptions, sut) + } + @Test fun `when dsn is an invalid string, client throws`() { fixture.sentryOptions.dsn = "invalid-dsn" diff --git a/sentry/src/test/java/io/sentry/SentryOptionsTest.kt b/sentry/src/test/java/io/sentry/SentryOptionsTest.kt index 17546c62136..d56cbeb41ac 100644 --- a/sentry/src/test/java/io/sentry/SentryOptionsTest.kt +++ b/sentry/src/test/java/io/sentry/SentryOptionsTest.kt @@ -485,7 +485,6 @@ class SentryOptionsTest { assertTrue(options.isEnableSpotlight) assertEquals("http://local.sentry.io:1234", options.spotlightConnectionUrl) assertTrue(options.isGlobalHubMode!!) - assertFalse(options.metrics.isEnabled) assertEquals(0.8, options.profileSessionSampleRate) assertEquals("/profiling-traces${File.separator}${hash}", options.profilingTracesDirPath) assertEquals(ProfileLifecycle.TRACE, options.profileLifecycle) @@ -499,14 +498,6 @@ class SentryOptionsTest { assertTrue(options.isEnableUncaughtExceptionHandler) } - @Test - fun `merging options when enableMetrics is not set preserves the default value`() { - val externalOptions = ExternalOptions() - val options = SentryOptions() - options.merge(externalOptions) - assertTrue(options.metrics.isEnabled) - } - @Test fun `merging options does not warn when legacy logs configuration is absent`() { val logger = mock() @@ -804,11 +795,6 @@ class SentryOptionsTest { assertFalse(SentryOptions().isEnableQueueTracing) } - @Test - fun `when options are initialized, metrics is enabled by default`() { - assertTrue(SentryOptions().metrics.isEnabled) - } - @Test fun `when options are initialized, enableSpotlight is set to false by default`() { assertFalse(SentryOptions().isEnableSpotlight)