Skip to content
This repository has been archived by the owner on Aug 30, 2023. It is now read-only.

fix(sentry-java): Contexts belong on the Scope #504

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 4 additions & 31 deletions sentry-core/src/main/java/io/sentry/core/Breadcrumb.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.sentry.core;

import io.sentry.core.util.CollectionUtils;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -188,7 +188,7 @@ public void setLevel(@Nullable SentryLevel level) {
@ApiStatus.Internal
@Override
public void acceptUnknownProperties(@Nullable Map<String, Object> unknown) {
this.unknown = unknown;
this.unknown = new ConcurrentHashMap<>(unknown);
}

/**
Expand All @@ -212,35 +212,8 @@ Map<String, Object> getUnknown() {
public @NotNull Breadcrumb clone() throws CloneNotSupportedException {
final Breadcrumb clone = (Breadcrumb) super.clone();

final Map<String, Object> dataRef = data;
if (dataRef != null) {
final Map<String, Object> dataClone = new ConcurrentHashMap<>();

for (Map.Entry<String, Object> item : dataRef.entrySet()) {
if (item != null) {
dataClone.put(item.getKey(), item.getValue()); // shallow copy
}
}

clone.data = dataClone;
} else {
clone.data = null;
}

final Map<String, Object> unknownRef = unknown;
if (unknownRef != null) {
final Map<String, Object> unknownClone = new HashMap<>();

for (Map.Entry<String, Object> item : unknownRef.entrySet()) {
if (item != null) {
unknownClone.put(item.getKey(), item.getValue()); // shallow copy
}
}

clone.unknown = unknownClone;
} else {
clone.unknown = null;
}
clone.data = CollectionUtils.shallowCopy(data);
clone.unknown = CollectionUtils.shallowCopy(unknown);
maciejwalkowiak marked this conversation as resolved.
Show resolved Hide resolved

final SentryLevel levelRef = level;
clone.level =
Expand Down
30 changes: 27 additions & 3 deletions sentry-core/src/main/java/io/sentry/core/Scope.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package io.sentry.core;

import io.sentry.core.protocol.Contexts;
import io.sentry.core.protocol.User;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
Expand Down Expand Up @@ -50,6 +50,9 @@ public final class Scope implements Cloneable {
/** Session lock, Ops should be atomic */
private final @NotNull Object sessionLock = new Object();

/** Scope's contexts */
private @NotNull Contexts contexts = new Contexts();

/**
* Scope's ctor
*
Expand Down Expand Up @@ -125,7 +128,7 @@ List<String> getFingerprint() {
}

/**
* Sets the Scoope's fingerprint list
* Sets the Scope's fingerprint list
*
* @param fingerprint the fingerprint list
*/
Expand Down Expand Up @@ -278,6 +281,25 @@ public void removeExtra(@NotNull String key) {
this.extra.remove(key);
}

/**
* Returns the Scope's contexts
*
* @return the contexts
*/
public @NotNull Contexts getContexts() {
bruno-garcia marked this conversation as resolved.
Show resolved Hide resolved
return contexts;
}

/**
* Sets the Scope's contexts
*
* @param key the context key
* @param value the context value
*/
public void setContexts(final @NotNull String key, final @NotNull Object value) {
this.contexts.put(key, value);
}

/**
* Creates a breadcrumb list with the max number of breadcrumbs
*
Expand Down Expand Up @@ -332,7 +354,7 @@ public void removeExtra(@NotNull String key) {

final Map<String, Object> extraRef = extra;

Map<String, Object> extraClone = new HashMap<>();
Map<String, Object> extraClone = new ConcurrentHashMap<>();
marandaneto marked this conversation as resolved.
Show resolved Hide resolved

for (Map.Entry<String, Object> item : extraRef.entrySet()) {
if (item != null) {
Expand All @@ -342,6 +364,8 @@ public void removeExtra(@NotNull String key) {

clone.extra = extraClone;

clone.contexts = contexts.clone();

return clone;
}

Expand Down
11 changes: 11 additions & 0 deletions sentry-core/src/main/java/io/sentry/core/SentryClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,17 @@ public void captureSession(final @NotNull Session session, final @Nullable Objec
}
}
}
try {
for (Map.Entry<String, Object> entry : scope.getContexts().clone().entrySet()) {
if (!event.getContexts().containsKey(entry.getKey())) {
event.getContexts().put(entry.getKey(), entry.getValue());
}
}
} catch (CloneNotSupportedException e) {
options
.getLogger()
.log(SentryLevel.ERROR, "An error has occurred when cloning Contexts", e);
}
// Level from scope exceptionally take precedence over the event
if (scope.getLevel() != null) {
event.setLevel(scope.getLevel());
Expand Down
28 changes: 26 additions & 2 deletions sentry-core/src/main/java/io/sentry/core/protocol/App.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package io.sentry.core.protocol;

import io.sentry.core.IUnknownPropertiesConsumer;
import io.sentry.core.util.CollectionUtils;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;

public final class App implements IUnknownPropertiesConsumer {
public final class App implements IUnknownPropertiesConsumer, Cloneable {
public static final String TYPE = "app";

private String appIdentifier;
Expand Down Expand Up @@ -77,9 +81,29 @@ public void setAppBuild(String appBuild) {
this.appBuild = appBuild;
}

@TestOnly
Map<String, Object> getUnknown() {
return unknown;
}

@ApiStatus.Internal
@Override
public void acceptUnknownProperties(Map<String, Object> unknown) {
this.unknown = unknown;
this.unknown = new ConcurrentHashMap<>(unknown);
}

/**
* Clones an App aka deep copy
*
* @return the cloned App
* @throws CloneNotSupportedException if object is not cloneable
*/
@Override
public @NotNull App clone() throws CloneNotSupportedException {
final App clone = (App) super.clone();
bruno-garcia marked this conversation as resolved.
Show resolved Hide resolved

clone.unknown = CollectionUtils.shallowCopy(unknown);

return clone;
}
}
28 changes: 26 additions & 2 deletions sentry-core/src/main/java/io/sentry/core/protocol/Browser.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package io.sentry.core.protocol;

