Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b1ced85
Add sentry replay envelope and event
romtsn Feb 1, 2024
f8419d1
Merge branch 'rz/feat/session-replay-sources' into rz/feat/session-re…
romtsn Feb 13, 2024
a63cac1
WIP
romtsn Feb 15, 2024
fa72057
Add replay envelopes
romtsn Feb 19, 2024
6cfb511
Remove jsonValue
romtsn Feb 19, 2024
0d031d7
Remove
romtsn Feb 19, 2024
07e6b26
Fix json
romtsn Feb 19, 2024
18af924
Finalize replay envelopes
romtsn Feb 20, 2024
64cedfa
Introduce MapObjectReader
romtsn Feb 20, 2024
b8cb924
Add missing test
romtsn Feb 20, 2024
28d341f
Merge branch 'rz/feat/session-replay-envelopes' into rz/feat/session-…
romtsn Feb 20, 2024
1e76fc7
Add test for MapObjectReader
romtsn Feb 22, 2024
13c1971
Add MapObjectWriter change
romtsn Feb 22, 2024
a14e090
Merge branch 'rz/feat/session-replay-envelopes' into rz/feat/session-…
romtsn Feb 22, 2024
86baf7f
Add finals
romtsn Feb 22, 2024
f1ca9f6
Fix test
romtsn Feb 22, 2024
fbbe0d9
Fix test
romtsn Feb 22, 2024
688233f
Merge branch 'rz/feat/session-replay-envelopes' into rz/feat/session-…
romtsn Feb 22, 2024
fd63960
Address review
romtsn Feb 28, 2024
93785cc
Add finals and annotations
romtsn Feb 28, 2024
4db19e0
Merge pull request #3215 from getsentry/rz/feat/session-replay-map-ob…
romtsn Feb 28, 2024
62477b4
Remove public captureReplay method
romtsn Mar 1, 2024
af42fb3
Fix test
romtsn Mar 1, 2024
cd09739
Merge branch 'rz/feat/session-replay-sources' into rz/feat/session-re…
romtsn Mar 1, 2024
4e54c77
api dump
romtsn Mar 1, 2024
fb14ecb
Merge branch 'rz/feat/session-replay' into rz/feat/session-replay-env…
romtsn Mar 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add sentry replay envelope and event
  • Loading branch information
romtsn committed Feb 1, 2024
commit b1ced8534d462686bf27ca0ad2867c65c0c6e29f
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.sentry.SentryBaseEvent;
import io.sentry.SentryEvent;
import io.sentry.SentryLevel;
import io.sentry.SentryReplayEvent;
import io.sentry.android.core.internal.util.AndroidMainThreadChecker;
import io.sentry.android.core.performance.AppStartMetrics;
import io.sentry.android.core.performance.TimeSpan;
Expand Down Expand Up @@ -256,4 +257,20 @@ private void setSideLoadedInfo(final @NotNull SentryBaseEvent event) {

return transaction;
}

