Skip to content

Commit

Permalink
Merge dd366fd into beba014
Browse files Browse the repository at this point in the history
  • Loading branch information
markushi committed Jul 18, 2023
2 parents beba014 + dd366fd commit f4bdef7
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 50 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
- Fix ANRv2 thread dump parsing for native-only threads ([#2839](https://github.com/getsentry/sentry-java/pull/2839))
- Derive `TracingContext` values from event for ANRv2 events ([#2839](https://github.com/getsentry/sentry-java/pull/2839))

### Features
- (Internal) Extend APIs for hybrid SDKs ([#2814](https://github.com/getsentry/sentry-java/pull/2814), [#2846](https://github.com/getsentry/sentry-java/pull/2846))

## 6.25.2

### Fixes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public final class InternalSentrySdk {
@Nullable
public static Scope getCurrentScope() {
final @NotNull AtomicReference<Scope> scopeRef = new AtomicReference<>();
HubAdapter.getInstance().withScope(scopeRef::set);
//noinspection Convert2MethodRef
HubAdapter.getInstance().withScope(scope -> scopeRef.set(scope));
return scopeRef.get();
}

Expand All @@ -53,22 +54,21 @@ public static Scope getCurrentScope() {
* @param options Sentry Options
* @param scope the scope
* @return a map containing all relevant scope data (user, contexts, tags, extras, fingerprint,
* level, breadcrumbs)
* level, breadcrumbs) or null if the scope itself is null or serialization fails
*/
@NotNull
public static Map<String, Object> serializeScope(
final @NotNull Context context,
final @NotNull SentryAndroidOptions options,
final @Nullable Scope scope) {

final @NotNull Map<String, Object> data = new HashMap<>();
if (scope == null) {
return data;
}

final @NotNull ILogger logger = options.getLogger();
final @NotNull ObjectWriter writer = new MapObjectWriter(data);

try {
final @NotNull ILogger logger = options.getLogger();
final @NotNull ObjectWriter writer = new MapObjectWriter(data);

final @NotNull DeviceInfoUtil deviceInfoUtil = DeviceInfoUtil.getInstance(context, options);
final @NotNull Device deviceInfo = deviceInfoUtil.collectDeviceInformation(true, true);
Expand Down Expand Up @@ -114,7 +114,7 @@ public static Map<String, Object> serializeScope(
writer.name("fingerprint").value(logger, scope.getFingerprint());
writer.name("level").value(logger, scope.getLevel());
writer.name("breadcrumbs").value(logger, scope.getBreadcrumbs());
} catch (Exception e) {
} catch (Throwable e) {
options.getLogger().log(SentryLevel.ERROR, "Could not serialize scope.", e);
return new HashMap<>();
}
Expand All @@ -124,54 +124,62 @@ public static Map<String, Object> serializeScope(

/**
* Captures the provided envelope. Compared to {@link IHub#captureEvent(SentryEvent)} this method
* - will not enrich events with additional data (e.g. scope) - will not execute beforeSend: it's
* up to the caller to take care of this - will not perform any sampling: it's up to the caller to
* take care of this - will enrich the envelope with a Session updates is applicable
* <br>
* - will not enrich events with additional data (e.g. scope)<br>
* - will not execute beforeSend: it's up to the caller to take care of this<br>
* - will not perform any sampling: it's up to the caller to take care of this<br>
* - will enrich the envelope with a Session update if applicable<br>
*
* @param envelopeData the serialized envelope data
* @return The Id (SentryId object) of the event
* @throws Exception In case the provided envelope could not be parsed / is invalid
* @return The Id (SentryId object) of the event, or null in case the envelope could not be
* captured
*/
public static SentryId captureEnvelope(final @NotNull byte[] envelopeData) throws Exception {
@Nullable
public static SentryId captureEnvelope(final @NotNull byte[] envelopeData) {
final @NotNull IHub hub = HubAdapter.getInstance();
final @NotNull SentryOptions options = hub.getOptions();

final @NotNull ISerializer serializer = options.getSerializer();
final @Nullable SentryEnvelope envelope =
options.getEnvelopeReader().read(new ByteArrayInputStream(envelopeData));
if (envelope == null) {
throw new IllegalArgumentException("Envelope could not be read");
}
try {
final @NotNull ISerializer serializer = options.getSerializer();
final @Nullable SentryEnvelope envelope =
options.getEnvelopeReader().read(new ByteArrayInputStream(envelopeData));
if (envelope == null) {
return null;
}

final @NotNull List<SentryEnvelopeItem> envelopeItems = new ArrayList<>();
final @NotNull List<SentryEnvelopeItem> envelopeItems = new ArrayList<>();

// determine session state based on events inside envelope
@Nullable Session.State status = null;
boolean crashedOrErrored = false;
for (SentryEnvelopeItem item : envelope.getItems()) {
envelopeItems.add(item);
// determine session state based on events inside envelope
@Nullable Session.State status = null;
boolean crashedOrErrored = false;
for (SentryEnvelopeItem item : envelope.getItems()) {
envelopeItems.add(item);

final SentryEvent event = item.getEvent(serializer);
if (event != null) {
if (event.isCrashed()) {
status = Session.State.Crashed;
}
if (event.isCrashed() || event.isErrored()) {
crashedOrErrored = true;
final SentryEvent event = item.getEvent(serializer);
if (event != null) {
if (event.isCrashed()) {
status = Session.State.Crashed;
}
if (event.isCrashed() || event.isErrored()) {
crashedOrErrored = true;
}
}
}
}

// update session and add it to envelope if necessary
final @Nullable Session session = updateSession(hub, options, status, crashedOrErrored);
if (session != null) {
final SentryEnvelopeItem sessionItem = SentryEnvelopeItem.fromSession(serializer, session);
envelopeItems.add(sessionItem);
}
// update session and add it to envelope if necessary
final @Nullable Session session = updateSession(hub, options, status, crashedOrErrored);
if (session != null) {
final SentryEnvelopeItem sessionItem = SentryEnvelopeItem.fromSession(serializer, session);
envelopeItems.add(sessionItem);
}

final SentryEnvelope repackagedEnvelope =
new SentryEnvelope(envelope.getHeader(), envelopeItems);
return hub.captureEnvelope(repackagedEnvelope);
final SentryEnvelope repackagedEnvelope =
new SentryEnvelope(envelope.getHeader(), envelopeItems);
return hub.captureEnvelope(repackagedEnvelope);
} catch (Throwable t) {
options.getLogger().log(SentryLevel.ERROR, "Failed to capture envelope", t);
}
return null;
}

@Nullable
Expand All @@ -181,7 +189,7 @@ private static Session updateSession(
final @Nullable Session.State status,
final boolean crashedOrErrored) {
final @NotNull AtomicReference<Session> sessionRef = new AtomicReference<>();
hub.withScope(
hub.configureScope(
scope -> {
final @Nullable Session session = scope.getSession();
if (session != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ import org.mockito.kotlin.whenever
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStreamReader
import java.util.concurrent.atomic.AtomicReference
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFails
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue
Expand Down Expand Up @@ -203,9 +203,7 @@ class InternalSentrySdkTest {

@Test
fun `captureEnvelope fails if payload is invalid`() {
assertFails {
InternalSentrySdk.captureEnvelope(ByteArray(8))
}
assertNull(InternalSentrySdk.captureEnvelope(ByteArray(8)))
}

@Test
Expand Down Expand Up @@ -251,20 +249,26 @@ class InternalSentrySdkTest {
}
)

// then the session should be included
val capturedEnvelope = fixture.capturedEnvelopes.first()
val capturedEnvelopeItems = capturedEnvelope.items.toList()

// and it should contain the original event / attachment
// then it should contain the original event + session
assertEquals(2, capturedEnvelopeItems.size)
assertEquals(SentryItemType.Event, capturedEnvelopeItems[0].header.type)
assertEquals(SentryItemType.Session, capturedEnvelopeItems[1].header.type)

// and then the sent session should be marked as crashed
val capturedSession = fixture.options.serializer.deserialize(
InputStreamReader(ByteArrayInputStream(capturedEnvelopeItems[1].data)),
Session::class.java
)!!

assertEquals(Session.State.Crashed, capturedSession.status)

// and the local session should be marked as crashed too
val scopeRef = AtomicReference<Scope>()
Sentry.configureScope { scope ->
scopeRef.set(scope)
}
assertEquals(Session.State.Crashed, scopeRef.get().session!!.status)
}
}

0 comments on commit f4bdef7

Please sign in to comment.