From 460eff1026dd4019e77c403bd9a1bc5f9893914e Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Thu, 4 May 2023 17:08:05 +0200 Subject: [PATCH 1/6] open up some transaction methods to be public --- sentry/api/sentry.api | 3 +++ sentry/src/main/java/io/sentry/IHub.java | 1 - sentry/src/main/java/io/sentry/ITransaction.java | 4 ++++ sentry/src/main/java/io/sentry/NoOpTransaction.java | 5 +++++ sentry/src/main/java/io/sentry/Sentry.java | 1 - sentry/src/main/java/io/sentry/SentryTracer.java | 8 ++++++++ 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 666fc6080b..48812a5bf3 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -596,6 +596,7 @@ public abstract interface class io/sentry/ITransaction : io/sentry/ISpan { public abstract fun setContext (Ljava/lang/String;Ljava/lang/Object;)V public abstract fun setName (Ljava/lang/String;)V public abstract fun setName (Ljava/lang/String;Lio/sentry/protocol/TransactionNameSource;)V + public abstract fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryDate;)Lio/sentry/ISpan; } public abstract interface class io/sentry/ITransactionProfiler { @@ -898,6 +899,7 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction { public fun setThrowable (Ljava/lang/Throwable;)V public fun startChild (Ljava/lang/String;)Lio/sentry/ISpan; public fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/ISpan; + public fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryDate;)Lio/sentry/ISpan; public fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryDate;Lio/sentry/Instrumenter;)Lio/sentry/ISpan; public fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryDate;Lio/sentry/Instrumenter;Lio/sentry/SpanOptions;)Lio/sentry/ISpan; public fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SpanOptions;)Lio/sentry/ISpan; @@ -1834,6 +1836,7 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction { public fun setThrowable (Ljava/lang/Throwable;)V public fun startChild (Ljava/lang/String;)Lio/sentry/ISpan; public fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/ISpan; + public fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryDate;)Lio/sentry/ISpan; public fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryDate;Lio/sentry/Instrumenter;)Lio/sentry/ISpan; public fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryDate;Lio/sentry/Instrumenter;Lio/sentry/SpanOptions;)Lio/sentry/ISpan; public fun startChild (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SpanOptions;)Lio/sentry/ISpan; diff --git a/sentry/src/main/java/io/sentry/IHub.java b/sentry/src/main/java/io/sentry/IHub.java index 31cc143797..58741a0afa 100644 --- a/sentry/src/main/java/io/sentry/IHub.java +++ b/sentry/src/main/java/io/sentry/IHub.java @@ -494,7 +494,6 @@ ITransaction startTransaction( return startTransaction(name, operation, null); } - @ApiStatus.Internal @NotNull ITransaction startTransaction( final @NotNull TransactionContext transactionContext, diff --git a/sentry/src/main/java/io/sentry/ITransaction.java b/sentry/src/main/java/io/sentry/ITransaction.java index 29478511ec..0166850f1e 100644 --- a/sentry/src/main/java/io/sentry/ITransaction.java +++ b/sentry/src/main/java/io/sentry/ITransaction.java @@ -41,6 +41,10 @@ public interface ITransaction extends ISpan { @TestOnly List getSpans(); + @NotNull + ISpan startChild( + @NotNull String operation, @Nullable String description, @Nullable SentryDate timestamp); + /** * Returns if transaction is sampled. * diff --git a/sentry/src/main/java/io/sentry/NoOpTransaction.java b/sentry/src/main/java/io/sentry/NoOpTransaction.java index cc2b0b5426..56e8e1c74d 100644 --- a/sentry/src/main/java/io/sentry/NoOpTransaction.java +++ b/sentry/src/main/java/io/sentry/NoOpTransaction.java @@ -82,6 +82,11 @@ public void setName(@NotNull String name, @NotNull TransactionNameSource transac return Collections.emptyList(); } + @Override + public @NotNull ISpan startChild(@NotNull String operation, @Nullable String description, @Nullable SentryDate timestamp) { + return NoOpSpan.getInstance(); + } + @Override public @Nullable Span getLatestActiveSpan() { return null; diff --git a/sentry/src/main/java/io/sentry/Sentry.java b/sentry/src/main/java/io/sentry/Sentry.java index c3eea1d9b1..a239d8fea0 100644 --- a/sentry/src/main/java/io/sentry/Sentry.java +++ b/sentry/src/main/java/io/sentry/Sentry.java @@ -844,7 +844,6 @@ public static void endSession() { * @param transactionOptions options for the transaction * @return created transaction. */ - @ApiStatus.Internal public static @NotNull ITransaction startTransaction( final @NotNull TransactionContext transactionContext, final @NotNull TransactionOptions transactionOptions) { diff --git a/sentry/src/main/java/io/sentry/SentryTracer.java b/sentry/src/main/java/io/sentry/SentryTracer.java index 0ad89e8a20..d27499cb6c 100644 --- a/sentry/src/main/java/io/sentry/SentryTracer.java +++ b/sentry/src/main/java/io/sentry/SentryTracer.java @@ -404,6 +404,14 @@ private ISpan createChild( return createChild(operation, description, timestamp, instrumenter, spanOptions); } + @Override + public @NotNull ISpan startChild( + final @NotNull String operation, + @Nullable String description, + @Nullable SentryDate timestamp) { + return createChild(operation, description, timestamp, Instrumenter.SENTRY, new SpanOptions()); + } + @Override public @NotNull ISpan startChild( final @NotNull String operation, final @Nullable String description) { From 952da48d0e80872381e8b312c91fb91f5a5875c0 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Fri, 5 May 2023 12:26:58 +0000 Subject: [PATCH 2/6] Format code --- sentry/src/main/java/io/sentry/NoOpTransaction.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sentry/src/main/java/io/sentry/NoOpTransaction.java b/sentry/src/main/java/io/sentry/NoOpTransaction.java index 56e8e1c74d..902c8a7da6 100644 --- a/sentry/src/main/java/io/sentry/NoOpTransaction.java +++ b/sentry/src/main/java/io/sentry/NoOpTransaction.java @@ -83,7 +83,8 @@ public void setName(@NotNull String name, @NotNull TransactionNameSource transac } @Override - public @NotNull ISpan startChild(@NotNull String operation, @Nullable String description, @Nullable SentryDate timestamp) { + public @NotNull ISpan startChild( + @NotNull String operation, @Nullable String description, @Nullable SentryDate timestamp) { return NoOpSpan.getInstance(); } From 391fbe30dad72e168d527695e3c9b14f4a04e5b3 Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Fri, 5 May 2023 14:33:09 +0200 Subject: [PATCH 3/6] add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec08b2ae2d..c5a04ffc9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Auxiliary information (such as current memory load) at the time of ANR event. - If you would like us to provide support for the old approach working alongside the new one on Android 11 and above (e.g. for raising events for slow code on main thread), consider upvoting [this issue](https://github.com/getsentry/sentry-java/issues/2693). - The old watchdog implementation will continue working for older API versions (Android < 11) +- Open up transaction methods ([#2701](https://github.com/getsentry/sentry-java/pull/2701)) ### Fixes From 46a6a483d1f5a966cfd5a0f1a7c584e00464a3cb Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Wed, 10 May 2023 15:03:30 +0200 Subject: [PATCH 4/6] add javadoc, add tests, make TransactionOptions public --- sentry/src/main/java/io/sentry/IHub.java | 9 ++++++++ .../src/main/java/io/sentry/ITransaction.java | 8 +++++++ .../java/io/sentry/TransactionOptions.java | 3 +-- .../java/io/sentry/NoOpTransactionTest.kt | 4 ++++ .../test/java/io/sentry/SentryTracerTest.kt | 21 +++++++++++++++++++ 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/sentry/src/main/java/io/sentry/IHub.java b/sentry/src/main/java/io/sentry/IHub.java index 58741a0afa..b99e99ab82 100644 --- a/sentry/src/main/java/io/sentry/IHub.java +++ b/sentry/src/main/java/io/sentry/IHub.java @@ -494,6 +494,15 @@ ITransaction startTransaction( return startTransaction(name, operation, null); } + /** + * Creates a Transaction and returns the instance. Based on the passed transaction context and + * transaction options the decision if transaction is sampled will be taken by {@link + * TracesSampler}. + * + * @param transactionContext the transaction context + * @param transactionOptions the transaction options + * @return created transaction. + */ @NotNull ITransaction startTransaction( final @NotNull TransactionContext transactionContext, diff --git a/sentry/src/main/java/io/sentry/ITransaction.java b/sentry/src/main/java/io/sentry/ITransaction.java index 0166850f1e..127dc448ee 100644 --- a/sentry/src/main/java/io/sentry/ITransaction.java +++ b/sentry/src/main/java/io/sentry/ITransaction.java @@ -41,6 +41,14 @@ public interface ITransaction extends ISpan { @TestOnly List getSpans(); + /** + * Starts a child Span. + * + * @param operation - new span operation name + * @param description - the span description + * @param timestamp - the start timestamp of the span + * @return a new transaction span + */ @NotNull ISpan startChild( @NotNull String operation, @Nullable String description, @Nullable SentryDate timestamp); diff --git a/sentry/src/main/java/io/sentry/TransactionOptions.java b/sentry/src/main/java/io/sentry/TransactionOptions.java index a3b1450d74..0b4e12d29e 100644 --- a/sentry/src/main/java/io/sentry/TransactionOptions.java +++ b/sentry/src/main/java/io/sentry/TransactionOptions.java @@ -1,9 +1,8 @@ package io.sentry; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -@ApiStatus.Internal +/** Sentry Transaction options */ public final class TransactionOptions extends SpanOptions { private @Nullable CustomSamplingContext customSamplingContext = null; diff --git a/sentry/src/test/java/io/sentry/NoOpTransactionTest.kt b/sentry/src/test/java/io/sentry/NoOpTransactionTest.kt index b228ae6f23..7c0ed522ed 100644 --- a/sentry/src/test/java/io/sentry/NoOpTransactionTest.kt +++ b/sentry/src/test/java/io/sentry/NoOpTransactionTest.kt @@ -15,6 +15,10 @@ class NoOpTransactionTest { fun `startChild does not return null`() { assertNotNull(transaction.startChild("op")) assertNotNull(transaction.startChild("op", "desc")) + assertNotNull(transaction.startChild("op", "desc", SpanOptions())) + assertNotNull(transaction.startChild("op", "desc", SentryNanotimeDate())) + assertNotNull(transaction.startChild("op", "desc", SentryNanotimeDate(), Instrumenter.SENTRY)) + assertNotNull(transaction.startChild("op", "desc", SentryNanotimeDate(), Instrumenter.SENTRY, SpanOptions())) } @Test diff --git a/sentry/src/test/java/io/sentry/SentryTracerTest.kt b/sentry/src/test/java/io/sentry/SentryTracerTest.kt index fafe1f4009..6f9300a907 100644 --- a/sentry/src/test/java/io/sentry/SentryTracerTest.kt +++ b/sentry/src/test/java/io/sentry/SentryTracerTest.kt @@ -328,6 +328,27 @@ class SentryTracerTest { assertEquals(tracer.root.traceId, span.traceId) } + @Test + fun `starting child with operation, description and timestamp creates a new span`() { + val tracer = fixture.getSut() + val sentryDate = SentryNanotimeDate() + val span = tracer.startChild("op", "description", sentryDate) as Span + assertNotNull(span) + assertNotNull(span.spanId) + assertNotNull(span.startDate) + assertEquals("op", span.operation) + assertEquals("description", span.description) + assertEquals(sentryDate, span.startDate) + } + + @Test + fun `sstarting child with operation, description and timestamp adds a span to transaction`() { + val tracer = fixture.getSut() + val span = tracer.startChild("op", "description", SentryNanotimeDate()) + assertEquals(1, tracer.children.size) + assertEquals(span, tracer.children.first()) + } + @Test fun `setting op sets op on TraceContext`() { val tracer = fixture.getSut() From f8d3e91047f0cf932f820c7eba442ba5f413d6fe Mon Sep 17 00:00:00 2001 From: Lukas Bloder Date: Wed, 10 May 2023 17:08:48 +0200 Subject: [PATCH 5/6] add javadoc to TransactionOptions --- .../java/io/sentry/TransactionOptions.java | 90 +++++++++++++++++-- 1 file changed, 82 insertions(+), 8 deletions(-) diff --git a/sentry/src/main/java/io/sentry/TransactionOptions.java b/sentry/src/main/java/io/sentry/TransactionOptions.java index 0b4e12d29e..3362d97940 100644 --- a/sentry/src/main/java/io/sentry/TransactionOptions.java +++ b/sentry/src/main/java/io/sentry/TransactionOptions.java @@ -5,71 +5,145 @@ /** Sentry Transaction options */ public final class TransactionOptions extends SpanOptions { + /** + * Arbitrary data used in {@link SamplingContext} to determine if transaction is going to be + * sampled. + */ private @Nullable CustomSamplingContext customSamplingContext = null; + + /** Defines if transaction should be bound to scope */ private boolean bindToScope = false; + + /** The start timestamp of the transaction */ private @Nullable SentryDate startTimestamp = null; + + /** + * When `waitForChildren` is set to `true`, tracer will finish only when both conditions are met + * (the order of meeting condition does not matter): - tracer itself is finished - all child spans + * are finished. + */ private boolean waitForChildren = false; + /** + * The idle time, measured in ms, to wait until the transaction will be finished. The span will + * use the end timestamp of the last finished span as the endtime for the transaction. + * + *

When set to {@code null} the transaction must be finished manually. + * + *

The default is 3 seconds. + */ private @Nullable Long idleTimeout = null; + + /** + * When `waitForChildren` is set to `true` and this callback is set, it's called before the + * transaction is captured. + */ private @Nullable TransactionFinishedCallback transactionFinishedCallback = null; + /** + * Gets the customSamplingContext + * + * @return customSamplingContext - the customSamplingContext + */ public @Nullable CustomSamplingContext getCustomSamplingContext() { return customSamplingContext; } + /** + * Sets the customSamplingContext + * + * @param customSamplingContext - the customSamplingContext + */ public void setCustomSamplingContext(@Nullable CustomSamplingContext customSamplingContext) { this.customSamplingContext = customSamplingContext; } + /** + * Checks if bindToScope is enabled + * + * @return true if enabled or false otherwise + */ public boolean isBindToScope() { return bindToScope; } + /** + * Sets bindToScope to enabled or disabled + * + * @param bindToScope true if enabled or false otherwise + */ public void setBindToScope(boolean bindToScope) { this.bindToScope = bindToScope; } + /** + * Gets the startTimestamp + * + * @return startTimestamp - the startTimestamp + */ public @Nullable SentryDate getStartTimestamp() { return startTimestamp; } + /** + * Sets the startTimestamp + * + * @param startTimestamp - the startTimestamp + */ public void setStartTimestamp(@Nullable SentryDate startTimestamp) { this.startTimestamp = startTimestamp; } /** - * When `waitForChildren` is set to `true`, tracer will finish only when both conditions are met - * (the order of meeting condition does not matter): - tracer itself is finished - all child spans - * are finished. + * Checks if waitForChildren is enabled + * + * @return true if enabled or false otherwise */ public boolean isWaitForChildren() { return waitForChildren; } + /** + * Sets waitForChildren to enabled or disabled + * + * @param waitForChildren true if enabled or false otherwise + */ public void setWaitForChildren(boolean waitForChildren) { this.waitForChildren = waitForChildren; } /** - * The idle time, measured in ms, to wait until the transaction will be finished. The span will - * use the end timestamp of the last finished span as the endtime for the transaction. - * - *

When set to {@code null} the transaction must be finished manually. + * Gets the idleTimeout * - *

The default is 3 seconds. + * @return idleTimeout - the idleTimeout */ public @Nullable Long getIdleTimeout() { return idleTimeout; } + /** + * Sets the idleTimeout + * + * @param idleTimeout - the idleTimeout + */ public void setIdleTimeout(@Nullable Long idleTimeout) { this.idleTimeout = idleTimeout; } + /** + * Gets the transactionFinishedCallback callback + * + * @return transactionFinishedCallback - the transactionFinishedCallback callback + */ public @Nullable TransactionFinishedCallback getTransactionFinishedCallback() { return transactionFinishedCallback; } + /** + * Sets the transactionFinishedCallback callback + * + * @param transactionFinishedCallback - the transactionFinishedCallback callback + */ public void setTransactionFinishedCallback( @Nullable TransactionFinishedCallback transactionFinishedCallback) { this.transactionFinishedCallback = transactionFinishedCallback; From 7a00e8793226167f06535afd65b321cdcbcbd393 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Wed, 10 May 2023 22:13:41 +0200 Subject: [PATCH 6/6] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5a04ffc9e..4054f490ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ - Auxiliary information (such as current memory load) at the time of ANR event. - If you would like us to provide support for the old approach working alongside the new one on Android 11 and above (e.g. for raising events for slow code on main thread), consider upvoting [this issue](https://github.com/getsentry/sentry-java/issues/2693). - The old watchdog implementation will continue working for older API versions (Android < 11) -- Open up transaction methods ([#2701](https://github.com/getsentry/sentry-java/pull/2701)) +- Open up `TransactionOptions`, `ITransaction` and `IHub` methods allowing consumers modify start/end timestamp of transactions and spans ([#2701](https://github.com/getsentry/sentry-java/pull/2701)) ### Fixes