io.sentry.protocol.SentryThread Maven / Gradle / Ivy
package io.sentry.protocol;
import io.sentry.ILogger;
import io.sentry.JsonDeserializer;
import io.sentry.JsonSerializable;
import io.sentry.JsonUnknown;
import io.sentry.ObjectReader;
import io.sentry.ObjectWriter;
import io.sentry.SentryLockReason;
import io.sentry.vendor.gson.stream.JsonToken;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A process thread of an event.
*
* The Threads Interface specifies threads that were running at the time an event happened. These
* threads can also contain stack traces.
*
*
An event may contain one or more threads in an attribute named `threads`.
*
*
The following example illustrates the threads part of the event payload and omits other
* attributes for simplicity.
*
*
```json { "threads": { "values": [ { "id": "0", "name": "main", "crashed": true, "stacktrace":
* {} } ] } } ```
*/
public final class SentryThread implements JsonUnknown, JsonSerializable {
private @Nullable Long id;
private @Nullable Integer priority;
private @Nullable String name;
private @Nullable String state;
private @Nullable Boolean crashed;
private @Nullable Boolean current;
private @Nullable Boolean daemon;
private @Nullable Boolean main;
private @Nullable SentryStackTrace stacktrace;
private @Nullable Map heldLocks;
@SuppressWarnings("unused")
private @Nullable Map unknown;
/**
* Gets the Id of the thread.
*
* @return the thread id.
*/
public @Nullable Long getId() {
return id;
}
/**
* Sets the Id of the thread.
*
* @param id the thread id.
*/
public void setId(final @Nullable Long id) {
this.id = id;
}
/**
* Gets the name of the thread.
*
* @return the name of the thread.
*/
public @Nullable String getName() {
return name;
}
/**
* Sets the name of the thread.
*
* @param name the name of the thread.
*/
public void setName(final @Nullable String name) {
this.name = name;
}
/**
* Gets whether the crash happened on this thread.
*
* @return whether it was the crashed thread.
*/
public @Nullable Boolean isCrashed() {
return crashed;
}
/**
* Sets whether the crash happened on this thread.
*
* @param crashed whether it was the crashed thread.
*/
public void setCrashed(final @Nullable Boolean crashed) {
this.crashed = crashed;
}
/**
* Get an optional flag to indicate that the thread was in the foreground.
*
* @return whether the thread was in the foreground.
*/
public @Nullable Boolean isCurrent() {
return current;
}
/**
* Sets an optional flag to indicate that the thread was in the foreground.
*
* @param current whether the thread was in the foreground.
*/
public void setCurrent(final @Nullable Boolean current) {
this.current = current;
}
/**
* Gets the stacktrace of the thread.
*
* @return the thread stacktrace.
*/
public @Nullable SentryStackTrace getStacktrace() {
return stacktrace;
}
/**
* Sets the stacktrace of the thread.
*
* @param stacktrace the thread stacktrace.
*/
public void setStacktrace(final @Nullable SentryStackTrace stacktrace) {
this.stacktrace = stacktrace;
}
/**
* Gets the priority of the thread.
*
* @return the thread priority.
*/
public @Nullable Integer getPriority() {
return priority;
}
/**
* Sets the priority of the thread.
*
* @param priority of the thread.
*/
public void setPriority(final @Nullable Integer priority) {
this.priority = priority;
}
/**
* Gets if this thread is a daemon thread.
*
* @return if this is a daemon thread.
*/
public @Nullable Boolean isDaemon() {
return daemon;
}
/**
* Sets if this is a daemon thread.
*
* @param daemon true if the thread is daemon thread. Otherwise false.
*/
public void setDaemon(final @Nullable Boolean daemon) {
this.daemon = daemon;
}
/**
* If applicable, a flag indicating whether the thread was responsible for rendering the user
* interface. On mobile platforms this is oftentimes referred to as the "main thread" or "ui
* thread".
*
* @return if its the main thread or not
*/
@Nullable
public Boolean isMain() {
return main;
}
/**
* If applicable, a flag indicating whether the thread was responsible for rendering the user
* interface. On mobile platforms this is oftentimes referred to as the "main thread" or "ui
* thread".
*
* @param main if its the main thread or not
*/
public void setMain(final @Nullable Boolean main) {
this.main = main;
}
/**
* Gets the state of the thread.
*
* @return the state of the thread.
*/
public @Nullable String getState() {
return state;
}
/**
* Sets the state of the thread.
*
* @param state the state of the thread.
*/
public void setState(final @Nullable String state) {
this.state = state;
}
/**
* Gets locks held by this thread.
*
* @return locks held by this thread
*/
public @Nullable Map getHeldLocks() {
return heldLocks;
}
/**
* Sets locks held by this thread.
*
* @param heldLocks list of locks held by this thread
*/
public void setHeldLocks(final @Nullable Map heldLocks) {
this.heldLocks = heldLocks;
}
// region json
@Nullable
@Override
public Map getUnknown() {
return unknown;
}
@Override
public void setUnknown(@Nullable Map unknown) {
this.unknown = unknown;
}
public static final class JsonKeys {
public static final String ID = "id";
public static final String PRIORITY = "priority";
public static final String NAME = "name";
public static final String STATE = "state";
public static final String CRASHED = "crashed";
public static final String CURRENT = "current";
public static final String DAEMON = "daemon";
public static final String MAIN = "main";
public static final String STACKTRACE = "stacktrace";
public static final String HELD_LOCKS = "held_locks";
}
@Override
public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger)
throws IOException {
writer.beginObject();
if (id != null) {
writer.name(JsonKeys.ID).value(id);
}
if (priority != null) {
writer.name(JsonKeys.PRIORITY).value(priority);
}
if (name != null) {
writer.name(JsonKeys.NAME).value(name);
}
if (state != null) {
writer.name(JsonKeys.STATE).value(state);
}
if (crashed != null) {
writer.name(JsonKeys.CRASHED).value(crashed);
}
if (current != null) {
writer.name(JsonKeys.CURRENT).value(current);
}
if (daemon != null) {
writer.name(JsonKeys.DAEMON).value(daemon);
}
if (main != null) {
writer.name(JsonKeys.MAIN).value(main);
}
if (stacktrace != null) {
writer.name(JsonKeys.STACKTRACE).value(logger, stacktrace);
}
if (heldLocks != null) {
writer.name(JsonKeys.HELD_LOCKS).value(logger, heldLocks);
}
if (unknown != null) {
for (String key : unknown.keySet()) {
Object value = unknown.get(key);
writer.name(key);
writer.value(logger, value);
}
}
writer.endObject();
}
public static final class Deserializer implements JsonDeserializer {
@SuppressWarnings("unchecked")
@Override
public @NotNull SentryThread deserialize(@NotNull ObjectReader reader, @NotNull ILogger logger)
throws Exception {
SentryThread sentryThread = new SentryThread();
Map unknown = null;
reader.beginObject();
while (reader.peek() == JsonToken.NAME) {
final String nextName = reader.nextName();
switch (nextName) {
case JsonKeys.ID:
sentryThread.id = reader.nextLongOrNull();
break;
case JsonKeys.PRIORITY:
sentryThread.priority = reader.nextIntegerOrNull();
break;
case JsonKeys.NAME:
sentryThread.name = reader.nextStringOrNull();
break;
case JsonKeys.STATE:
sentryThread.state = reader.nextStringOrNull();
break;
case JsonKeys.CRASHED:
sentryThread.crashed = reader.nextBooleanOrNull();
break;
case JsonKeys.CURRENT:
sentryThread.current = reader.nextBooleanOrNull();
break;
case JsonKeys.DAEMON:
sentryThread.daemon = reader.nextBooleanOrNull();
break;
case JsonKeys.MAIN:
sentryThread.main = reader.nextBooleanOrNull();
break;
case JsonKeys.STACKTRACE:
sentryThread.stacktrace =
reader.nextOrNull(logger, new SentryStackTrace.Deserializer());
break;
case JsonKeys.HELD_LOCKS:
final Map heldLocks =
reader.nextMapOrNull(logger, new SentryLockReason.Deserializer());
if (heldLocks != null) {
sentryThread.heldLocks = new HashMap<>(heldLocks);
}
break;
default:
if (unknown == null) {
unknown = new ConcurrentHashMap<>();
}
reader.nextUnknown(logger, unknown, nextName);
break;
}
}
sentryThread.setUnknown(unknown);
reader.endObject();
return sentryThread;
}
}
// endregion
}