From 031147fc57638e30328b22037b12e734e1ded876 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Wed, 15 Sep 2021 10:39:53 +0200 Subject: [PATCH 1/5] Feat: Add "data" to spans Fixes #1233 --- sentry/api/sentry.api | 12 ++++++++++ sentry/src/main/java/io/sentry/ISpan.java | 16 +++++++++++++ sentry/src/main/java/io/sentry/NoOpSpan.java | 8 +++++++ .../main/java/io/sentry/NoOpTransaction.java | 8 +++++++ .../src/main/java/io/sentry/SentryTracer.java | 15 ++++++++++++ sentry/src/main/java/io/sentry/Span.java | 17 +++++++++++++ .../java/io/sentry/protocol/SentrySpan.java | 2 +- .../io/sentry/protocol/SentryTransaction.java | 7 ++++++ .../test/java/io/sentry/GsonSerializerTest.kt | 8 +++++++ .../test/java/io/sentry/SentryTracerTest.kt | 24 +++++++++++++++++++ 10 files changed, 116 insertions(+), 1 deletion(-) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 1050fb43c6..e45f77ee8a 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -304,6 +304,7 @@ public abstract interface class io/sentry/ISerializer { public abstract interface class io/sentry/ISpan { public abstract fun finish ()V public abstract fun finish (Lio/sentry/SpanStatus;)V + public abstract fun getData (Ljava/lang/String;)Ljava/lang/Object; public abstract fun getDescription ()Ljava/lang/String; public abstract fun getOperation ()Ljava/lang/String; public abstract fun getSpanContext ()Lio/sentry/SpanContext; @@ -311,6 +312,7 @@ public abstract interface class io/sentry/ISpan { public abstract fun getTag (Ljava/lang/String;)Ljava/lang/String; public abstract fun getThrowable ()Ljava/lang/Throwable; public abstract fun isFinished ()Z + public abstract fun setData (Ljava/lang/String;Ljava/lang/Object;)V public abstract fun setDescription (Ljava/lang/String;)V public abstract fun setOperation (Ljava/lang/String;)V public abstract fun setStatus (Lio/sentry/SpanStatus;)V @@ -414,6 +416,7 @@ public final class io/sentry/NoOpLogger : io/sentry/ILogger { public final class io/sentry/NoOpSpan : io/sentry/ISpan { public fun finish ()V public fun finish (Lio/sentry/SpanStatus;)V + public fun getData (Ljava/lang/String;)Ljava/lang/Object; public fun getDescription ()Ljava/lang/String; public static fun getInstance ()Lio/sentry/NoOpSpan; public fun getOperation ()Ljava/lang/String; @@ -422,6 +425,7 @@ public final class io/sentry/NoOpSpan : io/sentry/ISpan { public fun getTag (Ljava/lang/String;)Ljava/lang/String; public fun getThrowable ()Ljava/lang/Throwable; public fun isFinished ()Z + 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 setStatus (Lio/sentry/SpanStatus;)V @@ -439,6 +443,7 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction { public fun finish ()V public fun finish (Lio/sentry/SpanStatus;)V public fun getContexts ()Lio/sentry/protocol/Contexts; + public fun getData (Ljava/lang/String;)Ljava/lang/Object; public fun getDescription ()Ljava/lang/String; public fun getEventId ()Lio/sentry/protocol/SentryId; public static fun getInstance ()Lio/sentry/NoOpTransaction; @@ -453,6 +458,7 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction { public fun getThrowable ()Ljava/lang/Throwable; public fun isFinished ()Z public fun isSampled ()Ljava/lang/Boolean; + public fun setData (Ljava/lang/String;Ljava/lang/Object;)V public fun setDescription (Ljava/lang/String;)V public fun setName (Ljava/lang/String;)V public fun setOperation (Ljava/lang/String;)V @@ -971,6 +977,8 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction { public fun finish (Lio/sentry/SpanStatus;)V public fun getChildren ()Ljava/util/List; public fun getContexts ()Lio/sentry/protocol/Contexts; + public fun getData ()Ljava/util/Map; + public fun getData (Ljava/lang/String;)Ljava/lang/Object; public fun getDescription ()Ljava/lang/String; public fun getEventId ()Lio/sentry/protocol/SentryId; public fun getLatestActiveSpan ()Lio/sentry/Span; @@ -986,6 +994,7 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction { public fun getTimestamp ()Ljava/util/Date; public fun isFinished ()Z public fun isSampled ()Ljava/lang/Boolean; + public fun setData (Ljava/lang/String;Ljava/lang/Object;)V public fun setDescription (Ljava/lang/String;)V public fun setName (Ljava/lang/String;)V public fun setOperation (Ljava/lang/String;)V @@ -1053,6 +1062,8 @@ public final class io/sentry/Span : io/sentry/ISpan { public fun (Lio/sentry/TransactionContext;Lio/sentry/SentryTracer;Lio/sentry/IHub;Ljava/util/Date;)V public fun finish ()V public fun finish (Lio/sentry/SpanStatus;)V + public fun getData ()Ljava/util/Map; + public fun getData (Ljava/lang/String;)Ljava/lang/Object; public fun getDescription ()Ljava/lang/String; public fun getOperation ()Ljava/lang/String; public fun getParentSpanId ()Lio/sentry/SpanId; @@ -1067,6 +1078,7 @@ public final class io/sentry/Span : io/sentry/ISpan { public fun getTraceId ()Lio/sentry/protocol/SentryId; public fun isFinished ()Z public fun isSampled ()Ljava/lang/Boolean; + 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 setStatus (Lio/sentry/SpanStatus;)V diff --git a/sentry/src/main/java/io/sentry/ISpan.java b/sentry/src/main/java/io/sentry/ISpan.java index 408118a7b8..9b5987ee33 100644 --- a/sentry/src/main/java/io/sentry/ISpan.java +++ b/sentry/src/main/java/io/sentry/ISpan.java @@ -154,4 +154,20 @@ ISpan startChild( * @return if span has finished. */ boolean isFinished(); + + /** + * Sets extra data on span on transaction. + * + * @param key the data key + * @param value the data value + */ + void setData(@NotNull String key, @NotNull Object value); + + /** + * Returns extra data from span or transaction. + * + * @return the data + */ + @Nullable + Object getData(@NotNull String key); } diff --git a/sentry/src/main/java/io/sentry/NoOpSpan.java b/sentry/src/main/java/io/sentry/NoOpSpan.java index 0ba8e53597..af5ea4e926 100644 --- a/sentry/src/main/java/io/sentry/NoOpSpan.java +++ b/sentry/src/main/java/io/sentry/NoOpSpan.java @@ -102,4 +102,12 @@ public void setTag(@NotNull String key, @NotNull String value) {} public boolean isFinished() { return false; } + + @Override + public void setData(@NotNull String key, @NotNull Object value) {} + + @Override + public @Nullable Object getData(@NotNull String key) { + return null; + } } diff --git a/sentry/src/main/java/io/sentry/NoOpTransaction.java b/sentry/src/main/java/io/sentry/NoOpTransaction.java index 91d0e96700..208edf9f7a 100644 --- a/sentry/src/main/java/io/sentry/NoOpTransaction.java +++ b/sentry/src/main/java/io/sentry/NoOpTransaction.java @@ -159,4 +159,12 @@ public void setTag(@NotNull String key, @NotNull String value) {} public @Nullable Boolean isSampled() { return null; } + + @Override + public void setData(@NotNull String key, @NotNull Object value) {} + + @Override + public @Nullable Object getData(@NotNull String key) { + return null; + } } diff --git a/sentry/src/main/java/io/sentry/SentryTracer.java b/sentry/src/main/java/io/sentry/SentryTracer.java index 34438e8a27..eab380a3af 100644 --- a/sentry/src/main/java/io/sentry/SentryTracer.java +++ b/sentry/src/main/java/io/sentry/SentryTracer.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicReference; import org.jetbrains.annotations.ApiStatus; @@ -345,6 +346,20 @@ public boolean isFinished() { return this.root.isFinished(); } + @Override + public void setData(@NotNull String key, @NotNull Object value) { + this.root.setData(key, value); + } + + @Override + public @Nullable Object getData(@NotNull String key) { + return this.root.getData(key); + } + + public @Nullable Map getData() { + return this.root.getData(); + } + @Override public @Nullable Boolean isSampled() { return this.root.isSampled(); diff --git a/sentry/src/main/java/io/sentry/Span.java b/sentry/src/main/java/io/sentry/Span.java index f47f4edc13..e99b969bfe 100644 --- a/sentry/src/main/java/io/sentry/Span.java +++ b/sentry/src/main/java/io/sentry/Span.java @@ -4,6 +4,7 @@ import io.sentry.util.Objects; import java.util.Date; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -35,6 +36,8 @@ public final class Span implements ISpan { private final @Nullable SpanFinishedCallback spanFinishedCallback; + private final @NotNull Map data = new ConcurrentHashMap<>(); + Span( final @NotNull SentryId traceId, final @Nullable SpanId parentSpanId, @@ -197,6 +200,10 @@ public boolean isFinished() { return finished.get(); } + public @NotNull Map getData() { + return data; + } + public @Nullable Boolean isSampled() { return context.getSampled(); } @@ -227,4 +234,14 @@ public SentryId getTraceId() { public Map getTags() { return context.getTags(); } + + @Override + public void setData(@NotNull String key, @NotNull Object value) { + data.put(key, value); + } + + @Override + public @Nullable Object getData(@NotNull String key) { + return data.get(key); + } } diff --git a/sentry/src/main/java/io/sentry/protocol/SentrySpan.java b/sentry/src/main/java/io/sentry/protocol/SentrySpan.java index fbcd743ba5..8cd4224aad 100644 --- a/sentry/src/main/java/io/sentry/protocol/SentrySpan.java +++ b/sentry/src/main/java/io/sentry/protocol/SentrySpan.java @@ -26,7 +26,7 @@ public final class SentrySpan { private final @Nullable Map data; public SentrySpan(final @NotNull Span span) { - this(span, null); + this(span, span.getData()); } @ApiStatus.Internal diff --git a/sentry/src/main/java/io/sentry/protocol/SentryTransaction.java b/sentry/src/main/java/io/sentry/protocol/SentryTransaction.java index 0f33675c53..5e46fb16f7 100644 --- a/sentry/src/main/java/io/sentry/protocol/SentryTransaction.java +++ b/sentry/src/main/java/io/sentry/protocol/SentryTransaction.java @@ -67,6 +67,13 @@ public SentryTransaction(final @NotNull SentryTracer sentryTracer) { for (final Map.Entry tag : tracerContext.getTags().entrySet()) { this.setTag(tag.getKey(), tag.getValue()); } + + final Map data = sentryTracer.getData(); + if (data != null) { + for (final Map.Entry tag : data.entrySet()) { + this.setExtra(tag.getKey(), tag.getValue()); + } + } } public @NotNull List getSpans() { diff --git a/sentry/src/test/java/io/sentry/GsonSerializerTest.kt b/sentry/src/test/java/io/sentry/GsonSerializerTest.kt index 04f12622ba..38eb17ea94 100644 --- a/sentry/src/test/java/io/sentry/GsonSerializerTest.kt +++ b/sentry/src/test/java/io/sentry/GsonSerializerTest.kt @@ -512,6 +512,7 @@ class GsonSerializerTest { trace.setTag("myTag", "myValue") trace.sampled = true val tracer = SentryTracer(trace, fixture.hub) + tracer.setData("dataKey", "dataValue") val span = tracer.startChild("child") span.finish(SpanStatus.OK) tracer.finish() @@ -527,6 +528,8 @@ class GsonSerializerTest { assertNotNull(element["spans"].asJsonArray) assertEquals("myValue", element["tags"].asJsonObject["myTag"].asString) + assertEquals("dataValue", element["extra"].asJsonObject["dataKey"].asString) + val jsonSpan = element["spans"].asJsonArray[0].asJsonObject assertNotNull(jsonSpan["trace_id"]) assertNotNull(jsonSpan["span_id"]) @@ -563,6 +566,9 @@ class GsonSerializerTest { "some-key": "some-value" } }, + "extra": { + "extraKey": "extraValue" + }, "spans": [ { "start_timestamp": "2021-03-05T08:51:12.838Z", @@ -597,6 +603,8 @@ class GsonSerializerTest { assertNotNull(transaction.contexts["custom"]) assertEquals("some-value", (transaction.contexts["custom"] as Map<*, *>)["some-key"]) + assertEquals("extraValue", transaction.getExtra("extraKey")) + assertNotNull(transaction.spans) assertEquals(1, transaction.spans.size) val span = transaction.spans[0] diff --git a/sentry/src/test/java/io/sentry/SentryTracerTest.kt b/sentry/src/test/java/io/sentry/SentryTracerTest.kt index 72fe9cbb64..41c6726550 100644 --- a/sentry/src/test/java/io/sentry/SentryTracerTest.kt +++ b/sentry/src/test/java/io/sentry/SentryTracerTest.kt @@ -498,4 +498,28 @@ class SentryTracerTest { assertNotNull(it.value) } } + + @Test + fun `sets ITransaction data as extra in SentryTransaction`() { + val transaction = fixture.getSut(sampled = true) + transaction.setData("key", "val") + transaction.finish() + verify(fixture.hub, times(1)).captureTransaction(check { + assertEquals("val", it.getExtra("key")) + }, anyOrNull()) + } + + @Test + fun `sets Span data as data in SentrySpan`() { + val transaction = fixture.getSut(sampled = true) + val span = transaction.startChild("op") + span.setData("key", "val") + span.finish() + transaction.finish() + verify(fixture.hub, times(1)).captureTransaction(check { + assertNotNull(it.spans.first().data) { + assertEquals("val", it["key"]) + } + }, anyOrNull()) + } } From a6319684c22645f500dfa38c9754c402236df324 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Wed, 15 Sep 2021 10:41:05 +0200 Subject: [PATCH 2/5] Changelog. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index df430e5249..fcab397b1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +* Feat: Add "data" to spans (#1717) + ## 5.2.0-beta.2 * Bump AGP to 7.0.2 (#1650) From db13534cc6a3dbc5f5cb6de716c10f9bafd18a85 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Wed, 15 Sep 2021 11:27:18 +0200 Subject: [PATCH 3/5] Update sentry/src/test/java/io/sentry/SentryTracerTest.kt Co-authored-by: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com> --- sentry/src/test/java/io/sentry/SentryTracerTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry/src/test/java/io/sentry/SentryTracerTest.kt b/sentry/src/test/java/io/sentry/SentryTracerTest.kt index 41c6726550..7e4427b0de 100644 --- a/sentry/src/test/java/io/sentry/SentryTracerTest.kt +++ b/sentry/src/test/java/io/sentry/SentryTracerTest.kt @@ -516,7 +516,7 @@ class SentryTracerTest { span.setData("key", "val") span.finish() transaction.finish() - verify(fixture.hub, times(1)).captureTransaction(check { + verify(fixture.hub).captureTransaction(check { assertNotNull(it.spans.first().data) { assertEquals("val", it["key"]) } From b513a31285a937a26f58648c416019d9f51ce6c7 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Wed, 15 Sep 2021 11:27:24 +0200 Subject: [PATCH 4/5] Update sentry/src/test/java/io/sentry/SentryTracerTest.kt Co-authored-by: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com> --- sentry/src/test/java/io/sentry/SentryTracerTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry/src/test/java/io/sentry/SentryTracerTest.kt b/sentry/src/test/java/io/sentry/SentryTracerTest.kt index 7e4427b0de..5f516057d6 100644 --- a/sentry/src/test/java/io/sentry/SentryTracerTest.kt +++ b/sentry/src/test/java/io/sentry/SentryTracerTest.kt @@ -504,7 +504,7 @@ class SentryTracerTest { val transaction = fixture.getSut(sampled = true) transaction.setData("key", "val") transaction.finish() - verify(fixture.hub, times(1)).captureTransaction(check { + verify(fixture.hub).captureTransaction(check { assertEquals("val", it.getExtra("key")) }, anyOrNull()) } From 1d5ce6e1ba43a8b7c9d93b734ad48fe76cbe1545 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Wed, 15 Sep 2021 11:27:30 +0200 Subject: [PATCH 5/5] Update sentry/src/main/java/io/sentry/ISpan.java Co-authored-by: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com> --- sentry/src/main/java/io/sentry/ISpan.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry/src/main/java/io/sentry/ISpan.java b/sentry/src/main/java/io/sentry/ISpan.java index 9b5987ee33..2a25a1129f 100644 --- a/sentry/src/main/java/io/sentry/ISpan.java +++ b/sentry/src/main/java/io/sentry/ISpan.java @@ -156,7 +156,7 @@ ISpan startChild( boolean isFinished(); /** - * Sets extra data on span on transaction. + * Sets extra data on span or transaction. * * @param key the data key * @param value the data value