@Override
public @NotNull SentryReplayEvent process(
final @NotNull SentryReplayEvent event, final @NotNull Hint hint) {
final boolean applyScopeData = shouldApplyScopeData(event, hint);
if (applyScopeData) {
// we only set memory data if it's not a hard crash, when it's a hard crash the event is
// enriched on restart, so non static data might be wrong, eg lowMemory or availMem will
// be different if the App. crashes because of OOM.
processNonCachedEvent(event, hint);
}

setCommons(event, false, applyScopeData);

return event;
}
}
1 change: 1 addition & 0 deletions sentry/src/main/java/io/sentry/DataCategory.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public enum DataCategory {
Monitor("monitor"),
Profile("profile"),
Transaction("transaction"),
Replay("replay"),
Security("security"),
UserReport("user_report"),
Unknown("unknown");
Expand Down
12 changes: 12 additions & 0 deletions sentry/src/main/java/io/sentry/EventProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,16 @@ default SentryEvent process(@NotNull SentryEvent event, @NotNull Hint hint) {
default SentryTransaction process(@NotNull SentryTransaction transaction, @NotNull Hint hint) {
return transaction;
}

/**
* May mutate or drop a SentryEvent
*
* @param event the SentryEvent
* @param hint the Hint
* @return the event itself, a mutated SentryEvent or null
*/
@Nullable
default SentryReplayEvent process(@NotNull SentryReplayEvent event, @NotNull Hint hint) {
return event;
}
}
15 changes: 15 additions & 0 deletions sentry/src/main/java/io/sentry/Hint.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public final class Hint {

private final @NotNull Map<String, Object> internalStorage = new HashMap<String, Object>();
private final @NotNull List<Attachment> attachments = new ArrayList<>();
private final @NotNull List<ReplayRecording> replayRecordings = new ArrayList<>();
private @Nullable Attachment screenshot = null;
private @Nullable Attachment viewHierarchy = null;

Expand Down Expand Up @@ -70,6 +71,12 @@ public synchronized void remove(@NotNull String name) {
internalStorage.remove(name);
}

public void addReplayRecording(final @Nullable ReplayRecording recording) {
if (recording != null) {
replayRecordings.add(recording);
}
}

public void addAttachment(@Nullable Attachment attachment) {
if (attachment != null) {
attachments.add(attachment);
Expand All @@ -86,6 +93,10 @@ public void addAttachments(@Nullable List<Attachment> attachments) {
return new ArrayList<>(attachments);
}

public @NotNull List<ReplayRecording> getReplayRecordings() {
return new ArrayList<>(replayRecordings);
}

public void replaceAttachments(@Nullable List<Attachment> attachments) {
clearAttachments();
addAttachments(attachments);
Expand All @@ -95,6 +106,10 @@ public void clearAttachments() {
attachments.clear();
}

public void clearReplayRecordings() {
replayRecordings.clear();
}

/**
* Clears all attributes added via {@link #set(String, Object)} Note: SDK internal attributes are
* being kept. This is useful to avoid leaking any objects (e.g. Android activities) being
Expand Down
22 changes: 22 additions & 0 deletions sentry/src/main/java/io/sentry/Hub.java
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,28 @@ private IScope buildLocalScope(
return sentryId;
}

@Override
public @NotNull SentryId captureReplay(
final @NotNull SentryReplayEvent replay, final @Nullable Hint hint) {
SentryId sentryId = SentryId.EMPTY_ID;
if (!isEnabled()) {
options
.getLogger()
.log(
SentryLevel.WARNING,
"Instance is disabled and this 'captureReplay' call is a no-op.");
} else {
try {
StackItem item = stack.peek();
sentryId = item.getClient().captureReplayEvent(replay, item.getScope(), null);
} catch (Throwable e) {
options.getLogger().log(SentryLevel.ERROR, "Error while capturing check-in for slug", e);
}
}
this.lastEventId = sentryId;
return sentryId;
}

@ApiStatus.Internal
@Override
public @Nullable RateLimiter getRateLimiter() {
Expand Down
6 changes: 6 additions & 0 deletions sentry/src/main/java/io/sentry/HubAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,12 @@ public void reportFullyDisplayed() {
return Sentry.captureCheckIn(checkIn);
}

@Override
public @NotNull SentryId captureReplay(
final @NotNull SentryReplayEvent replay, final @Nullable Hint hint) {
return Sentry.getCurrentHub().captureReplay(replay, hint);
}

@ApiStatus.Internal
@Override
public @Nullable RateLimiter getRateLimiter() {
Expand Down
3 changes: 3 additions & 0 deletions sentry/src/main/java/io/sentry/IHub.java
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,9 @@ TransactionContext continueTrace(
@NotNull
SentryId captureCheckIn(final @NotNull CheckIn checkIn);

@NotNull
SentryId captureReplay(@NotNull SentryReplayEvent replay, @Nullable Hint hint);

@ApiStatus.Internal
@Nullable
RateLimiter getRateLimiter();
Expand Down
3 changes: 3 additions & 0 deletions sentry/src/main/java/io/sentry/ISentryClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ public interface ISentryClient {
return captureException(throwable, scope, null);
}

@NotNull SentryId captureReplayEvent(
@NotNull SentryReplayEvent event, @Nullable IScope scope, @Nullable Hint hint);

/**
* Captures a manually created user feedback and sends it to Sentry.
*
Expand Down
10 changes: 10 additions & 0 deletions sentry/src/main/java/io/sentry/MainEventProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,16 @@ private void processNonCachedEvent(final @NotNull SentryBaseEvent event) {
return transaction;
}

@Override
public @NotNull SentryReplayEvent process(@NotNull SentryReplayEvent event, @NotNull Hint hint) {
setCommons(event);
setDebugMeta(event);

if (shouldApplyScopeData(event, hint)) {
processNonCachedEvent(event);
}
return event;
}
private void setCommons(final @NotNull SentryBaseEvent event) {
setPlatform(event);
}
Expand Down
5 changes: 5 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpHub.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ public void reportFullyDisplayed() {}
return SentryId.EMPTY_ID;
}

@Override
public @NotNull SentryId captureReplay(@NotNull SentryReplayEvent replay, @Nullable Hint hint) {
return SentryId.EMPTY_ID;
}

@Override
public @Nullable RateLimiter getRateLimiter() {
return null;
Expand Down
6 changes: 6 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpSentryClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ public SentryId captureEnvelope(@NotNull SentryEnvelope envelope, @Nullable Hint
return SentryId.EMPTY_ID;
}

@Override
public @NotNull SentryId captureReplayEvent(@NotNull SentryReplayEvent event,
@Nullable IScope scope, @Nullable Hint hint) {
return SentryId.EMPTY_ID;
}

@Override
public @Nullable RateLimiter getRateLimiter() {
return null;
Expand Down
101 changes: 101 additions & 0 deletions sentry/src/main/java/io/sentry/ReplayRecording.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package io.sentry;

import io.sentry.vendor.gson.stream.JsonToken;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public final class ReplayRecording implements JsonUnknown, JsonSerializable {

public static final class JsonKeys {
public static final String SEGMENT_ID = "segment_id";
}

private @Nullable Integer segmentId;
private @Nullable Map<String, Object> unknown;

// TODO spec it out, good enough for now
private @Nullable List<Object> payload;

@Nullable
public Integer getSegmentId() {
return segmentId;
}

public void setSegmentId(@Nullable Integer segmentId) {
this.segmentId = segmentId;
}

@Nullable
public List<Object> getPayload() {
return payload;
}

public void setPayload(@Nullable List<Object> payload) {
this.payload = payload;
}

@Override
public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger)
throws IOException {
writer.beginObject();
if (segmentId != null) {
writer.name(JsonKeys.SEGMENT_ID).value(segmentId);
}

if (unknown != null) {
for (String key : unknown.keySet()) {
Object value = unknown.get(key);
writer.name(key).value(logger, value);
}
}
writer.endObject();
}

@Override
public @Nullable Map<String, Object> getUnknown() {
return unknown;
}

@Override
public void setUnknown(@Nullable Map<String, Object> unknown) {
this.unknown = unknown;
}

public static final class Deserializer implements JsonDeserializer<ReplayRecording> {

@Override
public @NotNull ReplayRecording deserialize(
@NotNull JsonObjectReader reader, @NotNull ILogger logger) throws Exception {

final ReplayRecording replay = new ReplayRecording();

@Nullable Map<String, Object> unknown = null;
@Nullable Integer segmentId = null;

reader.beginObject();
while (reader.peek() == JsonToken.NAME) {
final String nextName = reader.nextName();
switch (nextName) {
case JsonKeys.SEGMENT_ID:
segmentId = reader.nextIntegerOrNull();
break;
default:
if (unknown == null) {
unknown = new HashMap<>();
}
reader.nextUnknown(logger, unknown, nextName);
break;
}
}
reader.endObject();

replay.setSegmentId(segmentId);
replay.setUnknown(unknown);
return replay;
}
}
}
5 changes: 5 additions & 0 deletions sentry/src/main/java/io/sentry/Sentry.java
Original file line number Diff line number Diff line change
Expand Up @@ -1025,4 +1025,9 @@ public interface OptionsConfiguration<T extends SentryOptions> {
public static @NotNull SentryId captureCheckIn(final @NotNull CheckIn checkIn) {
return getCurrentHub().captureCheckIn(checkIn);
}

public static void captureReplay(
final @NotNull SentryReplayEvent replay, final @Nullable Hint hint) {
getCurrentHub().captureReplay(replay, hint);
}
}
Loading