Skip to content

Commit e33b29c

Browse files
committed
Send temporary breadcrumbs and add test
1 parent 0e951eb commit e33b29c

File tree

5 files changed

+127
-16
lines changed

5 files changed

+127
-16
lines changed

sentry-android-replay/src/main/java/io/sentry/android/replay/capture/BaseCaptureStrategy.kt

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,60 @@ internal abstract class BaseCaptureStrategy(
170170

171171
hub?.configureScope { scope ->
172172
scope.breadcrumbs.forEach { breadcrumb ->
173-
if (breadcrumb.timestamp.after(segmentTimestamp) && breadcrumb.timestamp.before(endTimestamp)) {
174-
recordingPayload += RRWebBreadcrumbEvent().apply {
175-
timestamp = breadcrumb.timestamp.time
176-
breadcrumbTimestamp = breadcrumb.timestamp.time
177-
breadcrumbType = breadcrumb.type
178-
category = breadcrumb.category
179-
message = breadcrumb.message
180-
data = breadcrumb.data
173+
if (breadcrumb.timestamp.after(segmentTimestamp) && breadcrumb.timestamp.before(
174+
endTimestamp
175+
)
176+
) {
177+
// TODO: rework this later when aligned with iOS and frontend
178+
var breadcrumbMessage: String? = null
179+
val breadcrumbCategory: String?
180+
val breadcrumbData = mutableMapOf<String, Any?>()
181+
when {
182+
breadcrumb.category == "http" -> return@forEach
183+
184+
breadcrumb.category == "device.orientation" -> {
185+
breadcrumbCategory = breadcrumb.category!!
186+
breadcrumbMessage = breadcrumb.data["position"] as? String ?: ""
187+
}
188+
189+
breadcrumb.type == "navigation" -> {
190+
breadcrumbCategory = "navigation"
191+
breadcrumbData["to"] = when {
192+
breadcrumb.data["state"] == "resumed" -> breadcrumb.data["screen"] as? String
193+
breadcrumb.category == "app.lifecycle" -> breadcrumb.data["state"] as? String
194+
"to" in breadcrumb.data -> breadcrumb.data["to"] as? String
195+
else -> return@forEach
196+
} ?: return@forEach
197+
}
198+
199+
breadcrumb.category in setOf("ui.click", "ui.scroll", "ui.swipe") -> {
200+
breadcrumbCategory = breadcrumb.category!!
201+
breadcrumbMessage = (
202+
breadcrumb.data["view.id"]
203+
?: breadcrumb.data["view.class"]
204+
?: breadcrumb.data["view.tag"]
205+
) as? String ?: ""
206+
}
207+
208+
breadcrumb.type == "system" -> {
209+
breadcrumbCategory = breadcrumb.type!!
210+
breadcrumbMessage = breadcrumb.data.entries.joinToString() as? String ?: ""
211+
}
212+
213+
else -> {
214+
breadcrumbCategory = breadcrumb.category
215+
breadcrumbMessage = breadcrumb.message
216+
}
217+
}
218+
if (!breadcrumbCategory.isNullOrEmpty()) {
219+
recordingPayload += RRWebBreadcrumbEvent().apply {
220+
timestamp = breadcrumb.timestamp.time
221+
breadcrumbTimestamp = breadcrumb.timestamp.time / 1000.0
222+
breadcrumbType = "default"
223+
category = breadcrumbCategory
224+
message = breadcrumbMessage
225+
data = if (breadcrumbData.isEmpty()) null else breadcrumbData
226+
}
181227
}
182228
}
183229
}
@@ -188,7 +234,11 @@ internal abstract class BaseCaptureStrategy(
188234
payload = recordingPayload
189235
}
190236

191-
return ReplaySegment.Created(videoDuration = duration, replay = replay, recording = recording)
237+
return ReplaySegment.Created(
238+
videoDuration = duration,
239+
replay = replay,
240+
recording = recording
241+
)
192242
}
193243

194244
override fun onConfigurationChanged(recorderConfig: ScreenshotRecorderConfig) {

sentry/api/sentry.api

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5038,7 +5038,7 @@ public final class io/sentry/protocol/ViewHierarchyNode$JsonKeys {
50385038
public final class io/sentry/rrweb/RRWebBreadcrumbEvent : io/sentry/rrweb/RRWebEvent, io/sentry/JsonSerializable, io/sentry/JsonUnknown {
50395039
public static final field EVENT_TAG Ljava/lang/String;
50405040
public fun <init> ()V
5041-
public fun getBreadcrumbTimestamp ()J
5041+
public fun getBreadcrumbTimestamp ()D
50425042
public fun getBreadcrumbType ()Ljava/lang/String;
50435043
public fun getCategory ()Ljava/lang/String;
50445044
public fun getData ()Ljava/util/Map;
@@ -5048,7 +5048,7 @@ public final class io/sentry/rrweb/RRWebBreadcrumbEvent : io/sentry/rrweb/RRWebE
50485048
public fun getTag ()Ljava/lang/String;
50495049
public fun getUnknown ()Ljava/util/Map;
50505050
public fun serialize (Lio/sentry/ObjectWriter;Lio/sentry/ILogger;)V
5051-
public fun setBreadcrumbTimestamp (J)V
5051+
public fun setBreadcrumbTimestamp (D)V
50525052
public fun setBreadcrumbType (Ljava/lang/String;)V
50535053
public fun setCategory (Ljava/lang/String;)V
50545054
public fun setData (Ljava/util/Map;)V

sentry/src/main/java/io/sentry/rrweb/RRWebBreadcrumbEvent.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import io.sentry.util.CollectionUtils;
1010
import io.sentry.vendor.gson.stream.JsonToken;
1111
import java.io.IOException;
12+
import java.math.BigDecimal;
1213
import java.util.HashMap;
1314
import java.util.Map;
1415
import java.util.concurrent.ConcurrentHashMap;
@@ -20,7 +21,7 @@ public final class RRWebBreadcrumbEvent extends RRWebEvent
2021
public static final String EVENT_TAG = "breadcrumb";
2122

2223
private @NotNull String tag;
23-
private long breadcrumbTimestamp;
24+
private double breadcrumbTimestamp;
2425
private @Nullable String breadcrumbType;
2526
private @Nullable String category;
2627
private @Nullable String message;
@@ -45,11 +46,11 @@ public void setTag(final @NotNull String tag) {
4546
this.tag = tag;
4647
}
4748

48-
public long getBreadcrumbTimestamp() {
49+
public double getBreadcrumbTimestamp() {
4950
return breadcrumbTimestamp;
5051
}
5152

52-
public void setBreadcrumbTimestamp(final long breadcrumbTimestamp) {
53+
public void setBreadcrumbTimestamp(final double breadcrumbTimestamp) {
5354
this.breadcrumbTimestamp = breadcrumbTimestamp;
5455
}
5556

@@ -165,7 +166,7 @@ private void serializePayload(final @NotNull ObjectWriter writer, final @NotNull
165166
if (breadcrumbType != null) {
166167
writer.name(JsonKeys.TYPE).value(breadcrumbType);
167168
}
168-
writer.name(JsonKeys.TIMESTAMP).value(breadcrumbTimestamp);
169+
writer.name(JsonKeys.TIMESTAMP).value(logger, BigDecimal.valueOf(breadcrumbTimestamp));
169170
if (category != null) {
170171
writer.name(JsonKeys.CATEGORY).value(category);
171172
}
@@ -263,7 +264,7 @@ private void deserializePayload(
263264
event.breadcrumbType = reader.nextStringOrNull();
264265
break;
265266
case JsonKeys.TIMESTAMP:
266-
event.breadcrumbTimestamp = reader.nextLong();
267+
event.breadcrumbTimestamp = reader.nextDouble();
267268
break;
268269
case JsonKeys.CATEGORY:
269270
event.category = reader.nextStringOrNull();
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package io.sentry.rrweb
2+
3+
import io.sentry.ILogger
4+
import io.sentry.protocol.SerializationUtils
5+
import org.junit.Test
6+
import org.mockito.kotlin.mock
7+
import kotlin.test.assertEquals
8+
9+
class RRWebBreadcrumbEventSerializationTest {
10+
class Fixture {
11+
val logger = mock<ILogger>()
12+
13+
fun getSut() = RRWebBreadcrumbEvent().apply {
14+
timestamp = 12345678901
15+
breadcrumbType = "default"
16+
breadcrumbTimestamp = 12345678.901
17+
category = "navigation"
18+
message = "message"
19+
data = mapOf(
20+
"screen" to "MainActivity",
21+
"state" to "resumed"
22+
)
23+
}
24+
}
25+
26+
private val fixture = Fixture()
27+
28+
@Test
29+
fun serialize() {
30+
val expected = SerializationUtils.sanitizedFile("json/rrweb_breadcrumb_event.json")
31+
val actual = SerializationUtils.serializeToString(fixture.getSut(), fixture.logger)
32+
assertEquals(expected, actual)
33+
}
34+
35+
@Test
36+
fun deserialize() {
37+
val expectedJson = SerializationUtils.sanitizedFile("json/rrweb_breadcrumb_event.json")
38+
val actual =
39+
SerializationUtils.deserializeJson(expectedJson, RRWebBreadcrumbEvent.Deserializer(), fixture.logger)
40+
val actualJson = SerializationUtils.serializeToString(actual, fixture.logger)
41+
assertEquals(expectedJson, actualJson)
42+
}
43+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"type": 5,
3+
"timestamp": 12345678901,
4+
"data": {
5+
"tag": "breadcrumb",
6+
"payload": {
7+
"type": "default",
8+
"timestamp": 12345678.901,
9+
"category": "navigation",
10+
"message": "message",
11+
"data": {
12+
"screen": "MainActivity",
13+
"state": "resumed"
14+
}
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)