Skip to content

Commit 6c5011f

Browse files
committed
Detect oversized events
1 parent 3bd2cf0 commit 6c5011f

File tree

11 files changed

+918
-4
lines changed

11 files changed

+918
-4
lines changed

sentry/api/sentry.api

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ public final class io/sentry/DataCategory : java/lang/Enum {
347347
public static final field Default Lio/sentry/DataCategory;
348348
public static final field Error Lio/sentry/DataCategory;
349349
public static final field Feedback Lio/sentry/DataCategory;
350+
public static final field LogByte Lio/sentry/DataCategory;
350351
public static final field LogItem Lio/sentry/DataCategory;
351352
public static final field Monitor Lio/sentry/DataCategory;
352353
public static final field Profile Lio/sentry/DataCategory;
@@ -3384,6 +3385,7 @@ public class io/sentry/SentryOptions {
33843385
public fun getMaxTraceFileSize ()J
33853386
public fun getModulesLoader ()Lio/sentry/internal/modules/IModulesLoader;
33863387
public fun getOnDiscard ()Lio/sentry/SentryOptions$OnDiscardCallback;
3388+
public fun getOnOversizedError ()Lio/sentry/SentryOptions$OnOversizedErrorCallback;
33873389
public fun getOpenTelemetryMode ()Lio/sentry/SentryOpenTelemetryMode;
33883390
public fun getOptionsObservers ()Ljava/util/List;
33893391
public fun getOutboxPath ()Ljava/lang/String;
@@ -3434,6 +3436,7 @@ public class io/sentry/SentryOptions {
34343436
public fun isEnableAutoSessionTracking ()Z
34353437
public fun isEnableBackpressureHandling ()Z
34363438
public fun isEnableDeduplication ()Z
3439+
public fun isEnableEventSizeLimiting ()Z
34373440
public fun isEnableExternalConfiguration ()Z
34383441
public fun isEnablePrettySerializationOutput ()Z
34393442
public fun isEnableScopePersistence ()Z
@@ -3490,6 +3493,7 @@ public class io/sentry/SentryOptions {
34903493
public fun setEnableAutoSessionTracking (Z)V
34913494
public fun setEnableBackpressureHandling (Z)V
34923495
public fun setEnableDeduplication (Z)V
3496+
public fun setEnableEventSizeLimiting (Z)V
34933497
public fun setEnableExternalConfiguration (Z)V
34943498
public fun setEnablePrettySerializationOutput (Z)V
34953499
public fun setEnableScopePersistence (Z)V
@@ -3531,6 +3535,7 @@ public class io/sentry/SentryOptions {
35313535
public fun setMaxTraceFileSize (J)V
35323536
public fun setModulesLoader (Lio/sentry/internal/modules/IModulesLoader;)V
35333537
public fun setOnDiscard (Lio/sentry/SentryOptions$OnDiscardCallback;)V
3538+
public fun setOnOversizedError (Lio/sentry/SentryOptions$OnOversizedErrorCallback;)V
35343539
public fun setOpenTelemetryMode (Lio/sentry/SentryOpenTelemetryMode;)V
35353540
public fun setPrintUncaughtStackTrace (Z)V
35363541
public fun setProfileLifecycle (Lio/sentry/ProfileLifecycle;)V
@@ -3640,6 +3645,10 @@ public abstract interface class io/sentry/SentryOptions$OnDiscardCallback {
36403645
public abstract fun execute (Lio/sentry/clientreport/DiscardReason;Lio/sentry/DataCategory;Ljava/lang/Long;)V
36413646
}
36423647

3648+
public abstract interface class io/sentry/SentryOptions$OnOversizedErrorCallback {
3649+
public abstract fun execute (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent;
3650+
}
3651+
36433652
public abstract interface class io/sentry/SentryOptions$ProfilesSamplerCallback {
36443653
public abstract fun sample (Lio/sentry/SamplingContext;)Ljava/lang/Double;
36453654
}
@@ -6996,6 +7005,10 @@ public final class io/sentry/util/EventProcessorUtils {
69967005
public static fun unwrap (Ljava/util/List;)Ljava/util/List;
69977006
}
69987007

7008+
public final class io/sentry/util/EventSizeLimitingUtils {
7009+
public static fun limitEventSize (Lio/sentry/SentryEvent;Lio/sentry/Hint;Lio/sentry/SentryOptions;)Lio/sentry/SentryEvent;
7010+
}
7011+
69997012
public final class io/sentry/util/ExceptionUtils {
70007013
public fun <init> ()V
70017014
public static fun findRootCause (Ljava/lang/Throwable;)Ljava/lang/Throwable;
@@ -7062,6 +7075,7 @@ public final class io/sentry/util/IntegrationUtils {
70627075
public final class io/sentry/util/JsonSerializationUtils {
70637076
public fun <init> ()V
70647077
public static fun atomicIntegerArrayToList (Ljava/util/concurrent/atomic/AtomicIntegerArray;)Ljava/util/List;
7078+
public static fun byteSizeOf (Lio/sentry/ISerializer;Lio/sentry/ILogger;Lio/sentry/JsonSerializable;)J
70657079
public static fun bytesFrom (Lio/sentry/ISerializer;Lio/sentry/ILogger;Lio/sentry/JsonSerializable;)[B
70667080
public static fun calendarToMap (Ljava/util/Calendar;)Ljava/util/Map;
70677081
}

sentry/src/main/java/io/sentry/DataCategory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public enum DataCategory {
1010
Session("session"),
1111
Attachment("attachment"),
1212
LogItem("log_item"),
13+
LogByte("log_byte"),
1314
Monitor("monitor"),
1415
Profile("profile"),
1516
ProfileChunkUi("profile_chunk_ui"),

sentry/src/main/java/io/sentry/SentryClient.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ private boolean shouldApplyScopeData(final @NotNull CheckIn event, final @NotNul
163163
}
164164
}
165165

166+
if (event != null) {
167+
event = EventSizeLimitingUtils.limitEventSize(event, hint, options);
168+
}
169+
166170
if (event == null) {
167171
return SentryId.EMPTY_ID;
168172
}
@@ -1183,13 +1187,21 @@ public void captureLog(@Nullable SentryLogEvent logEvent, @Nullable IScope scope
11831187
}
11841188

11851189
if (logEvent != null) {
1190+
final @NotNull SentryLogEvent tmpLogEvent = logEvent;
11861191
logEvent = executeBeforeSendLog(logEvent);
11871192

11881193
if (logEvent == null) {
11891194
options.getLogger().log(SentryLevel.DEBUG, "Log Event was dropped by beforeSendLog");
11901195
options
11911196
.getClientReportRecorder()
11921197
.recordLostEvent(DiscardReason.BEFORE_SEND, DataCategory.LogItem);
1198+
final @NotNull long logEventNumberOfBytes =
1199+
JsonSerializationUtils.byteSizeOf(
1200+
options.getSerializer(), options.getLogger(), tmpLogEvent);
1201+
options
1202+
.getClientReportRecorder()
1203+
.recordLostEvent(
1204+
DiscardReason.BEFORE_SEND, DataCategory.LogByte, logEventNumberOfBytes);
11931205
return;
11941206
}
11951207

sentry/src/main/java/io/sentry/SentryOptions.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,18 @@ public class SentryOptions {
346346
*/
347347
private boolean enableDeduplication = true;
348348

349+
/**
350+
* Enables event size limiting with {@link EventSizeLimitingEventProcessor}. When enabled, events
351+
* exceeding 1MB will have breadcrumbs and stack frames reduced to stay under the limit.
352+
*/
353+
private boolean enableEventSizeLimiting = false;
354+
355+
/**
356+
* Callback invoked when an oversized event is detected. This allows custom handling of oversized
357+
* events before the automatic reduction steps are applied.
358+
*/
359+
private @Nullable OnOversizedErrorCallback onOversizedError;
360+
349361
/** Maximum number of spans that can be atteched to single transaction. */
350362
private int maxSpans = 1000;
351363

@@ -1716,6 +1728,44 @@ public void setEnableDeduplication(final boolean enableDeduplication) {
17161728
this.enableDeduplication = enableDeduplication;
17171729
}
17181730

1731+
/**
1732+
* Returns if event size limiting is enabled.
1733+
*
1734+
* @return true if event size limiting is enabled, false otherwise
1735+
*/
1736+
public boolean isEnableEventSizeLimiting() {
1737+
return enableEventSizeLimiting;
1738+
}
1739+
1740+
/**
1741+
* Enables or disables event size limiting. When enabled, events exceeding 1MB will have
1742+
* breadcrumbs and stack frames reduced to stay under the limit.
1743+
*
1744+
* @param enableEventSizeLimiting true to enable, false to disable
1745+
*/
1746+
public void setEnableEventSizeLimiting(final boolean enableEventSizeLimiting) {
1747+
this.enableEventSizeLimiting = enableEventSizeLimiting;
1748+
}
1749+
1750+
/**
1751+
* Returns the onOversizedError callback.
1752+
*
1753+
* @return the onOversizedError callback or null if not set
1754+
*/
1755+
public @Nullable OnOversizedErrorCallback getOnOversizedError() {
1756+
return onOversizedError;
1757+
}
1758+
1759+
/**
1760+
* Sets the onOversizedError callback. This callback is invoked when an oversized event is
1761+
* detected, before the automatic reduction steps are applied.
1762+
*
1763+
* @param onOversizedError the onOversizedError callback
1764+
*/
1765+
public void setOnOversizedError(@Nullable OnOversizedErrorCallback onOversizedError) {
1766+
this.onOversizedError = onOversizedError;
1767+
}
1768+
17191769
/**
17201770
* Returns if tracing should be enabled. If tracing is disabled, starting transactions returns
17211771
* {@link NoOpTransaction}.
@@ -3100,6 +3150,21 @@ public interface BeforeBreadcrumbCallback {
31003150
Breadcrumb execute(@NotNull Breadcrumb breadcrumb, @NotNull Hint hint);
31013151
}
31023152

3153+
/** The OnOversizedError callback */
3154+
public interface OnOversizedErrorCallback {
3155+
3156+
/**
3157+
* Called when an oversized event is detected. This callback allows custom handling of oversized
3158+
* events before automatic reduction steps are applied.
3159+
*
3160+
* @param event the oversized event
3161+
* @param hint the hints
3162+
* @return the modified event (should ideally be reduced in size)
3163+
*/
3164+
@NotNull
3165+
SentryEvent execute(@NotNull SentryEvent event, @NotNull Hint hint);
3166+
}
3167+
31033168
/** The OnDiscard callback */
31043169
public interface OnDiscardCallback {
31053170

sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.sentry.SentryEnvelopeItem;
77
import io.sentry.SentryItemType;
88
import io.sentry.SentryLevel;
9+
import io.sentry.SentryLogEvent;
910
import io.sentry.SentryLogEvents;
1011
import io.sentry.SentryOptions;
1112
import io.sentry.protocol.SentrySpan;
@@ -104,8 +105,12 @@ public void recordLostEnvelopeItem(
104105
} else if (itemCategory.equals(DataCategory.LogItem)) {
105106
final @Nullable SentryLogEvents logs = envelopeItem.getLogs(options.getSerializer());
106107
if (logs != null) {
107-
final long count = logs.getItems().size();
108+
final @NotNull List<SentryLogEvent> items = logs.getItems();
109+
final long count = items.size();
108110
recordLostEventInternal(reason.getReason(), itemCategory.getCategory(), count);
111+
final long logBytes = envelopeItem.getData().length;
112+
recordLostEventInternal(
113+
reason.getReason(), DataCategory.LogByte.getCategory(), logBytes);
109114
executeOnDiscard(reason, itemCategory, count);
110115
}
111116
} else {

0 commit comments

Comments
 (0)