import io.sentry.core.IUnknownPropertiesConsumer;
import io.sentry.core.util.CollectionUtils;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;

public final class Browser implements IUnknownPropertiesConsumer {
public final class Browser implements IUnknownPropertiesConsumer, Cloneable {
public static final String TYPE = "browser";
private String name;
private String version;
Expand All @@ -28,9 +32,29 @@ public void setVersion(String version) {
this.version = version;
}

@TestOnly
Map<String, Object> getUnknown() {
return unknown;
}

@ApiStatus.Internal
@Override
public void acceptUnknownProperties(Map<String, Object> unknown) {
this.unknown = unknown;
this.unknown = new ConcurrentHashMap<>(unknown);
}

/**
* Clones a Browser aka deep copy
*
* @return the cloned Browser
* @throws CloneNotSupportedException if object is not cloneable
*/
@Override
public @NotNull Browser clone() throws CloneNotSupportedException {
final Browser clone = (Browser) super.clone();

clone.unknown = CollectionUtils.shallowCopy(unknown);
bruno-garcia marked this conversation as resolved.
Show resolved Hide resolved

return clone;
}
}
33 changes: 32 additions & 1 deletion sentry-core/src/main/java/io/sentry/core/protocol/Contexts.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package io.sentry.core.protocol;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jetbrains.annotations.NotNull;

public final class Contexts extends ConcurrentHashMap<String, Object> {
public final class Contexts extends ConcurrentHashMap<String, Object> implements Cloneable {
private static final long serialVersionUID = 252445813254943011L;

private <T> T toContextType(String key, Class<T> clazz) {
Expand Down Expand Up @@ -57,4 +59,33 @@ public Gpu getGpu() {
public void setGpu(Gpu gpu) {
this.put(Gpu.TYPE, gpu);
}

@Override
public @NotNull Contexts clone() throws CloneNotSupportedException {
final Contexts clone = new Contexts();

for (Map.Entry<String, Object> entry : entrySet()) {
if (entry != null) {
Object value = entry.getValue();
if (App.TYPE.equals(entry.getKey()) && value instanceof App) {
clone.setApp(((App) value).clone());
} else if (Browser.TYPE.equals(entry.getKey()) && value instanceof Browser) {
clone.setBrowser(((Browser) value).clone());
} else if (Device.TYPE.equals(entry.getKey()) && value instanceof Device) {
clone.setDevice(((Device) value).clone());
} else if (OperatingSystem.TYPE.equals(entry.getKey())
&& value instanceof OperatingSystem) {
clone.setOperatingSystem(((OperatingSystem) value).clone());
} else if (SentryRuntime.TYPE.equals(entry.getKey()) && value instanceof SentryRuntime) {
clone.setRuntime(((SentryRuntime) value).clone());
} else if (Gpu.TYPE.equals(entry.getKey()) && value instanceof Gpu) {
clone.setGpu(((Gpu) value).clone());
} else {
clone.put(entry.getKey(), value);
}
}
}

return clone;
}
}
34 changes: 32 additions & 2 deletions sentry-core/src/main/java/io/sentry/core/protocol/Device.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package io.sentry.core.protocol;

import io.sentry.core.IUnknownPropertiesConsumer;
import io.sentry.core.util.CollectionUtils;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;

public final class Device implements IUnknownPropertiesConsumer {
public final class Device implements IUnknownPropertiesConsumer, Cloneable {
public static final String TYPE = "device";

private String name;
Expand Down Expand Up @@ -343,9 +347,35 @@ public enum DeviceOrientation {
LANDSCAPE
}

@TestOnly
Map<String, Object> getUnknown() {
return unknown;
}

@ApiStatus.Internal
@Override
public void acceptUnknownProperties(Map<String, Object> unknown) {
this.unknown = unknown;
this.unknown = new ConcurrentHashMap<>(unknown);
}

/**
* Clones a Device aka deep copy
*
* @return the cloned Device
* @throws CloneNotSupportedException if object is not cloneable
*/
@Override
public @NotNull Device clone() throws CloneNotSupportedException {
final Device clone = (Device) super.clone();

final String[] archsRef = this.archs;
clone.archs = archsRef != null ? this.archs.clone() : null;

final TimeZone timezoneRef = this.timezone;
clone.timezone = timezoneRef != null ? (TimeZone) this.timezone.clone() : null;

maciejwalkowiak marked this conversation as resolved.
Show resolved Hide resolved
clone.unknown = CollectionUtils.shallowCopy(unknown);

return clone;
}
}
28 changes: 26 additions & 2 deletions sentry-core/src/main/java/io/sentry/core/protocol/Gpu.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package io.sentry.core.protocol;

import io.sentry.core.IUnknownPropertiesConsumer;
import io.sentry.core.util.CollectionUtils;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;

public final class Gpu implements IUnknownPropertiesConsumer {
public final class Gpu implements IUnknownPropertiesConsumer, Cloneable {
public static final String TYPE = "gpu";

private String name;
Expand Down Expand Up @@ -92,9 +96,29 @@ public void setNpotSupport(String npotSupport) {
this.npotSupport = npotSupport;
}

@TestOnly
Map<String, Object> getUnknown() {
return unknown;
}

@ApiStatus.Internal
@Override
public void acceptUnknownProperties(Map<String, Object> unknown) {
this.unknown = unknown;
this.unknown = new ConcurrentHashMap<>(unknown);
}

/**
* Clones a Gpu aka deep copy
*
* @return the cloned Gpu
* @throws CloneNotSupportedException if object is not cloneable
*/
@Override
public @NotNull Gpu clone() throws CloneNotSupportedException {
final Gpu clone = (Gpu) super.clone();

clone.unknown = CollectionUtils.shallowCopy(unknown);

return clone;
}
}
Loading