From 43ed5c92463202cc7be1bd8299051cca77b11b24 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 6 Jun 2023 15:07:15 +0200 Subject: [PATCH 1/5] Expand protocols to support GraphQL errors --- CHANGELOG.md | 1 + .../main/java/io/sentry/protocol/Request.java | 34 ++++++++++++++++--- .../java/io/sentry/protocol/Response.java | 25 +++++++++++++- .../protocol/RequestSerializationTest.kt | 1 + .../java/io/sentry/protocol/RequestTest.kt | 4 +++ .../protocol/ResponseSerializationTest.kt | 3 ++ sentry/src/test/resources/json/request.json | 3 +- sentry/src/test/resources/json/response.json | 4 +++ 8 files changed, 69 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f2234f1b3..822f321093 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 2e51a23197..188a17c345 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 d34b605d2d..f46ad369a3 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 973c661b33..4aaa5423c3 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 2acb3316d6..5cf1d68aae 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 203b697aec..e278813d8d 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 d0eb6d9735..d744deac62 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 9faf2b4183..af7d4ab767 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" } From d9447a583c5fb1efe17e921bfc0c9db47603f760 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Tue, 6 Jun 2023 13:11:23 +0000 Subject: [PATCH 2/5] Format code --- .../src/main/java/io/sentry/protocol/Request.java | 14 ++++++++------ .../src/main/java/io/sentry/protocol/Response.java | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/sentry/src/main/java/io/sentry/protocol/Request.java b/sentry/src/main/java/io/sentry/protocol/Request.java index 188a17c345..2b4f8a9a3d 100644 --- a/sentry/src/main/java/io/sentry/protocol/Request.java +++ b/sentry/src/main/java/io/sentry/protocol/Request.java @@ -111,11 +111,12 @@ public final class Request implements JsonUnknown, JsonSerializable { /** * 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. - * */ + * + *

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") @@ -236,7 +237,8 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(url, method, queryString, cookies, headers, env, bodySize, fragment, apiTarget); + return Objects.hash( + url, method, queryString, cookies, headers, env, bodySize, fragment, apiTarget); } // region json diff --git a/sentry/src/main/java/io/sentry/protocol/Response.java b/sentry/src/main/java/io/sentry/protocol/Response.java index f46ad369a3..dcfec08f46 100644 --- a/sentry/src/main/java/io/sentry/protocol/Response.java +++ b/sentry/src/main/java/io/sentry/protocol/Response.java @@ -39,8 +39,8 @@ public final class Response implements JsonUnknown, JsonSerializable { /** * Response data in any format that makes sense. - *

- * SDKs should discard large and binary bodies by default. Can be given as a string or + * + *

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; From efcf05cc663da1ab369d0dae8abf9324013769cc Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 6 Jun 2023 15:38:53 +0200 Subject: [PATCH 3/5] fix pr id --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 822f321093..5f12959872 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +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)) +- Add `api_target` to `Request` and `data` to `Response` Protocols ([#2775](https://github.com/getsentry/sentry-java/pull/2775)) ## 6.21.0 From 1817bed06792236d31a35b7c82cfc24f3f2ca1b2 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 6 Jun 2023 15:41:14 +0200 Subject: [PATCH 4/5] fix --- sentry/src/main/java/io/sentry/protocol/Request.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry/src/main/java/io/sentry/protocol/Request.java b/sentry/src/main/java/io/sentry/protocol/Request.java index 2b4f8a9a3d..8d5e0cda4b 100644 --- a/sentry/src/main/java/io/sentry/protocol/Request.java +++ b/sentry/src/main/java/io/sentry/protocol/Request.java @@ -232,7 +232,7 @@ public boolean equals(Object o) { && Objects.equals(env, request.env) && Objects.equals(bodySize, request.bodySize) && Objects.equals(fragment, request.fragment) - && Objects.equals(apiTarget, request.getApiTarget()); + && Objects.equals(apiTarget, request.apiTarget); } @Override From 1d0b774a293d14ee7b28a8217e8eb0da50ceec9d Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 6 Jun 2023 15:48:24 +0200 Subject: [PATCH 5/5] api target --- sentry/api/sentry.api | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 94a92dd72f..531f861838 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -3305,6 +3305,7 @@ public final class io/sentry/protocol/Request : io/sentry/JsonSerializable, io/s public fun ()V public fun (Lio/sentry/protocol/Request;)V public fun equals (Ljava/lang/Object;)Z + public fun getApiTarget ()Ljava/lang/String; public fun getBodySize ()Ljava/lang/Long; public fun getCookies ()Ljava/lang/String; public fun getData ()Ljava/lang/Object; @@ -3318,6 +3319,7 @@ public final class io/sentry/protocol/Request : io/sentry/JsonSerializable, io/s public fun getUrl ()Ljava/lang/String; public fun hashCode ()I public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V + public fun setApiTarget (Ljava/lang/String;)V public fun setBodySize (Ljava/lang/Long;)V public fun setCookies (Ljava/lang/String;)V public fun setData (Ljava/lang/Object;)V @@ -3338,6 +3340,7 @@ public final class io/sentry/protocol/Request$Deserializer : io/sentry/JsonDeser } public final class io/sentry/protocol/Request$JsonKeys { + public static final field API_TARGET Ljava/lang/String; public static final field BODY_SIZE Ljava/lang/String; public static final field COOKIES Ljava/lang/String; public static final field DATA Ljava/lang/String; @@ -3357,12 +3360,14 @@ public final class io/sentry/protocol/Response : io/sentry/JsonSerializable, io/ public fun (Lio/sentry/protocol/Response;)V public fun getBodySize ()Ljava/lang/Long; public fun getCookies ()Ljava/lang/String; + public fun getData ()Ljava/lang/Object; public fun getHeaders ()Ljava/util/Map; public fun getStatusCode ()Ljava/lang/Integer; public fun getUnknown ()Ljava/util/Map; public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V public fun setBodySize (Ljava/lang/Long;)V public fun setCookies (Ljava/lang/String;)V + public fun setData (Ljava/lang/Object;)V public fun setHeaders (Ljava/util/Map;)V public fun setStatusCode (Ljava/lang/Integer;)V public fun setUnknown (Ljava/util/Map;)V @@ -3377,6 +3382,7 @@ public final class io/sentry/protocol/Response$Deserializer : io/sentry/JsonDese public final class io/sentry/protocol/Response$JsonKeys { public static final field BODY_SIZE Ljava/lang/String; public static final field COOKIES Ljava/lang/String; + public static final field DATA Ljava/lang/String; public static final field HEADERS Ljava/lang/String; public static final field STATUS_CODE Ljava/lang/String; public fun ()V