Skip to content

Commit fc5ccaf

Browse files
feat(envelope-item): Support span type (#4935)
* Support span type * Update CHANGELOG * Update CHANGELOG * Update CHANGELOG * Update CHANGELOG Moved 'Support span envelope item type' feature to internal section. * Add client report recorder and rate limiting case * Formatting * Fix test * Format code --------- Co-authored-by: Sentry Github Bot <[email protected]>
1 parent 4742e23 commit fc5ccaf

File tree

7 files changed

+42
-0
lines changed

7 files changed

+42
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ SentryAndroid.init(
6060

6161
- Fix missing thread stacks for ANRv1 events ([#4918](https://github.com/getsentry/sentry-java/pull/4918))
6262

63+
### Internal
64+
65+
- Support `span` envelope item type ([#4935](https://github.com/getsentry/sentry-java/pull/4935))
66+
6367
## 8.27.1
6468

6569
### Fixes

sentry/api/sentry.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3137,6 +3137,7 @@ public final class io/sentry/SentryItemType : java/lang/Enum, io/sentry/JsonSeri
31373137
public static final field ReplayRecording Lio/sentry/SentryItemType;
31383138
public static final field ReplayVideo Lio/sentry/SentryItemType;
31393139
public static final field Session Lio/sentry/SentryItemType;
3140+
public static final field Span Lio/sentry/SentryItemType;
31403141
public static final field Transaction Lio/sentry/SentryItemType;
31413142
public static final field Unknown Lio/sentry/SentryItemType;
31423143
public static final field UserFeedback Lio/sentry/SentryItemType;

sentry/src/main/java/io/sentry/SentryItemType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public enum SentryItemType implements JsonSerializable {
2323
CheckIn("check_in"),
2424
Feedback("feedback"),
2525
Log("log"),
26+
Span("span"),
2627
Unknown("__unknown__"); // DataCategory.Unknown
2728

2829
private final String itemType;

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ private DataCategory categoryFromItemType(SentryItemType itemType) {
215215
if (SentryItemType.Log.equals(itemType)) {
216216
return DataCategory.LogItem;
217217
}
218+
if (SentryItemType.Span.equals(itemType)) {
219+
return DataCategory.Span;
220+
}
218221

219222
return DataCategory.Default;
220223
}

sentry/src/main/java/io/sentry/transport/RateLimiter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ private boolean isRetryAfter(final @NotNull String itemType) {
213213
return Collections.singletonList(DataCategory.Feedback);
214214
case "log":
215215
return Collections.singletonList(DataCategory.LogItem);
216+
case "span":
217+
return Collections.singletonList(DataCategory.Span);
216218
default:
217219
return Collections.singletonList(DataCategory.Unknown);
218220
}

sentry/src/test/java/io/sentry/protocol/SentryItemTypeSerializationTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class SentryItemTypeSerializationTest {
3232
assertEquals(serialize(SentryItemType.ReplayVideo), json("replay_video"))
3333
assertEquals(serialize(SentryItemType.CheckIn), json("check_in"))
3434
assertEquals(serialize(SentryItemType.Feedback), json("feedback"))
35+
assertEquals(serialize(SentryItemType.Span), json("span"))
3536
}
3637

3738
@Test
@@ -49,6 +50,7 @@ class SentryItemTypeSerializationTest {
4950
assertEquals(deserialize(json("replay_video")), SentryItemType.ReplayVideo)
5051
assertEquals(deserialize(json("check_in")), SentryItemType.CheckIn)
5152
assertEquals(deserialize(json("feedback")), SentryItemType.Feedback)
53+
assertEquals(deserialize(json("span")), SentryItemType.Span)
5254
}
5355

5456
private fun json(type: String): String = "{\"type\":\"${type}\"}"

sentry/src/test/java/io/sentry/transport/RateLimiterTest.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import io.sentry.Attachment
44
import io.sentry.CheckIn
55
import io.sentry.CheckInStatus
66
import io.sentry.DataCategory.Replay
7+
import io.sentry.EnvelopeReader
78
import io.sentry.Hint
89
import io.sentry.ILogger
910
import io.sentry.IScopes
1011
import io.sentry.ISerializer
12+
import io.sentry.JsonSerializer
1113
import io.sentry.NoOpLogger
1214
import io.sentry.ProfileChunk
1315
import io.sentry.ProfilingTraceData
@@ -534,6 +536,33 @@ class RateLimiterTest {
534536
verifyNoMoreInteractions(fixture.clientReportRecorder)
535537
}
536538

539+
@Test
540+
fun `drop span items as lost`() {
541+
val rateLimiter = fixture.getSUT()
542+
543+
// There is no span API yet so we'll create the envelope manually using EnvelopeReader
544+
// This mimics how hybrid SDKs would send span v2 envelope items
545+
val spanPayload = """{"items":[]}"""
546+
val spanItemHeader =
547+
"""{"type":"span","length":${spanPayload.length},"content_type":"application/vnd.sentry.items.span.v2+json","item_count":1}"""
548+
val envelopeHeader = """{}"""
549+
val rawEnvelope = "$envelopeHeader\n$spanItemHeader\n$spanPayload"
550+
551+
val options = SentryOptions()
552+
val envelopeReader = EnvelopeReader(JsonSerializer(options))
553+
val spanEnvelope = envelopeReader.read(rawEnvelope.byteInputStream())!!
554+
val spanItem = spanEnvelope.items.first()
555+
556+
rateLimiter.updateRetryAfterLimits("60:span:key", null, 1)
557+
val result = rateLimiter.filter(spanEnvelope, Hint())
558+
559+
assertNull(result)
560+
561+
verify(fixture.clientReportRecorder, times(1))
562+
.recordLostEnvelopeItem(eq(DiscardReason.RATELIMIT_BACKOFF), same(spanItem))
563+
verifyNoMoreInteractions(fixture.clientReportRecorder)
564+
}
565+
537566
@Test
538567
fun `apply rate limits notifies observers`() {
539568
val rateLimiter = fixture.getSUT()

0 commit comments

Comments
 (0)