From 1f53dd9160bb69f87d2698f22b3444859f306a10 Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Fri, 16 Aug 2024 14:47:38 +0200 Subject: [PATCH 1/2] add transaction/root-span data to traceContext, adapt tests --- sentry/api/sentry.api | 4 ++++ .../src/main/java/io/sentry/SpanContext.java | 23 +++++++++++++++++++ .../io/sentry/protocol/SentryTransaction.java | 10 +++++--- .../test/java/io/sentry/JsonSerializerTest.kt | 6 ++++- .../protocol/SpanContextSerializationTest.kt | 1 + sentry/src/test/resources/json/contexts.json | 4 ++++ .../resources/json/sentry_base_event.json | 4 ++++ .../sentry_base_event_with_null_extra.json | 4 ++++ .../src/test/resources/json/sentry_event.json | 4 ++++ .../resources/json/sentry_replay_event.json | 4 ++++ .../resources/json/sentry_transaction.json | 4 ++++ ...sentry_transaction_legacy_date_format.json | 4 ++++ ...entry_transaction_no_measurement_unit.json | 4 ++++ .../src/test/resources/json/span_context.json | 3 +++ 14 files changed, 75 insertions(+), 4 deletions(-) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 598b2c7b6bf..fde30282fc7 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -2941,6 +2941,7 @@ public final class io/sentry/Span : io/sentry/ISpan { public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonUnknown { public static final field TYPE Ljava/lang/String; + protected field data Ljava/util/Map; protected field description Ljava/lang/String; protected field op Ljava/lang/String; protected field origin Ljava/lang/String; @@ -2952,6 +2953,7 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU public fun (Ljava/lang/String;)V public fun (Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V public fun equals (Ljava/lang/Object;)Z + public fun getData ()Ljava/util/Map; public fun getDescription ()Ljava/lang/String; public fun getOperation ()Ljava/lang/String; public fun getOrigin ()Ljava/lang/String; @@ -2966,6 +2968,7 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU public fun getUnknown ()Ljava/util/Map; public fun hashCode ()I public fun serialize (Lio/sentry/ObjectWriter;Lio/sentry/ILogger;)V + public fun setData (Ljava/lang/String;Ljava/lang/Object;)V public fun setDescription (Ljava/lang/String;)V public fun setOperation (Ljava/lang/String;)V public fun setOrigin (Ljava/lang/String;)V @@ -2984,6 +2987,7 @@ public final class io/sentry/SpanContext$Deserializer : io/sentry/JsonDeserializ } public final class io/sentry/SpanContext$JsonKeys { + public static final field DATA Ljava/lang/String; public static final field DESCRIPTION Ljava/lang/String; public static final field OP Ljava/lang/String; public static final field ORIGIN Ljava/lang/String; diff --git a/sentry/src/main/java/io/sentry/SpanContext.java b/sentry/src/main/java/io/sentry/SpanContext.java index 5a43ff845e0..a4ea9331f11 100644 --- a/sentry/src/main/java/io/sentry/SpanContext.java +++ b/sentry/src/main/java/io/sentry/SpanContext.java @@ -46,6 +46,8 @@ public class SpanContext implements JsonUnknown, JsonSerializable { /** Describes the status of the Transaction. */ protected @Nullable String origin = "manual"; + protected @NotNull Map data = new ConcurrentHashMap<>(); + private @Nullable Map unknown; public SpanContext( @@ -213,6 +215,14 @@ public void setOrigin(final @Nullable String origin) { this.origin = origin; } + public @NotNull Map getData() { + return data; + } + + public void setData(final @NotNull String key, final @NotNull Object value) { + data.put(key, value); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -242,6 +252,7 @@ public static final class JsonKeys { public static final String STATUS = "status"; public static final String TAGS = "tags"; public static final String ORIGIN = "origin"; + public static final String DATA = "data"; } @Override @@ -269,6 +280,9 @@ public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger if (!tags.isEmpty()) { writer.name(JsonKeys.TAGS).value(logger, tags); } + if (!data.isEmpty()) { + writer.name(JsonKeys.DATA).value(logger, data); + } if (unknown != null) { for (String key : unknown.keySet()) { Object value = unknown.get(key); @@ -303,6 +317,7 @@ public static final class Deserializer implements JsonDeserializer SpanStatus status = null; String origin = null; Map tags = null; + Map data = null; Map unknown = null; while (reader.peek() == JsonToken.NAME) { @@ -334,6 +349,9 @@ public static final class Deserializer implements JsonDeserializer CollectionUtils.newConcurrentHashMap( (Map) reader.nextObjectOrNull()); break; + case JsonKeys.DATA: + data = (Map) reader.nextObjectOrNull(); + break; default: if (unknown == null) { unknown = new ConcurrentHashMap<>(); @@ -374,6 +392,11 @@ public static final class Deserializer implements JsonDeserializer if (tags != null) { spanContext.tags = tags; } + + if (data != null) { + spanContext.data = data; + } + spanContext.setUnknown(unknown); reader.endObject(); return spanContext; diff --git a/sentry/src/main/java/io/sentry/protocol/SentryTransaction.java b/sentry/src/main/java/io/sentry/protocol/SentryTransaction.java index 3bc42e42084..7d4e611a2c0 100644 --- a/sentry/src/main/java/io/sentry/protocol/SentryTransaction.java +++ b/sentry/src/main/java/io/sentry/protocol/SentryTransaction.java @@ -80,8 +80,9 @@ public SentryTransaction(final @NotNull SentryTracer sentryTracer) { contexts.putAll(sentryTracer.getContexts()); final SpanContext tracerContext = sentryTracer.getSpanContext(); + Map data = sentryTracer.getData(); // tags must be placed on the root of the transaction instead of contexts.trace.tags - contexts.setTrace( + final SpanContext tracerContextToSend = new SpanContext( tracerContext.getTraceId(), tracerContext.getSpanId(), @@ -90,15 +91,18 @@ public SentryTransaction(final @NotNull SentryTracer sentryTracer) { tracerContext.getDescription(), tracerContext.getSamplingDecision(), tracerContext.getStatus(), - tracerContext.getOrigin())); + tracerContext.getOrigin()); + + contexts.setTrace(tracerContextToSend); for (final Map.Entry tag : tracerContext.getTags().entrySet()) { this.setTag(tag.getKey(), tag.getValue()); } - final Map data = sentryTracer.getData(); + // TODO should we remove setExtra here, or do we need it for backwards compat? if (data != null) { for (final Map.Entry tag : data.entrySet()) { this.setExtra(tag.getKey(), tag.getValue()); + tracerContextToSend.setData(tag.getKey(), tag.getValue()); } } diff --git a/sentry/src/test/java/io/sentry/JsonSerializerTest.kt b/sentry/src/test/java/io/sentry/JsonSerializerTest.kt index ba8ee84d516..794b9faca8d 100644 --- a/sentry/src/test/java/io/sentry/JsonSerializerTest.kt +++ b/sentry/src/test/java/io/sentry/JsonSerializerTest.kt @@ -889,7 +889,10 @@ class JsonSerializerTest { "trace_id": "b156a475de54423d9c1571df97ec7eb6", "span_id": "0a53026963414893", "op": "http", - "status": "ok" + "status": "ok", + "data": { + "transactionDataKey": "transactionDataValue" + } }, "custom": { "some-key": "some-value" @@ -930,6 +933,7 @@ class JsonSerializerTest { assertEquals("0a53026963414893", transaction.contexts.trace!!.spanId.toString()) assertEquals("http", transaction.contexts.trace!!.operation) assertNotNull(transaction.contexts["custom"]) + assertEquals("transactionDataValue", transaction.contexts.trace!!.data!!["transactionDataKey"]) assertEquals("some-value", (transaction.contexts["custom"] as Map<*, *>)["some-key"]) assertEquals("extraValue", transaction.getExtra("extraKey")) diff --git a/sentry/src/test/java/io/sentry/protocol/SpanContextSerializationTest.kt b/sentry/src/test/java/io/sentry/protocol/SpanContextSerializationTest.kt index bd3bcd72c35..707daa78f10 100644 --- a/sentry/src/test/java/io/sentry/protocol/SpanContextSerializationTest.kt +++ b/sentry/src/test/java/io/sentry/protocol/SpanContextSerializationTest.kt @@ -35,6 +35,7 @@ class SpanContextSerializationTest { setTag("2a5fa3f5-7b87-487f-aaa5-84567aa73642", "4781d51a-c5af-47f2-a4ed-f030c9b3e194") setTag("29106d7d-7fa4-444f-9d34-b9d7510c69ab", "218c23ea-694a-497e-bf6d-e5f26f1ad7bd") setTag("ba9ce913-269f-4c03-882d-8ca5e6991b14", "35a74e90-8db8-4610-a411-872cbc1030ac") + setData("spanContextDataKey", "spanContextDataValue") } } private val fixture = Fixture() diff --git a/sentry/src/test/resources/json/contexts.json b/sentry/src/test/resources/json/contexts.json index 574bb019214..549ce557ba5 100644 --- a/sentry/src/test/resources/json/contexts.json +++ b/sentry/src/test/resources/json/contexts.json @@ -121,6 +121,10 @@ "2a5fa3f5-7b87-487f-aaa5-84567aa73642": "4781d51a-c5af-47f2-a4ed-f030c9b3e194", "29106d7d-7fa4-444f-9d34-b9d7510c69ab": "218c23ea-694a-497e-bf6d-e5f26f1ad7bd", "ba9ce913-269f-4c03-882d-8ca5e6991b14": "35a74e90-8db8-4610-a411-872cbc1030ac" + }, + "data": + { + "spanContextDataKey": "spanContextDataValue" } } } diff --git a/sentry/src/test/resources/json/sentry_base_event.json b/sentry/src/test/resources/json/sentry_base_event.json index afaf0408638..df2c82bce47 100644 --- a/sentry/src/test/resources/json/sentry_base_event.json +++ b/sentry/src/test/resources/json/sentry_base_event.json @@ -124,6 +124,10 @@ "2a5fa3f5-7b87-487f-aaa5-84567aa73642": "4781d51a-c5af-47f2-a4ed-f030c9b3e194", "29106d7d-7fa4-444f-9d34-b9d7510c69ab": "218c23ea-694a-497e-bf6d-e5f26f1ad7bd", "ba9ce913-269f-4c03-882d-8ca5e6991b14": "35a74e90-8db8-4610-a411-872cbc1030ac" + }, + "data": + { + "spanContextDataKey": "spanContextDataValue" } } }, diff --git a/sentry/src/test/resources/json/sentry_base_event_with_null_extra.json b/sentry/src/test/resources/json/sentry_base_event_with_null_extra.json index 018cc7aae7d..722b38f76e2 100644 --- a/sentry/src/test/resources/json/sentry_base_event_with_null_extra.json +++ b/sentry/src/test/resources/json/sentry_base_event_with_null_extra.json @@ -124,6 +124,10 @@ "2a5fa3f5-7b87-487f-aaa5-84567aa73642": "4781d51a-c5af-47f2-a4ed-f030c9b3e194", "29106d7d-7fa4-444f-9d34-b9d7510c69ab": "218c23ea-694a-497e-bf6d-e5f26f1ad7bd", "ba9ce913-269f-4c03-882d-8ca5e6991b14": "35a74e90-8db8-4610-a411-872cbc1030ac" + }, + "data": + { + "spanContextDataKey": "spanContextDataValue" } } }, diff --git a/sentry/src/test/resources/json/sentry_event.json b/sentry/src/test/resources/json/sentry_event.json index 6d0b351ed49..49ce85b7ed8 100644 --- a/sentry/src/test/resources/json/sentry_event.json +++ b/sentry/src/test/resources/json/sentry_event.json @@ -259,6 +259,10 @@ "2a5fa3f5-7b87-487f-aaa5-84567aa73642": "4781d51a-c5af-47f2-a4ed-f030c9b3e194", "29106d7d-7fa4-444f-9d34-b9d7510c69ab": "218c23ea-694a-497e-bf6d-e5f26f1ad7bd", "ba9ce913-269f-4c03-882d-8ca5e6991b14": "35a74e90-8db8-4610-a411-872cbc1030ac" + }, + "data": + { + "spanContextDataKey": "spanContextDataValue" } } }, diff --git a/sentry/src/test/resources/json/sentry_replay_event.json b/sentry/src/test/resources/json/sentry_replay_event.json index f026c9fee47..83728f8b7fe 100644 --- a/sentry/src/test/resources/json/sentry_replay_event.json +++ b/sentry/src/test/resources/json/sentry_replay_event.json @@ -142,6 +142,10 @@ "2a5fa3f5-7b87-487f-aaa5-84567aa73642": "4781d51a-c5af-47f2-a4ed-f030c9b3e194", "29106d7d-7fa4-444f-9d34-b9d7510c69ab": "218c23ea-694a-497e-bf6d-e5f26f1ad7bd", "ba9ce913-269f-4c03-882d-8ca5e6991b14": "35a74e90-8db8-4610-a411-872cbc1030ac" + }, + "data": + { + "spanContextDataKey": "spanContextDataValue" } } }, diff --git a/sentry/src/test/resources/json/sentry_transaction.json b/sentry/src/test/resources/json/sentry_transaction.json index 944a0bfe92d..db8d7dfac93 100644 --- a/sentry/src/test/resources/json/sentry_transaction.json +++ b/sentry/src/test/resources/json/sentry_transaction.json @@ -207,6 +207,10 @@ "2a5fa3f5-7b87-487f-aaa5-84567aa73642": "4781d51a-c5af-47f2-a4ed-f030c9b3e194", "29106d7d-7fa4-444f-9d34-b9d7510c69ab": "218c23ea-694a-497e-bf6d-e5f26f1ad7bd", "ba9ce913-269f-4c03-882d-8ca5e6991b14": "35a74e90-8db8-4610-a411-872cbc1030ac" + }, + "data": + { + "spanContextDataKey": "spanContextDataValue" } } }, diff --git a/sentry/src/test/resources/json/sentry_transaction_legacy_date_format.json b/sentry/src/test/resources/json/sentry_transaction_legacy_date_format.json index 789c4fe2a93..6055e0fcd8f 100644 --- a/sentry/src/test/resources/json/sentry_transaction_legacy_date_format.json +++ b/sentry/src/test/resources/json/sentry_transaction_legacy_date_format.json @@ -207,6 +207,10 @@ "2a5fa3f5-7b87-487f-aaa5-84567aa73642": "4781d51a-c5af-47f2-a4ed-f030c9b3e194", "29106d7d-7fa4-444f-9d34-b9d7510c69ab": "218c23ea-694a-497e-bf6d-e5f26f1ad7bd", "ba9ce913-269f-4c03-882d-8ca5e6991b14": "35a74e90-8db8-4610-a411-872cbc1030ac" + }, + "data": + { + "spanContextDataKey": "spanContextDataValue" } } }, diff --git a/sentry/src/test/resources/json/sentry_transaction_no_measurement_unit.json b/sentry/src/test/resources/json/sentry_transaction_no_measurement_unit.json index 330555c1ec0..ea2b042b007 100644 --- a/sentry/src/test/resources/json/sentry_transaction_no_measurement_unit.json +++ b/sentry/src/test/resources/json/sentry_transaction_no_measurement_unit.json @@ -177,6 +177,10 @@ "2a5fa3f5-7b87-487f-aaa5-84567aa73642": "4781d51a-c5af-47f2-a4ed-f030c9b3e194", "29106d7d-7fa4-444f-9d34-b9d7510c69ab": "218c23ea-694a-497e-bf6d-e5f26f1ad7bd", "ba9ce913-269f-4c03-882d-8ca5e6991b14": "35a74e90-8db8-4610-a411-872cbc1030ac" + }, + "data": + { + "spanContextDataKey": "spanContextDataValue" } } }, diff --git a/sentry/src/test/resources/json/span_context.json b/sentry/src/test/resources/json/span_context.json index 4a6e08bcc2d..dc7d883a4da 100644 --- a/sentry/src/test/resources/json/span_context.json +++ b/sentry/src/test/resources/json/span_context.json @@ -11,5 +11,8 @@ "2a5fa3f5-7b87-487f-aaa5-84567aa73642": "4781d51a-c5af-47f2-a4ed-f030c9b3e194", "29106d7d-7fa4-444f-9d34-b9d7510c69ab": "218c23ea-694a-497e-bf6d-e5f26f1ad7bd", "ba9ce913-269f-4c03-882d-8ca5e6991b14": "35a74e90-8db8-4610-a411-872cbc1030ac" + }, + "data": { + "spanContextDataKey": "spanContextDataValue" } } From b5e06918d17ec0eda498bfcd8cefccf947272526 Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Fri, 16 Aug 2024 14:54:00 +0200 Subject: [PATCH 2/2] add changelog entry --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d26f36b9703..a325fe18b6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## Unreleased + +### Features +- Emit transaction.data inside contexts.trace.data ([#3642](https://github.com/getsentry/sentry-java/pull/3642)) + ## 7.14.0 ### Features