Skip to content

Commit 62e71ff

Browse files
committed
added Feedback class and extended Contexts with it
1 parent b61429a commit 62e71ff

File tree

2 files changed

+185
-0
lines changed

2 files changed

+185
-0
lines changed

sentry/src/main/java/io/sentry/protocol/Contexts.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ public Contexts(final @NotNull Contexts contexts) {
5151
this.setOperatingSystem(new OperatingSystem((OperatingSystem) value));
5252
} else if (SentryRuntime.TYPE.equals(entry.getKey()) && value instanceof SentryRuntime) {
5353
this.setRuntime(new SentryRuntime((SentryRuntime) value));
54+
} else if (Feedback.TYPE.equals(entry.getKey()) && value instanceof Feedback) {
55+
this.setFeedback(new Feedback((Feedback) value));
5456
} else if (Gpu.TYPE.equals(entry.getKey()) && value instanceof Gpu) {
5557
this.setGpu(new Gpu((Gpu) value));
5658
} else if (SpanContext.TYPE.equals(entry.getKey()) && value instanceof SpanContext) {
@@ -120,6 +122,14 @@ public void setRuntime(final @NotNull SentryRuntime runtime) {
120122
this.put(SentryRuntime.TYPE, runtime);
121123
}
122124

125+
public @Nullable Feedback getFeedback() {
126+
return toContextType(Feedback.TYPE, Feedback.class);
127+
}
128+
129+
public void setFeedback(final @NotNull Feedback feedback) {
130+
this.put(Feedback.TYPE, feedback);
131+
}
132+
123133
public @Nullable Gpu getGpu() {
124134
return toContextType(Gpu.TYPE, Gpu.class);
125135
}
@@ -302,6 +312,9 @@ public static final class Deserializer implements JsonDeserializer<Contexts> {
302312
case SentryRuntime.TYPE:
303313
contexts.setRuntime(new SentryRuntime.Deserializer().deserialize(reader, logger));
304314
break;
315+
case Feedback.TYPE:
316+
contexts.setFeedback(new Feedback.Deserializer().deserialize(reader, logger));
317+
break;
305318
case SpanContext.TYPE:
306319
contexts.setTrace(new SpanContext.Deserializer().deserialize(reader, logger));
307320
break;
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package io.sentry.protocol;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
import org.jetbrains.annotations.Nullable;
5+
6+
import java.io.IOException;
7+
import java.util.HashMap;
8+
import java.util.Map;
9+
10+
import io.sentry.ILogger;
11+
import io.sentry.JsonDeserializer;
12+
import io.sentry.JsonSerializable;
13+
import io.sentry.JsonUnknown;
14+
import io.sentry.ObjectReader;
15+
import io.sentry.ObjectWriter;
16+
import io.sentry.SentryLevel;
17+
import io.sentry.vendor.gson.stream.JsonToken;
18+
19+
// Specs can be found at https://develop.sentry.dev/sdk/data-model/envelope-items/#user-feedback
20+
21+
public class Feedback implements JsonUnknown, JsonSerializable {
22+
public static final String TYPE = "feedback";
23+
24+
final @NotNull String message;
25+
final @Nullable String contactEmail;
26+
final @Nullable String name;
27+
final @Nullable SentryId associatedEventId;
28+
final @Nullable SentryId replayId;
29+
final @Nullable String url;
30+
31+
private @Nullable Map<String, Object> unknown;
32+
33+
public Feedback(
34+
final @NotNull String message,
35+
final @Nullable String contactEmail,
36+
final @Nullable String name,
37+
final @Nullable SentryId associatedEventId,
38+
final @Nullable SentryId replayId,
39+
final @Nullable String url) {
40+
this.message = message;
41+
this.contactEmail = contactEmail;
42+
this.name = name;
43+
this.associatedEventId = associatedEventId;
44+
this.replayId = replayId;
45+
this.url = url;
46+
}
47+
48+
public Feedback(final @NotNull Feedback feedback) {
49+
this.message = feedback.message;
50+
this.contactEmail = feedback.contactEmail;
51+
this.name = feedback.name;
52+
this.associatedEventId = feedback.associatedEventId;
53+
this.replayId = feedback.replayId;
54+
this.url = feedback.url;
55+
this.unknown = feedback.unknown;
56+
}
57+
58+
// JsonKeys
59+
60+
public static final class JsonKeys {
61+
public static final String MESSAGE = "message";
62+
public static final String CONTACT_EMAIL = "contact_email";
63+
public static final String NAME = "name";
64+
public static final String ASSOCIATED_EVENT_ID = "associated_event_id";
65+
public static final String REPLAY_ID = "replay_id";
66+
public static final String URL = "url";
67+
}
68+
69+
// JsonUnknown
70+
71+
@Override
72+
public @Nullable Map<String, Object> getUnknown() {
73+
return unknown;
74+
}
75+
76+
@Override
77+
public void setUnknown(@Nullable Map<String, Object> unknown) {
78+
this.unknown = unknown;
79+
}
80+
81+
// JsonSerializable
82+
83+
@Override
84+
public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger)
85+
throws IOException {
86+
writer.beginObject();
87+
writer.name(JsonKeys.MESSAGE).value(message);
88+
if (contactEmail != null) {
89+
writer.name(JsonKeys.CONTACT_EMAIL).value(contactEmail);
90+
}
91+
if (name != null) {
92+
writer.name(JsonKeys.NAME).value(name);
93+
}
94+
if (associatedEventId != null) {
95+
writer.name(JsonKeys.ASSOCIATED_EVENT_ID);
96+
associatedEventId.serialize(writer, logger);
97+
}
98+
if (replayId != null) {
99+
writer.name(JsonKeys.REPLAY_ID);
100+
replayId.serialize(writer, logger);
101+
}
102+
if (url != null) {
103+
writer.name(JsonKeys.URL).value(url);
104+
}
105+
if (unknown != null) {
106+
for (String key : unknown.keySet()) {
107+
Object value = unknown.get(key);
108+
writer.name(key).value(logger, value);
109+
}
110+
}
111+
writer.endObject();
112+
}
113+
114+
// JsonDeserializer
115+
116+
public static final class Deserializer implements JsonDeserializer<Feedback> {
117+
@Override
118+
public @NotNull Feedback deserialize(@NotNull ObjectReader reader, @NotNull ILogger logger)
119+
throws Exception {
120+
@Nullable String message = null;
121+
@Nullable String contactEmail = null;
122+
@Nullable String name = null;
123+
@Nullable SentryId associatedEventId = null;
124+
@Nullable SentryId replayId = null;
125+
@Nullable String url = null;
126+
@Nullable Map<String, Object> unknown = null;
127+
128+
reader.beginObject();
129+
while (reader.peek() == JsonToken.NAME) {
130+
final String nextName = reader.nextName();
131+
switch (nextName) {
132+
case JsonKeys.MESSAGE:
133+
message = reader.nextStringOrNull();
134+
break;
135+
case JsonKeys.CONTACT_EMAIL:
136+
contactEmail = reader.nextStringOrNull();
137+
break;
138+
case JsonKeys.NAME:
139+
name = reader.nextStringOrNull();
140+
break;
141+
case JsonKeys.ASSOCIATED_EVENT_ID:
142+
associatedEventId = new SentryId.Deserializer().deserialize(reader, logger);
143+
break;
144+
case JsonKeys.REPLAY_ID:
145+
replayId = new SentryId.Deserializer().deserialize(reader, logger);
146+
break;
147+
case JsonKeys.URL:
148+
url = reader.nextStringOrNull();
149+
break;
150+
default:
151+
if (unknown == null) {
152+
unknown = new HashMap<>();
153+
}
154+
reader.nextUnknown(logger, unknown, nextName);
155+
break;
156+
}
157+
}
158+
reader.endObject();
159+
160+
if (message == null) {
161+
String errorMessage = "Missing required field \"" + JsonKeys.MESSAGE + "\"";
162+
Exception exception = new IllegalStateException(errorMessage);
163+
logger.log(SentryLevel.ERROR, errorMessage, exception);
164+
throw exception;
165+
}
166+
167+
Feedback feedback = new Feedback(message, contactEmail, name, associatedEventId, replayId, url);
168+
feedback.setUnknown(unknown);
169+
return feedback;
170+
}
171+
}
172+
}

0 commit comments

Comments
 (0)