diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt index a10d8add7b9..b34e79991fa 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt @@ -118,7 +118,7 @@ class InternalSentrySdkTest { @Test fun `current scope returns obj when hub is active`() { - Sentry.setCurrentHub( + Sentry.setCurrentScopes( Hub( SentryOptions().apply { dsn = "https://key@uri/1234567" @@ -131,7 +131,7 @@ class InternalSentrySdkTest { @Test fun `current scope returns a copy of the scope`() { - Sentry.setCurrentHub( + Sentry.setCurrentScopes( Hub( SentryOptions().apply { dsn = "https://key@uri/1234567" diff --git a/sentry/src/main/java/io/sentry/Breadcrumb.java b/sentry/src/main/java/io/sentry/Breadcrumb.java index fe2055c336c..5f43ab6d298 100644 --- a/sentry/src/main/java/io/sentry/Breadcrumb.java +++ b/sentry/src/main/java/io/sentry/Breadcrumb.java @@ -17,7 +17,7 @@ import org.jetbrains.annotations.Nullable; /** Series of application events */ -public final class Breadcrumb implements JsonUnknown, JsonSerializable { +public final class Breadcrumb implements JsonUnknown, JsonSerializable, Comparable { /** A timestamp representing when the breadcrumb occurred. */ private final @NotNull Date timestamp; @@ -660,6 +660,12 @@ public void setUnknown(@Nullable Map unknown) { this.unknown = unknown; } + @Override + @SuppressWarnings("JavaUtilDate") + public int compareTo(@NotNull Breadcrumb o) { + return timestamp.compareTo(o.timestamp); + } + public static final class JsonKeys { public static final String TIMESTAMP = "timestamp"; public static final String MESSAGE = "message"; diff --git a/sentry/src/main/java/io/sentry/CombinedContextsView.java b/sentry/src/main/java/io/sentry/CombinedContextsView.java new file mode 100644 index 00000000000..3362a8ea1e9 --- /dev/null +++ b/sentry/src/main/java/io/sentry/CombinedContextsView.java @@ -0,0 +1,214 @@ +package io.sentry; + +import io.sentry.protocol.App; +import io.sentry.protocol.Browser; +import io.sentry.protocol.Contexts; +import io.sentry.protocol.Device; +import io.sentry.protocol.Gpu; +import io.sentry.protocol.OperatingSystem; +import io.sentry.protocol.Response; +import io.sentry.protocol.SentryRuntime; +import io.sentry.util.HintUtils; +import java.io.IOException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class CombinedContextsView extends Contexts { + + private static final long serialVersionUID = 3585992094653318439L; + private final @NotNull Contexts globalContexts; + private final @NotNull Contexts isolationContexts; + private final @NotNull Contexts currentContexts; + + private final @NotNull ScopeType defaultScopeType; + + public CombinedContextsView( + final @NotNull Contexts globalContexts, + final @NotNull Contexts isolationContexts, + final @NotNull Contexts currentContexts, + final @NotNull ScopeType defaultScopeType) { + this.globalContexts = globalContexts; + this.isolationContexts = isolationContexts; + this.currentContexts = currentContexts; + this.defaultScopeType = defaultScopeType; + } + + @Override + public @Nullable SpanContext getTrace() { + final @Nullable SpanContext current = currentContexts.getTrace(); + if (current != null) { + return current; + } + final @Nullable SpanContext isolation = isolationContexts.getTrace(); + if (isolation != null) { + return isolation; + } + return globalContexts.getTrace(); + } + + @Override + public void setTrace(@Nullable SpanContext traceContext) { + getDefaultContexts().setTrace(traceContext); + } + + private Contexts getDefaultContexts() { + switch (defaultScopeType) { + case CURRENT: + return currentContexts; + case ISOLATION: + return isolationContexts; + case GLOBAL: + return globalContexts; + default: + return currentContexts; + } + } + + @Override + public @Nullable App getApp() { + final @Nullable App current = currentContexts.getApp(); + if (current != null) { + return current; + } + final @Nullable App isolation = isolationContexts.getApp(); + if (isolation != null) { + return isolation; + } + return globalContexts.getApp(); + } + + @Override + public void setApp(@NotNull App app) { + getDefaultContexts().setApp(app); + } + + @Override + public @Nullable Browser getBrowser() { + final @Nullable Browser current = currentContexts.getBrowser(); + if (current != null) { + return current; + } + final @Nullable Browser isolation = isolationContexts.getBrowser(); + if (isolation != null) { + return isolation; + } + return globalContexts.getBrowser(); + } + + @Override + public void setBrowser(@NotNull Browser browser) { + getDefaultContexts().setBrowser(browser); + } + + @Override + public @Nullable Device getDevice() { + final @Nullable Device current = currentContexts.getDevice(); + if (current != null) { + return current; + } + final @Nullable Device isolation = isolationContexts.getDevice(); + if (isolation != null) { + return isolation; + } + return globalContexts.getDevice(); + } + + @Override + public void setDevice(@NotNull Device device) { + getDefaultContexts().setDevice(device); + } + + @Override + public @Nullable OperatingSystem getOperatingSystem() { + final @Nullable OperatingSystem current = currentContexts.getOperatingSystem(); + if (current != null) { + return current; + } + final @Nullable OperatingSystem isolation = isolationContexts.getOperatingSystem(); + if (isolation != null) { + return isolation; + } + return globalContexts.getOperatingSystem(); + } + + @Override + public void setOperatingSystem(@NotNull OperatingSystem operatingSystem) { + getDefaultContexts().setOperatingSystem(operatingSystem); + } + + @Override + public @Nullable SentryRuntime getRuntime() { + final @Nullable SentryRuntime current = currentContexts.getRuntime(); + if (current != null) { + return current; + } + final @Nullable SentryRuntime isolation = isolationContexts.getRuntime(); + if (isolation != null) { + return isolation; + } + return globalContexts.getRuntime(); + } + + @Override + public void setRuntime(@NotNull SentryRuntime runtime) { + getDefaultContexts().setRuntime(runtime); + } + + @Override + public @Nullable Gpu getGpu() { + final @Nullable Gpu current = currentContexts.getGpu(); + if (current != null) { + return current; + } + final @Nullable Gpu isolation = isolationContexts.getGpu(); + if (isolation != null) { + return isolation; + } + return globalContexts.getGpu(); + } + + @Override + public void setGpu(@NotNull Gpu gpu) { + getDefaultContexts().setGpu(gpu); + } + + @Override + public @Nullable Response getResponse() { + final @Nullable Response current = currentContexts.getResponse(); + if (current != null) { + return current; + } + final @Nullable Response isolation = isolationContexts.getResponse(); + if (isolation != null) { + return isolation; + } + return globalContexts.getResponse(); + } + + @Override + public void withResponse(HintUtils.SentryConsumer callback) { + if (currentContexts.getResponse() != null) { + currentContexts.withResponse(callback); + } else if (isolationContexts.getResponse() != null) { + isolationContexts.withResponse(callback); + } else if (globalContexts.getResponse() != null) { + globalContexts.withResponse(callback); + } else { + getDefaultContexts().withResponse(callback); + } + } + + @Override + public void setResponse(@NotNull Response response) { + getDefaultContexts().setResponse(response); + } + + @Override + public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) throws IOException { + final @NotNull Contexts allContexts = new Contexts(); + allContexts.putAll(globalContexts); + allContexts.putAll(isolationContexts); + allContexts.putAll(currentContexts); + allContexts.serialize(writer, logger); + } +} diff --git a/sentry/src/main/java/io/sentry/CombinedScopeView.java b/sentry/src/main/java/io/sentry/CombinedScopeView.java new file mode 100644 index 00000000000..b9f8ab2c70d --- /dev/null +++ b/sentry/src/main/java/io/sentry/CombinedScopeView.java @@ -0,0 +1,456 @@ +package io.sentry; + +import io.sentry.protocol.Contexts; +import io.sentry.protocol.Request; +import io.sentry.protocol.SentryId; +import io.sentry.protocol.User; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class CombinedScopeView implements IScope { + + private final IScope globalScope; + private final IScope isolationScope; + private final IScope scope; + + public CombinedScopeView( + final @NotNull IScope globalScope, + final @NotNull IScope isolationScope, + final @NotNull IScope scope) { + this.globalScope = globalScope; + this.isolationScope = isolationScope; + this.scope = scope; + } + + @Override + public @Nullable SentryLevel getLevel() { + final @Nullable SentryLevel current = scope.getLevel(); + if (current != null) { + return current; + } + final @Nullable SentryLevel isolation = isolationScope.getLevel(); + if (isolation != null) { + return isolation; + } + return globalScope.getLevel(); + } + + @Override + public void setLevel(@Nullable SentryLevel level) { + getDefaultWriteScope().setLevel(level); + } + + @Override + public @Nullable String getTransactionName() { + final @Nullable String current = scope.getTransactionName(); + if (current != null) { + return current; + } + final @Nullable String isolation = isolationScope.getTransactionName(); + if (isolation != null) { + return isolation; + } + return globalScope.getTransactionName(); + } + + @Override + public void setTransaction(@NotNull String transaction) { + getDefaultWriteScope().setTransaction(transaction); + } + + @Override + public @Nullable ISpan getSpan() { + final @Nullable ISpan current = scope.getSpan(); + if (current != null) { + return current; + } + final @Nullable ISpan isolation = isolationScope.getSpan(); + if (isolation != null) { + return isolation; + } + return globalScope.getSpan(); + } + + @Override + public void setTransaction(@Nullable ITransaction transaction) { + getDefaultWriteScope().setTransaction(transaction); + } + + @Override + public @Nullable User getUser() { + final @Nullable User current = scope.getUser(); + if (current != null) { + return current; + } + final @Nullable User isolation = isolationScope.getUser(); + if (isolation != null) { + return isolation; + } + return globalScope.getUser(); + } + + @Override + public void setUser(@Nullable User user) { + getDefaultWriteScope().setUser(user); + } + + @Override + public @Nullable String getScreen() { + final @Nullable String current = scope.getScreen(); + if (current != null) { + return current; + } + final @Nullable String isolation = isolationScope.getScreen(); + if (isolation != null) { + return isolation; + } + return globalScope.getScreen(); + } + + @Override + public void setScreen(@Nullable String screen) { + getDefaultWriteScope().setScreen(screen); + } + + @Override + public @Nullable Request getRequest() { + final @Nullable Request current = scope.getRequest(); + if (current != null) { + return current; + } + final @Nullable Request isolation = isolationScope.getRequest(); + if (isolation != null) { + return isolation; + } + return globalScope.getRequest(); + } + + @Override + public void setRequest(@Nullable Request request) { + getDefaultWriteScope().setRequest(request); + } + + @Override + public @NotNull List getFingerprint() { + final @Nullable List current = scope.getFingerprint(); + if (!current.isEmpty()) { + return current; + } + final @Nullable List isolation = isolationScope.getFingerprint(); + if (!isolation.isEmpty()) { + return isolation; + } + return globalScope.getFingerprint(); + } + + @Override + public void setFingerprint(@NotNull List fingerprint) { + getDefaultWriteScope().setFingerprint(fingerprint); + } + + @Override + public @NotNull Queue getBreadcrumbs() { + final @NotNull List allBreadcrumbs = new ArrayList<>(); + allBreadcrumbs.addAll(globalScope.getBreadcrumbs()); + allBreadcrumbs.addAll(isolationScope.getBreadcrumbs()); + allBreadcrumbs.addAll(scope.getBreadcrumbs()); + Collections.sort(allBreadcrumbs); + + // TODO test oldest are removed first + final @NotNull Queue breadcrumbs = + createBreadcrumbsList(scope.getOptions().getMaxBreadcrumbs()); + breadcrumbs.addAll(allBreadcrumbs); + + return breadcrumbs; + } + + /** + * Creates a breadcrumb list with the max number of breadcrumbs + * + * @param maxBreadcrumb the max number of breadcrumbs + * @return the breadcrumbs queue + */ + // TODO copied from Scope, should reuse instead + private @NotNull Queue createBreadcrumbsList(final int maxBreadcrumb) { + return SynchronizedQueue.synchronizedQueue(new CircularFifoQueue<>(maxBreadcrumb)); + } + + @Override + public void addBreadcrumb(@NotNull Breadcrumb breadcrumb, @Nullable Hint hint) { + getDefaultWriteScope().addBreadcrumb(breadcrumb, hint); + } + + @Override + public void addBreadcrumb(@NotNull Breadcrumb breadcrumb) { + getDefaultWriteScope().addBreadcrumb(breadcrumb); + } + + @Override + public void clearBreadcrumbs() { + getDefaultWriteScope().clearBreadcrumbs(); + } + + @Override + public void clearTransaction() { + getDefaultWriteScope().clearTransaction(); + } + + @Override + public @Nullable ITransaction getTransaction() { + final @Nullable ITransaction current = scope.getTransaction(); + if (current != null) { + return current; + } + final @Nullable ITransaction isolation = isolationScope.getTransaction(); + if (isolation != null) { + return isolation; + } + return globalScope.getTransaction(); + } + + @Override + public void clear() { + getDefaultWriteScope().clear(); + } + + @Override + public @NotNull Map getTags() { + final @NotNull Map allTags = new ConcurrentHashMap<>(); + allTags.putAll(globalScope.getTags()); + allTags.putAll(isolationScope.getTags()); + allTags.putAll(scope.getTags()); + return allTags; + } + + @Override + public void setTag(@NotNull String key, @NotNull String value) { + getDefaultWriteScope().setTag(key, value); + } + + @Override + public void removeTag(@NotNull String key) { + getDefaultWriteScope().removeTag(key); + } + + @Override + public @NotNull Map getExtras() { + final @NotNull Map allTags = new ConcurrentHashMap<>(); + allTags.putAll(globalScope.getExtras()); + allTags.putAll(isolationScope.getExtras()); + allTags.putAll(scope.getExtras()); + return allTags; + } + + @Override + public void setExtra(@NotNull String key, @NotNull String value) { + getDefaultWriteScope().setExtra(key, value); + } + + @Override + public void removeExtra(@NotNull String key) { + getDefaultWriteScope().removeExtra(key); + } + + @Override + public @NotNull Contexts getContexts() { + return new CombinedContextsView( + globalScope.getContexts(), + isolationScope.getContexts(), + scope.getContexts(), + getOptions().getDefaultScopeType()); + } + + @Override + public void setContexts(@NotNull String key, @NotNull Object value) { + getDefaultWriteScope().setContexts(key, value); + } + + @Override + public void setContexts(@NotNull String key, @NotNull Boolean value) { + getDefaultWriteScope().setContexts(key, value); + } + + @Override + public void setContexts(@NotNull String key, @NotNull String value) { + getDefaultWriteScope().setContexts(key, value); + } + + @Override + public void setContexts(@NotNull String key, @NotNull Number value) { + getDefaultWriteScope().setContexts(key, value); + } + + @Override + public void setContexts(@NotNull String key, @NotNull Collection value) { + getDefaultWriteScope().setContexts(key, value); + } + + @Override + public void setContexts(@NotNull String key, @NotNull Object[] value) { + getDefaultWriteScope().setContexts(key, value); + } + + @Override + public void setContexts(@NotNull String key, @NotNull Character value) { + getDefaultWriteScope().setContexts(key, value); + } + + @Override + public void removeContexts(@NotNull String key) { + getDefaultWriteScope().removeContexts(key); + } + + private @NotNull IScope getDefaultWriteScope() { + if (ScopeType.CURRENT.equals(getOptions().getDefaultScopeType())) { + return scope; + } + if (ScopeType.ISOLATION.equals(getOptions().getDefaultScopeType())) { + return isolationScope; + } + return globalScope; + } + + @Override + public @NotNull List getAttachments() { + final @NotNull List allAttachments = new CopyOnWriteArrayList<>(); + allAttachments.addAll(globalScope.getAttachments()); + allAttachments.addAll(isolationScope.getAttachments()); + allAttachments.addAll(scope.getAttachments()); + return allAttachments; + } + + @Override + public void addAttachment(@NotNull Attachment attachment) { + getDefaultWriteScope().addAttachment(attachment); + } + + @Override + public void clearAttachments() { + getDefaultWriteScope().clearAttachments(); + } + + @Override + public @NotNull List getEventProcessors() { + // TODO mechanism for ordering event processors + final @NotNull List allEventProcessors = new CopyOnWriteArrayList<>(); + allEventProcessors.addAll(globalScope.getEventProcessors()); + allEventProcessors.addAll(isolationScope.getEventProcessors()); + allEventProcessors.addAll(scope.getEventProcessors()); + return allEventProcessors; + } + + @Override + public void addEventProcessor(@NotNull EventProcessor eventProcessor) { + getDefaultWriteScope().addEventProcessor(eventProcessor); + } + + @Override + public @Nullable Session withSession(Scope.@NotNull IWithSession sessionCallback) { + return getDefaultWriteScope().withSession(sessionCallback); + } + + @Override + public @Nullable Scope.SessionPair startSession() { + return getDefaultWriteScope().startSession(); + } + + @Override + public @Nullable Session endSession() { + return getDefaultWriteScope().endSession(); + } + + @Override + public void withTransaction(Scope.@NotNull IWithTransaction callback) { + getDefaultWriteScope().withTransaction(callback); + } + + @Override + public @NotNull SentryOptions getOptions() { + return scope.getOptions(); + } + + @Override + public @Nullable Session getSession() { + final @Nullable Session current = scope.getSession(); + if (current != null) { + return current; + } + final @Nullable Session isolation = isolationScope.getSession(); + if (isolation != null) { + return isolation; + } + return globalScope.getSession(); + } + + @Override + public void setPropagationContext(@NotNull PropagationContext propagationContext) { + getDefaultWriteScope().setPropagationContext(propagationContext); + } + + @Override + public @NotNull PropagationContext getPropagationContext() { + return getDefaultWriteScope().getPropagationContext(); + } + + @Override + public @NotNull PropagationContext withPropagationContext( + Scope.@NotNull IWithPropagationContext callback) { + return getDefaultWriteScope().withPropagationContext(callback); + } + + @Override + public @NotNull IScope clone() { + // TODO just return a new CombinedScopeView with forked scope? + return getDefaultWriteScope().clone(); + } + + @Override + public void setLastEventId(@NotNull SentryId lastEventId) { + globalScope.setLastEventId(lastEventId); + isolationScope.setLastEventId(lastEventId); + scope.setLastEventId(lastEventId); + } + + @Override + public @NotNull SentryId getLastEventId() { + return globalScope.getLastEventId(); + } + + @Override + public void bindClient(@NotNull ISentryClient client) { + getDefaultWriteScope().bindClient(client); + } + + @Override + public @NotNull ISentryClient getClient() { + // TODO checking for noop here doesn't allow disabling via client, is that ok? + final @Nullable ISentryClient current = scope.getClient(); + if (!(current instanceof NoOpSentryClient)) { + return current; + } + final @Nullable ISentryClient isolation = isolationScope.getClient(); + if (!(isolation instanceof NoOpSentryClient)) { + return isolation; + } + return globalScope.getClient(); + } + + @Override + public void assignTraceContext(@NotNull SentryEvent event) { + globalScope.assignTraceContext(event); + } + + @Override + public void setSpanContext( + @NotNull Throwable throwable, @NotNull ISpan span, @NotNull String transactionName) { + globalScope.setSpanContext(throwable, span, transactionName); + } +} diff --git a/sentry/src/main/java/io/sentry/Scopes.java b/sentry/src/main/java/io/sentry/Scopes.java index c37dddfd31a..daf143ba660 100644 --- a/sentry/src/main/java/io/sentry/Scopes.java +++ b/sentry/src/main/java/io/sentry/Scopes.java @@ -166,7 +166,7 @@ public boolean isEnabled() { } private void assignTraceContext(final @NotNull SentryEvent event) { - Sentry.getGlobalScope().assignTraceContext(event); + getCombinedScopeView().assignTraceContext(event); } private IScope buildLocalScope( @@ -363,8 +363,7 @@ public void endSession() { } private IScope getCombinedScopeView() { - // TODO combine global, isolation and current scope - return scope; + return new CombinedScopeView(getGlobalScope(), isolationScope, scope); } @Override @@ -424,7 +423,7 @@ public void addBreadcrumb(final @NotNull Breadcrumb breadcrumb, final @Nullable } else if (breadcrumb == null) { options.getLogger().log(SentryLevel.WARNING, "addBreadcrumb called with null parameter."); } else { - getDefaultWriteScope().addBreadcrumb(breadcrumb, hint); + getCombinedScopeView().addBreadcrumb(breadcrumb, hint); } } @@ -467,7 +466,7 @@ public void setLevel(final @Nullable SentryLevel level) { .getLogger() .log(SentryLevel.WARNING, "Instance is disabled and this 'setLevel' call is a no-op."); } else { - getDefaultWriteScope().setLevel(level); + getCombinedScopeView().setLevel(level); } } @@ -480,7 +479,7 @@ public void setTransaction(final @Nullable String transaction) { SentryLevel.WARNING, "Instance is disabled and this 'setTransaction' call is a no-op."); } else if (transaction != null) { - getDefaultWriteScope().setTransaction(transaction); + getCombinedScopeView().setTransaction(transaction); } else { options.getLogger().log(SentryLevel.WARNING, "Transaction cannot be null"); } @@ -493,7 +492,7 @@ public void setUser(final @Nullable User user) { .getLogger() .log(SentryLevel.WARNING, "Instance is disabled and this 'setUser' call is a no-op."); } else { - getDefaultWriteScope().setUser(user); + getCombinedScopeView().setUser(user); } } @@ -508,7 +507,7 @@ public void setFingerprint(final @NotNull List fingerprint) { } else if (fingerprint == null) { options.getLogger().log(SentryLevel.WARNING, "setFingerprint called with null parameter."); } else { - getDefaultWriteScope().setFingerprint(fingerprint); + getCombinedScopeView().setFingerprint(fingerprint); } } @@ -521,7 +520,7 @@ public void clearBreadcrumbs() { SentryLevel.WARNING, "Instance is disabled and this 'clearBreadcrumbs' call is a no-op."); } else { - getDefaultWriteScope().clearBreadcrumbs(); + getCombinedScopeView().clearBreadcrumbs(); } } @@ -534,7 +533,7 @@ public void setTag(final @NotNull String key, final @NotNull String value) { } else if (key == null || value == null) { options.getLogger().log(SentryLevel.WARNING, "setTag called with null parameter."); } else { - getDefaultWriteScope().setTag(key, value); + getCombinedScopeView().setTag(key, value); } } @@ -547,7 +546,7 @@ public void removeTag(final @NotNull String key) { } else if (key == null) { options.getLogger().log(SentryLevel.WARNING, "removeTag called with null parameter."); } else { - getDefaultWriteScope().removeTag(key); + getCombinedScopeView().removeTag(key); } } @@ -560,7 +559,7 @@ public void setExtra(final @NotNull String key, final @NotNull String value) { } else if (key == null || value == null) { options.getLogger().log(SentryLevel.WARNING, "setExtra called with null parameter."); } else { - getDefaultWriteScope().setExtra(key, value); + getCombinedScopeView().setExtra(key, value); } } @@ -573,14 +572,12 @@ public void removeExtra(final @NotNull String key) { } else if (key == null) { options.getLogger().log(SentryLevel.WARNING, "removeExtra called with null parameter."); } else { - getDefaultWriteScope().removeExtra(key); + getCombinedScopeView().removeExtra(key); } } private void updateLastEventId(final @NotNull SentryId lastEventId) { - scope.setLastEventId(lastEventId); - isolationScope.setLastEventId(lastEventId); - getGlobalScope().setLastEventId(lastEventId); + getCombinedScopeView().setLastEventId(lastEventId); } // TODO add to IScopes interface @@ -592,14 +589,9 @@ private void updateLastEventId(final @NotNull SentryId lastEventId) { @Override public @NotNull SentryId getLastEventId() { - // TODO read all scopes here / read default scope? - // returning scope.lastEventId isn't ideal because changed to child scope are not stored in - // there - return getGlobalScope().getLastEventId(); + return getCombinedScopeView().getLastEventId(); } - // TODO needs to be deprecated because there's no more stack - // TODO needs to return a lifecycle token @Override public ISentryLifecycleToken pushScope() { if (!isEnabled()) { @@ -698,10 +690,10 @@ public void bindClient(final @NotNull ISentryClient client) { } else { if (client != null) { options.getLogger().log(SentryLevel.DEBUG, "New client bound to scope."); - getDefaultWriteScope().bindClient(client); + getCombinedScopeView().bindClient(client); } else { options.getLogger().log(SentryLevel.DEBUG, "NoOp client bound to scope."); - getDefaultWriteScope().bindClient(NoOpSentryClient.getInstance()); + getCombinedScopeView().bindClient(NoOpSentryClient.getInstance()); } } } @@ -879,7 +871,7 @@ public void setSpanContext( final @NotNull Throwable throwable, final @NotNull ISpan span, final @NotNull String transactionName) { - Sentry.getGlobalScope().setSpanContext(throwable, span, transactionName); + getCombinedScopeView().setSpanContext(throwable, span, transactionName); } // // TODO this seems unused @@ -908,7 +900,7 @@ public void setSpanContext( .getLogger() .log(SentryLevel.WARNING, "Instance is disabled and this 'getSpan' call is a no-op."); } else { - span = getScope().getSpan(); + span = getCombinedScopeView().getSpan(); } return span; } @@ -924,7 +916,7 @@ public void setSpanContext( SentryLevel.WARNING, "Instance is disabled and this 'getTransaction' call is a no-op."); } else { - span = getScope().getTransaction(); + span = getCombinedScopeView().getTransaction(); } return span; } diff --git a/sentry/src/main/java/io/sentry/Sentry.java b/sentry/src/main/java/io/sentry/Sentry.java index 090cba0d669..42ccc3cf637 100644 --- a/sentry/src/main/java/io/sentry/Sentry.java +++ b/sentry/src/main/java/io/sentry/Sentry.java @@ -121,7 +121,7 @@ private Sentry() {} @ApiStatus.Internal // exposed for the coroutines integration in SentryContext @Deprecated - @SuppressWarnings({"deprecation"}) + @SuppressWarnings({"deprecation", "InlineMeSuggester"}) public static @NotNull ISentryLifecycleToken setCurrentHub(final @NotNull IHub hub) { return setCurrentScopes(hub); } diff --git a/sentry/src/main/java/io/sentry/protocol/Contexts.java b/sentry/src/main/java/io/sentry/protocol/Contexts.java index 21be9fd8a58..aa157e665e7 100644 --- a/sentry/src/main/java/io/sentry/protocol/Contexts.java +++ b/sentry/src/main/java/io/sentry/protocol/Contexts.java @@ -1,5 +1,6 @@ package io.sentry.protocol; +import com.jakewharton.nopen.annotation.Open; import io.sentry.ILogger; import io.sentry.JsonDeserializer; import io.sentry.JsonObjectReader; @@ -17,7 +18,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public final class Contexts extends ConcurrentHashMap implements JsonSerializable { +@Open +public class Contexts extends ConcurrentHashMap implements JsonSerializable { private static final long serialVersionUID = 252445813254943011L; /** Response lock, Ops should be atomic */