Skip to content

Commit 2091db3

Browse files
Add callback to record the type and amount of data discarded before reaching Sentry (#4612)
* Add callback to record the type and amount of data discarded before reaching Sentry * Remove empty test file * Use long variable in sample usage of onDiscard * Wrap onDiscard callback in a try-catch and fix docstring * Reference pull request instead of issue in the changelog * Remove Internal annotation from DiscardReason and DataCategory, update signature of onDiscard callback, and avoid duplicate invocation * Format code * Add stub for using onDiscard to the changelog * Switch samples to use enums instead of strings and lint * Move feature out of release that appeared by merging main in the changelog --------- Co-authored-by: Sentry Github Bot <[email protected]>
1 parent fc58aeb commit 2091db3

File tree

18 files changed

+314
-14
lines changed

18 files changed

+314
-14
lines changed

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Features
6+
7+
- Add onDiscard to enable users to track the type and amount of data discarded before reaching Sentry ([#4612](https://github.com/getsentry/sentry-java/pull/4612))
8+
- Stub for setting the callback on `Sentry.init`:
9+
```java
10+
Sentry.init(options -> {
11+
...
12+
options.setOnDiscard(
13+
(reason, category, number) -> {
14+
// Your logic to process discarded data
15+
});
16+
});
17+
```
18+
319
## 8.19.1
420

521
### Fixes

sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
11
package io.sentry.samples.console;
22

3-
import io.sentry.Breadcrumb;
4-
import io.sentry.EventProcessor;
5-
import io.sentry.Hint;
6-
import io.sentry.ISpan;
7-
import io.sentry.ITransaction;
8-
import io.sentry.Sentry;
9-
import io.sentry.SentryEvent;
10-
import io.sentry.SentryLevel;
11-
import io.sentry.SpanStatus;
3+
import io.sentry.*;
4+
import io.sentry.clientreport.DiscardReason;
125
import io.sentry.protocol.Message;
136
import io.sentry.protocol.User;
147
import java.util.Collections;
158

169
public class Main {
1710

11+
private static long numberOfDiscardedSpansDueToOverflow = 0;
12+
1813
public static void main(String[] args) throws InterruptedException {
1914
Sentry.init(
2015
options -> {
@@ -59,6 +54,18 @@ public static void main(String[] args) throws InterruptedException {
5954
return breadcrumb;
6055
});
6156

57+
// Record data being discarded, including the reason, type of data, and the number of
58+
// items dropped
59+
options.setOnDiscard(
60+
(reason, category, number) -> {
61+
// Only record the number of lost spans due to overflow conditions
62+
if ((reason.equals(DiscardReason.CACHE_OVERFLOW)
63+
|| reason.equals(DiscardReason.QUEUE_OVERFLOW))
64+
&& category.equals(DataCategory.Span)) {
65+
numberOfDiscardedSpansDueToOverflow += number;
66+
}
67+
});
68+
6269
// Configure the background worker which sends events to sentry:
6370
// Wait up to 5 seconds before shutdown while there are events to send.
6471
options.setShutdownTimeoutMillis(5000);

sentry-samples/sentry-samples-servlet/src/main/java/io/sentry/samples/servlet/SentryInitializer.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package io.sentry.samples.servlet;
22

3+
import io.sentry.DataCategory;
34
import io.sentry.Sentry;
5+
import io.sentry.clientreport.DiscardReason;
46
import javax.servlet.ServletContextEvent;
57
import javax.servlet.ServletContextListener;
68
import javax.servlet.annotation.WebListener;
@@ -9,6 +11,8 @@
911
@WebListener
1012
public final class SentryInitializer implements ServletContextListener {
1113

14+
private static long numberOfDiscardedSpansDueToOverflow = 0;
15+
1216
@Override
1317
public void contextInitialized(ServletContextEvent sce) {
1418
Sentry.init(
@@ -57,6 +61,18 @@ public void contextInitialized(ServletContextEvent sce) {
5761
return breadcrumb;
5862
});
5963

64+
// Record data being discarded, including the reason, type of data, and the number of
65+
// items dropped
66+
options.setOnDiscard(
67+
(reason, category, number) -> {
68+
// Only record the number of lost spans due to overflow conditions
69+
if ((reason.equals(DiscardReason.CACHE_OVERFLOW)
70+
|| reason.equals(DiscardReason.QUEUE_OVERFLOW))
71+
&& category.equals(DataCategory.Span)) {
72+
numberOfDiscardedSpansDueToOverflow += number;
73+
}
74+
});
75+
6076
// Configure the background worker which sends events to sentry:
6177
// Wait up to 5 seconds before shutdown while there are events to send.
6278
options.setShutdownTimeoutMillis(5000);

sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryAutoConfiguration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ static class HubConfiguration {
107107
beforeSendLogsCallback,
108108
final @NotNull ObjectProvider<SentryOptions.BeforeBreadcrumbCallback>
109109
beforeBreadcrumbCallback,
110+
final @NotNull ObjectProvider<SentryOptions.OnDiscardCallback> onDiscardCallback,
110111
final @NotNull ObjectProvider<SentryOptions.TracesSamplerCallback> tracesSamplerCallback,
111112
final @NotNull List<EventProcessor> eventProcessors,
112113
final @NotNull List<Integration> integrations,
@@ -118,6 +119,7 @@ static class HubConfiguration {
118119
beforeSendTransactionCallback.ifAvailable(options::setBeforeSendTransaction);
119120
beforeSendLogsCallback.ifAvailable(callback -> options.getLogs().setBeforeSend(callback));
120121
beforeBreadcrumbCallback.ifAvailable(options::setBeforeBreadcrumb);
122+
onDiscardCallback.ifAvailable(options::setOnDiscard);
121123
tracesSamplerCallback.ifAvailable(options::setTracesSampler);
122124
eventProcessors.forEach(options::addEventProcessor);
123125
integrations.forEach(options::addIntegration);

sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.acme.MainBootClass
44
import io.opentelemetry.api.OpenTelemetry
55
import io.sentry.AsyncHttpTransportFactory
66
import io.sentry.Breadcrumb
7+
import io.sentry.DataCategory
78
import io.sentry.EventProcessor
89
import io.sentry.FilterString
910
import io.sentry.Hint
@@ -19,6 +20,7 @@ import io.sentry.SentryLevel
1920
import io.sentry.SentryLogEvent
2021
import io.sentry.SentryOptions
2122
import io.sentry.checkEvent
23+
import io.sentry.clientreport.DiscardReason
2224
import io.sentry.opentelemetry.SentryAutoConfigurationCustomizerProvider
2325
import io.sentry.opentelemetry.agent.AgentMarker
2426
import io.sentry.protocol.SentryTransaction
@@ -373,6 +375,17 @@ class SentryAutoConfigurationTest {
373375
}
374376
}
375377

378+
@Test
379+
fun `registers onDiscardCallback on SentryOptions`() {
380+
contextRunner
381+
.withPropertyValues("sentry.dsn=http://key@localhost/proj")
382+
.withUserConfiguration(CustomOnDiscardCallbackConfiguration::class.java)
383+
.run {
384+
assertThat(it.getBean(SentryOptions::class.java).onDiscard)
385+
.isInstanceOf(CustomOnDiscardCallback::class.java)
386+
}
387+
}
388+
376389
@Test
377390
fun `registers event processor on SentryOptions`() {
378391
contextRunner
@@ -1137,6 +1150,16 @@ class SentryAutoConfigurationTest {
11371150
override fun execute(breadcrumb: Breadcrumb, hint: Hint): Breadcrumb? = null
11381151
}
11391152

1153+
@Configuration(proxyBeanMethods = false)
1154+
open class CustomOnDiscardCallbackConfiguration {
1155+
1156+
@Bean open fun onDiscardCallback() = CustomOnDiscardCallback()
1157+
}
1158+
1159+
class CustomOnDiscardCallback : SentryOptions.OnDiscardCallback {
1160+
override fun execute(reason: DiscardReason, category: DataCategory, countToAdd: Long) {}
1161+
}
1162+
11401163
@Configuration(proxyBeanMethods = false)
11411164
open class CustomEventProcessorConfiguration {
11421165

sentry-spring-boot/src/main/java/io/sentry/spring/boot/SentryAutoConfiguration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ static class HubConfiguration {
105105
beforeSendLogsCallback,
106106
final @NotNull ObjectProvider<SentryOptions.BeforeBreadcrumbCallback>
107107
beforeBreadcrumbCallback,
108+
final @NotNull ObjectProvider<SentryOptions.OnDiscardCallback> onDiscardCallback,
108109
final @NotNull ObjectProvider<SentryOptions.TracesSamplerCallback> tracesSamplerCallback,
109110
final @NotNull List<EventProcessor> eventProcessors,
110111
final @NotNull List<Integration> integrations,
@@ -116,6 +117,7 @@ static class HubConfiguration {
116117
beforeSendTransactionCallback.ifAvailable(options::setBeforeSendTransaction);
117118
beforeSendLogsCallback.ifAvailable(callback -> options.getLogs().setBeforeSend(callback));
118119
beforeBreadcrumbCallback.ifAvailable(options::setBeforeBreadcrumb);
120+
onDiscardCallback.ifAvailable(options::setOnDiscard);
119121
tracesSamplerCallback.ifAvailable(options::setTracesSampler);
120122
eventProcessors.forEach(options::addEventProcessor);
121123
integrations.forEach(options::addIntegration);

sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.acme.MainBootClass
44
import io.opentelemetry.api.OpenTelemetry
55
import io.sentry.AsyncHttpTransportFactory
66
import io.sentry.Breadcrumb
7+
import io.sentry.DataCategory
78
import io.sentry.EventProcessor
89
import io.sentry.FilterString
910
import io.sentry.Hint
@@ -19,6 +20,7 @@ import io.sentry.SentryLevel
1920
import io.sentry.SentryLogEvent
2021
import io.sentry.SentryOptions
2122
import io.sentry.checkEvent
23+
import io.sentry.clientreport.DiscardReason
2224
import io.sentry.opentelemetry.SentryAutoConfigurationCustomizerProvider
2325
import io.sentry.opentelemetry.agent.AgentMarker
2426
import io.sentry.protocol.SentryTransaction
@@ -372,6 +374,17 @@ class SentryAutoConfigurationTest {
372374
}
373375
}
374376

377+
@Test
378+
fun `registers onDiscardCallback on SentryOptions`() {
379+
contextRunner
380+
.withPropertyValues("sentry.dsn=http://key@localhost/proj")
381+
.withUserConfiguration(CustomOnDiscardCallbackConfiguration::class.java)
382+
.run {
383+
assertThat(it.getBean(SentryOptions::class.java).onDiscard)
384+
.isInstanceOf(CustomOnDiscardCallback::class.java)
385+
}
386+
}
387+
375388
@Test
376389
fun `registers event processor on SentryOptions`() {
377390
contextRunner
@@ -1063,6 +1076,16 @@ class SentryAutoConfigurationTest {
10631076
override fun execute(breadcrumb: Breadcrumb, hint: Hint): Breadcrumb? = null
10641077
}
10651078

1079+
@Configuration(proxyBeanMethods = false)
1080+
open class CustomOnDiscardCallbackConfiguration {
1081+
1082+
@Bean open fun onDiscardCallback() = CustomOnDiscardCallback()
1083+
}
1084+
1085+
class CustomOnDiscardCallback : SentryOptions.OnDiscardCallback {
1086+
override fun execute(reason: DiscardReason, category: DataCategory, countToAdd: Long) {}
1087+
}
1088+
10661089
@Configuration(proxyBeanMethods = false)
10671090
open class CustomEventProcessorConfiguration {
10681091

sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ public SentryInitBeanPostProcessor() {
6161
applicationContext
6262
.getBeanProvider(SentryOptions.BeforeBreadcrumbCallback.class)
6363
.ifAvailable(options::setBeforeBreadcrumb);
64+
applicationContext
65+
.getBeanProvider(SentryOptions.OnDiscardCallback.class)
66+
.ifAvailable(options::setOnDiscard);
6467
applicationContext
6568
.getBeansOfType(EventProcessor.class)
6669
.values()

sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/EnableSentryTest.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ class EnableSentryTest {
223223
@Bean fun beforeBreadcrumbCallback() = mock<SentryOptions.BeforeBreadcrumbCallback>()
224224
}
225225

226+
@EnableSentry(dsn = "http://key@localhost/proj")
227+
class AppConfigWithCustomOnDiscardCallback {
228+
@Bean fun onDiscardCallback() = mock<SentryOptions.OnDiscardCallback>()
229+
}
230+
226231
@EnableSentry(dsn = "http://key@localhost/proj")
227232
class AppConfigWithCustomEventProcessors {
228233
@Bean fun firstProcessor() = mock<EventProcessor>()

sentry-spring/src/main/java/io/sentry/spring/SentryInitBeanPostProcessor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ public SentryInitBeanPostProcessor() {
6161
applicationContext
6262
.getBeanProvider(SentryOptions.BeforeBreadcrumbCallback.class)
6363
.ifAvailable(options::setBeforeBreadcrumb);
64+
applicationContext
65+
.getBeanProvider(SentryOptions.OnDiscardCallback.class)
66+
.ifAvailable(options::setOnDiscard);
6467
applicationContext
6568
.getBeansOfType(EventProcessor.class)
6669
.values()

0 commit comments

Comments
 (0)