diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8f2234f1b32..822f3210930 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
- Add `lock` attribute to the `SentryStackFrame` protocol to better highlight offending frames in the UI ([#2761](https://github.com/getsentry/sentry-java/pull/2761))
- Enrich database spans with blocked main thread info ([#2760](https://github.com/getsentry/sentry-java/pull/2760))
+- Add `api_target` to `Request` and `data` to `Response` Protocols ([#2760](https://github.com/getsentry/sentry-java/pull/2760))
## 6.21.0
diff --git a/sentry/src/main/java/io/sentry/protocol/Request.java b/sentry/src/main/java/io/sentry/protocol/Request.java
index 2e51a231979..188a17c3453 100644
--- a/sentry/src/main/java/io/sentry/protocol/Request.java
+++ b/sentry/src/main/java/io/sentry/protocol/Request.java
@@ -109,6 +109,15 @@ public final class Request implements JsonUnknown, JsonSerializable {
/** The fragment (anchor) of the request URL. */
private @Nullable String fragment;
+ /**
+ * The API target/specification that made the request.
+ *
+ * Values can be `graphql`, `rest`, etc.
+ *
+ * The data field should contain the request and response bodies based on its target specification.
+ * */
+ private @Nullable String apiTarget;
+
@SuppressWarnings("unused")
private @Nullable Map unknown;
@@ -126,6 +135,7 @@ public Request(final @NotNull Request request) {
this.data = request.data;
this.fragment = request.fragment;
this.bodySize = request.bodySize;
+ this.apiTarget = request.apiTarget;
}
public @Nullable String getUrl() {
@@ -220,12 +230,13 @@ public boolean equals(Object o) {
&& Objects.equals(headers, request.headers)
&& Objects.equals(env, request.env)
&& Objects.equals(bodySize, request.bodySize)
- && Objects.equals(fragment, request.fragment);
+ && Objects.equals(fragment, request.fragment)
+ && Objects.equals(apiTarget, request.getApiTarget());
}
@Override
public int hashCode() {
- return Objects.hash(url, method, queryString, cookies, headers, env, bodySize, fragment);
+ return Objects.hash(url, method, queryString, cookies, headers, env, bodySize, fragment, apiTarget);
}
// region json
@@ -241,6 +252,14 @@ public void setUnknown(@Nullable Map unknown) {
this.unknown = unknown;
}
+ public @Nullable String getApiTarget() {
+ return apiTarget;
+ }
+
+ public void setApiTarget(final @Nullable String apiTarget) {
+ this.apiTarget = apiTarget;
+ }
+
public static final class JsonKeys {
public static final String URL = "url";
public static final String METHOD = "method";
@@ -252,6 +271,7 @@ public static final class JsonKeys {
public static final String OTHER = "other";
public static final String FRAGMENT = "fragment";
public static final String BODY_SIZE = "body_size";
+ public static final String API_TARGET = "api_target";
}
@Override
@@ -286,7 +306,10 @@ public void serialize(@NotNull JsonObjectWriter writer, @NotNull ILogger logger)
writer.name(JsonKeys.FRAGMENT).value(logger, fragment);
}
if (bodySize != null) {
- writer.name(Response.JsonKeys.BODY_SIZE).value(logger, bodySize);
+ writer.name(JsonKeys.BODY_SIZE).value(logger, bodySize);
+ }
+ if (apiTarget != null) {
+ writer.name(JsonKeys.API_TARGET).value(logger, apiTarget);
}
if (unknown != null) {
for (String key : unknown.keySet()) {
@@ -346,9 +369,12 @@ public static final class Deserializer implements JsonDeserializer {
case JsonKeys.FRAGMENT:
request.fragment = reader.nextStringOrNull();
break;
- case Response.JsonKeys.BODY_SIZE:
+ case JsonKeys.BODY_SIZE:
request.bodySize = reader.nextLongOrNull();
break;
+ case JsonKeys.API_TARGET:
+ request.apiTarget = reader.nextStringOrNull();
+ break;
default:
if (unknown == null) {
unknown = new ConcurrentHashMap<>();
diff --git a/sentry/src/main/java/io/sentry/protocol/Response.java b/sentry/src/main/java/io/sentry/protocol/Response.java
index d34b605d2d0..f46ad369a35 100644
--- a/sentry/src/main/java/io/sentry/protocol/Response.java
+++ b/sentry/src/main/java/io/sentry/protocol/Response.java
@@ -37,6 +37,14 @@ public final class Response implements JsonUnknown, JsonSerializable {
/** The body size in bytes */
private @Nullable Long bodySize;
+ /**
+ * Response data in any format that makes sense.
+ *
+ * SDKs should discard large and binary bodies by default. Can be given as a string or
+ * structural data of any format.
+ */
+ private @Nullable Object data;
+
@SuppressWarnings("unused")
private @Nullable Map unknown;
@@ -48,6 +56,7 @@ public Response(final @NotNull Response response) {
this.unknown = CollectionUtils.newConcurrentHashMap(response.unknown);
this.statusCode = response.statusCode;
this.bodySize = response.bodySize;
+ this.data = response.data;
}
public @Nullable String getCookies() {
@@ -93,6 +102,14 @@ public void setBodySize(final @Nullable Long bodySize) {
this.bodySize = bodySize;
}
+ public @Nullable Object getData() {
+ return data;
+ }
+
+ public void setData(final @Nullable Object data) {
+ this.data = data;
+ }
+
// region json
public static final class JsonKeys {
@@ -100,6 +117,7 @@ public static final class JsonKeys {
public static final String HEADERS = "headers";
public static final String STATUS_CODE = "status_code";
public static final String BODY_SIZE = "body_size";
+ public static final String DATA = "data";
}
@Override
@@ -119,7 +137,9 @@ public void serialize(final @NotNull JsonObjectWriter writer, final @NotNull ILo
if (bodySize != null) {
writer.name(JsonKeys.BODY_SIZE).value(logger, bodySize);
}
-
+ if (data != null) {
+ writer.name(JsonKeys.DATA).value(logger, data);
+ }
if (unknown != null) {
for (final String key : unknown.keySet()) {
final Object value = unknown.get(key);
@@ -157,6 +177,9 @@ public static final class Deserializer implements JsonDeserializer {
case JsonKeys.BODY_SIZE:
response.bodySize = reader.nextLongOrNull();
break;
+ case JsonKeys.DATA:
+ response.data = reader.nextObjectOrNull();
+ break;
default:
if (unknown == null) {
unknown = new ConcurrentHashMap<>();
diff --git a/sentry/src/test/java/io/sentry/protocol/RequestSerializationTest.kt b/sentry/src/test/java/io/sentry/protocol/RequestSerializationTest.kt
index 973c661b336..4aaa5423c34 100644
--- a/sentry/src/test/java/io/sentry/protocol/RequestSerializationTest.kt
+++ b/sentry/src/test/java/io/sentry/protocol/RequestSerializationTest.kt
@@ -29,6 +29,7 @@ class RequestSerializationTest {
)
bodySize = 1000
fragment = "fragment"
+ apiTarget = "graphql"
}
}
private val fixture = Fixture()
diff --git a/sentry/src/test/java/io/sentry/protocol/RequestTest.kt b/sentry/src/test/java/io/sentry/protocol/RequestTest.kt
index 2acb3316d66..5cf1d68aaef 100644
--- a/sentry/src/test/java/io/sentry/protocol/RequestTest.kt
+++ b/sentry/src/test/java/io/sentry/protocol/RequestTest.kt
@@ -35,6 +35,7 @@ class RequestTest {
assertEquals("unknown", clone.unknown!!["unknown"])
assertEquals(1000, clone.bodySize)
assertEquals("fragment", clone.fragment)
+ assertEquals("graphql", clone.apiTarget)
}
@Test
@@ -52,6 +53,7 @@ class RequestTest {
request.unknown = newUnknown
request.bodySize = 1001
request.fragment = "fragment2"
+ request.apiTarget = "graphql"
assertEquals("get", clone.method)
assertEquals("http://localhost:8080", clone.url)
@@ -64,6 +66,7 @@ class RequestTest {
assertEquals(1, clone.unknown!!.size)
assertEquals(1000, clone.bodySize)
assertEquals("fragment", clone.fragment)
+ assertEquals("graphql", clone.apiTarget)
}
@Test
@@ -119,6 +122,7 @@ class RequestTest {
setUnknown(unknown)
bodySize = 1000
fragment = "fragment"
+ apiTarget = "graphql"
}
}
}
diff --git a/sentry/src/test/java/io/sentry/protocol/ResponseSerializationTest.kt b/sentry/src/test/java/io/sentry/protocol/ResponseSerializationTest.kt
index 203b697aec1..e278813d8df 100644
--- a/sentry/src/test/java/io/sentry/protocol/ResponseSerializationTest.kt
+++ b/sentry/src/test/java/io/sentry/protocol/ResponseSerializationTest.kt
@@ -14,6 +14,9 @@ class ResponseSerializationTest {
headers = mapOf("content-type" to "text/html")
statusCode = 500
bodySize = 1000
+ data = mapOf(
+ "d9d709db-b666-40cc-bcbb-093bb12aad26" to "1631d0e6-96b7-4632-85f8-ef69e8bcfb16"
+ )
unknown = mapOf("arbitrary_field" to "arbitrary")
}
}
diff --git a/sentry/src/test/resources/json/request.json b/sentry/src/test/resources/json/request.json
index d0eb6d9735e..d744deac62a 100644
--- a/sentry/src/test/resources/json/request.json
+++ b/sentry/src/test/resources/json/request.json
@@ -20,5 +20,6 @@
"669ff1c1-517b-46dc-a889-131555364a56": "89043294-f6e1-4e2e-b152-1fdf9b1102fc"
},
"fragment": "fragment",
- "body_size": 1000
+ "body_size": 1000,
+ "api_target": "graphql"
}
diff --git a/sentry/src/test/resources/json/response.json b/sentry/src/test/resources/json/response.json
index 9faf2b41838..af7d4ab7670 100644
--- a/sentry/src/test/resources/json/response.json
+++ b/sentry/src/test/resources/json/response.json
@@ -5,5 +5,9 @@
},
"status_code": 500,
"body_size": 1000,
+ "data":
+ {
+ "d9d709db-b666-40cc-bcbb-093bb12aad26": "1631d0e6-96b7-4632-85f8-ef69e8bcfb16"
+ },
"arbitrary_field": "arbitrary"
}