Skip to content

Commit 9c6af50

Browse files
Polish Performance API (#1165)
1 parent c3b9cf7 commit 9c6af50

File tree

31 files changed

+259
-204
lines changed

31 files changed

+259
-204
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
# vNext
22

3-
* Enchancement: Support SENTRY_TRACES_SAMPLE_RATE conf. via env variables (#1171)
3+
* Enhancement: Support SENTRY_TRACES_SAMPLE_RATE conf. via env variables (#1171)
44
* Enhancement: Pass request to CustomSamplingContext in Spring integration (#1172)
55
* Ref: Set SpanContext on SentryTransaction to avoid potential NPE (#1173)
66
* Fix: Free Local Refs manually due to Android local ref. count limits
77
* Enhancement: Move `SentrySpanClientHttpRequestInterceptor` to Spring module (#1181)
88
* Enhancement: Add overload for `transaction/span.finish(SpanStatus)` (#1182)
99
* Fix: Bring back support for setting transaction name without ongoing transaction (#1183)
1010
* Enhancement: Simplify registering traces sample callback in Spring integration (#1184)
11+
* Enhancement: Polish Performance API (#1165)
1112
* Enhancement: Set "debug" through external properties (#1186)
1213

1314
# 4.0.0-alpha.3

sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
import io.sentry.Breadcrumb;
44
import io.sentry.EventProcessor;
5+
import io.sentry.ISpan;
56
import io.sentry.ITransaction;
67
import io.sentry.Sentry;
78
import io.sentry.SentryEvent;
89
import io.sentry.SentryLevel;
9-
import io.sentry.Span;
1010
import io.sentry.SpanStatus;
1111
import io.sentry.protocol.Message;
1212
import io.sentry.protocol.User;
@@ -72,7 +72,7 @@ public static void main(String[] args) throws InterruptedException {
7272
options.setTracesSampler(
7373
context -> {
7474
// only 10% of transactions with "/product" prefix will be collected
75-
if (!context.getTransactionContexts().getName().startsWith("/products")) {
75+
if (!context.getTransactionContext().getName().startsWith("/products")) {
7676
return 0.1;
7777
} else {
7878
return 0.5;
@@ -140,10 +140,10 @@ public static void main(String[] args) throws InterruptedException {
140140
// and finish of transaction.
141141
ITransaction transaction = Sentry.startTransaction("transaction name");
142142
// Transactions can contain one or more Spans
143-
Span outerSpan = transaction.startChild();
143+
ISpan outerSpan = transaction.startChild("child");
144144
Thread.sleep(100);
145145
// Spans create a tree structure. Each span can have one ore more spans inside.
146-
Span innerSpan = outerSpan.startChild("jdbc", "select * from product where id = :id");
146+
ISpan innerSpan = outerSpan.startChild("jdbc", "select * from product where id = :id");
147147
innerSpan.setStatus(SpanStatus.OK);
148148
Thread.sleep(300);
149149
// Finish the span and mark the end time of the span execution.

sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanRestTemplateCustomizerTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class SentrySpanRestTemplateCustomizerTest {
5858
assertThat(result).isEqualTo("OK")
5959
assertThat(fixture.transaction.spans).hasSize(1)
6060
val span = fixture.transaction.spans.first()
61-
assertThat(span.operation).isEqualTo("http")
61+
assertThat(span.operation).isEqualTo("http.client")
6262
assertThat(span.description).isEqualTo("GET /test/{id}")
6363
assertThat(span.status).isEqualTo(SpanStatus.OK)
6464
fixture.mockServer.verify()
@@ -71,7 +71,7 @@ class SentrySpanRestTemplateCustomizerTest {
7171
} catch (e: Throwable) {}
7272
assertThat(fixture.transaction.spans).hasSize(1)
7373
val span = fixture.transaction.spans.first()
74-
assertThat(span.operation).isEqualTo("http")
74+
assertThat(span.operation).isEqualTo("http.client")
7575
assertThat(span.description).isEqualTo("GET /test/{id}")
7676
assertThat(span.status).isEqualTo(SpanStatus.INTERNAL_ERROR)
7777
fixture.mockServer.verify()

sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpan.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,21 @@
1919
*
2020
* @return description
2121
*/
22-
@AliasFor("value")
2322
String description() default "";
2423

2524
/**
2625
* Span operation.
2726
*
2827
* @return operation.
2928
*/
29+
@AliasFor("value")
3030
String operation() default "";
3131

3232
/**
33-
* Span description.
33+
* Span operation.
3434
*
35-
* @return description.
35+
* @return operation.
3636
*/
37-
@AliasFor("description")
37+
@AliasFor("operation")
3838
String value() default "";
3939
}

sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanAdvice.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,12 @@ public Object invoke(final @NotNull MethodInvocation invocation) throws Throwabl
3737
final Method mostSpecificMethod =
3838
AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass());
3939
final Class<?> targetClass = invocation.getMethod().getDeclaringClass();
40-
final ISpan span = activeSpan.startChild();
41-
4240
final SentrySpan sentrySpan =
4341
AnnotationUtils.findAnnotation(mostSpecificMethod, SentrySpan.class);
44-
span.setDescription(resolveSpanDescription(targetClass, mostSpecificMethod, sentrySpan));
45-
if (sentrySpan != null && !StringUtils.isEmpty(sentrySpan.operation())) {
46-
span.setOperation(sentrySpan.operation());
42+
final String operation = resolveSpanOperation(targetClass, mostSpecificMethod, sentrySpan);
43+
final ISpan span = activeSpan.startChild(operation);
44+
if (sentrySpan != null && !StringUtils.isEmpty(sentrySpan.description())) {
45+
span.setDescription(sentrySpan.description());
4746
}
4847
try {
4948
final Object result = invocation.proceed();
@@ -59,7 +58,7 @@ public Object invoke(final @NotNull MethodInvocation invocation) throws Throwabl
5958
}
6059
}
6160

62-
private String resolveSpanDescription(
61+
private String resolveSpanOperation(
6362
Class<?> targetClass, Method method, @Nullable SentrySpan sentrySpan) {
6463
return sentrySpan == null || StringUtils.isEmpty(sentrySpan.value())
6564
? targetClass.getSimpleName() + "." + method.getName()

sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientHttpRequestInterceptor.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,9 @@ public SentrySpanClientHttpRequestInterceptor(final @NotNull IHub hub) {
4141
return execution.execute(request, body);
4242
}
4343

44-
final ISpan span = activeSpan.startChild();
44+
final ISpan span = activeSpan.startChild("http.client");
4545
span.setDescription(
4646
request.getMethodValue() + " " + ensureLeadingSlash(urlTemplate.get().poll()));
47-
span.setOperation("http");
4847

4948
final SentryTraceHeader sentryTraceHeader = activeSpan.toSentryTrace();
5049
request.getHeaders().add(sentryTraceHeader.getName(), sentryTraceHeader.getValue());

sentry-spring/src/test/kotlin/io/sentry/spring/tracing/SentrySpanAdviceTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ class SentrySpanAdviceTest {
6767
val result = sampleService.methodWithoutSpanDescriptionSet()
6868
assertEquals(2, result)
6969
assertEquals(1, tx.spans.size)
70-
assertEquals("SampleService.methodWithoutSpanDescriptionSet", tx.spans.first().description)
71-
assertNull(tx.spans.first().operation)
70+
assertEquals("SampleService.methodWithoutSpanDescriptionSet", tx.spans.first().operation)
71+
assertNull(tx.spans.first().description)
7272
}
7373

7474
@Test

sentry/api/sentry.api

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public final class io/sentry/Hub : io/sentry/IHub {
124124
public fun setExtra (Ljava/lang/String;Ljava/lang/String;)V
125125
public fun setFingerprint (Ljava/util/List;)V
126126
public fun setLevel (Lio/sentry/SentryLevel;)V
127-
public fun setSpanContext (Ljava/lang/Throwable;Lio/sentry/SpanContext;)V
127+
public fun setSpanContext (Ljava/lang/Throwable;Lio/sentry/ISpan;)V
128128
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
129129
public fun setTransaction (Ljava/lang/String;)V
130130
public fun setUser (Lio/sentry/protocol/User;)V
@@ -163,7 +163,7 @@ public final class io/sentry/HubAdapter : io/sentry/IHub {
163163
public fun setExtra (Ljava/lang/String;Ljava/lang/String;)V
164164
public fun setFingerprint (Ljava/util/List;)V
165165
public fun setLevel (Lio/sentry/SentryLevel;)V
166-
public fun setSpanContext (Ljava/lang/Throwable;Lio/sentry/SpanContext;)V
166+
public fun setSpanContext (Ljava/lang/Throwable;Lio/sentry/ISpan;)V
167167
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
168168
public fun setTransaction (Ljava/lang/String;)V
169169
public fun setUser (Lio/sentry/protocol/User;)V
@@ -217,7 +217,7 @@ public abstract interface class io/sentry/IHub {
217217
public abstract fun setExtra (Ljava/lang/String;Ljava/lang/String;)V
218218
public abstract fun setFingerprint (Ljava/util/List;)V
219219
public abstract fun setLevel (Lio/sentry/SentryLevel;)V
220-
public abstract fun setSpanContext (Ljava/lang/Throwable;Lio/sentry/SpanContext;)V
220+
public abstract fun setSpanContext (Ljava/lang/Throwable;Lio/sentry/ISpan;)V
221221
public abstract fun setTag (Ljava/lang/String;Ljava/lang/String;)V
222222
public abstract fun setTransaction (Ljava/lang/String;)V
223223
public abstract fun setUser (Lio/sentry/protocol/User;)V
@@ -287,8 +287,8 @@ public abstract interface class io/sentry/ISpan {
287287
public abstract fun setStatus (Lio/sentry/SpanStatus;)V
288288
public abstract fun setTag (Ljava/lang/String;Ljava/lang/String;)V
289289
public abstract fun setThrowable (Ljava/lang/Throwable;)V
290-
public abstract fun startChild ()Lio/sentry/Span;
291-
public abstract fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/Span;
290+
public abstract fun startChild (Ljava/lang/String;)Lio/sentry/ISpan;
291+
public abstract fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/ISpan;
292292
public abstract fun toSentryTrace ()Lio/sentry/SentryTraceHeader;
293293
}
294294

@@ -303,8 +303,6 @@ public abstract interface class io/sentry/ITransaction : io/sentry/ISpan {
303303
public abstract fun isSampled ()Ljava/lang/Boolean;
304304
public abstract fun setName (Ljava/lang/String;)V
305305
public abstract fun setRequest (Lio/sentry/protocol/Request;)V
306-
public abstract fun startChild (Lio/sentry/SpanId;)Lio/sentry/Span;
307-
public abstract fun startChild (Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;)Lio/sentry/Span;
308306
}
309307

310308
public abstract interface class io/sentry/ITransportFactory {
@@ -341,13 +339,29 @@ public final class io/sentry/NoOpLogger : io/sentry/ILogger {
341339
public fun log (Lio/sentry/SentryLevel;Ljava/lang/Throwable;Ljava/lang/String;[Ljava/lang/Object;)V
342340
}
343341

342+
public final class io/sentry/NoOpSpan : io/sentry/ISpan {
343+
public fun finish ()V
344+
public fun finish (Lio/sentry/SpanStatus;)V
345+
public static fun getInstance ()Lio/sentry/NoOpSpan;
346+
public fun getSpanContext ()Lio/sentry/SpanContext;
347+
public fun getThrowable ()Ljava/lang/Throwable;
348+
public fun setDescription (Ljava/lang/String;)V
349+
public fun setOperation (Ljava/lang/String;)V
350+
public fun setStatus (Lio/sentry/SpanStatus;)V
351+
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
352+
public fun setThrowable (Ljava/lang/Throwable;)V
353+
public fun startChild (Ljava/lang/String;)Lio/sentry/ISpan;
354+
public fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/ISpan;
355+
public fun toSentryTrace ()Lio/sentry/SentryTraceHeader;
356+
}
357+
344358
public final class io/sentry/NoOpTransaction : io/sentry/ITransaction {
345-
public fun <init> ()V
346359
public fun finish ()V
347360
public fun finish (Lio/sentry/SpanStatus;)V
348361
public fun getContexts ()Lio/sentry/protocol/Contexts;
349362
public fun getDescription ()Ljava/lang/String;
350363
public fun getEventId ()Lio/sentry/protocol/SentryId;
364+
public static fun getInstance ()Lio/sentry/NoOpTransaction;
351365
public fun getLatestActiveSpan ()Lio/sentry/Span;
352366
public fun getRequest ()Lio/sentry/protocol/Request;
353367
public fun getSpanContext ()Lio/sentry/SpanContext;
@@ -362,10 +376,8 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction {
362376
public fun setStatus (Lio/sentry/SpanStatus;)V
363377
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
364378
public fun setThrowable (Ljava/lang/Throwable;)V
365-
public fun startChild ()Lio/sentry/Span;
366-
public fun startChild (Lio/sentry/SpanId;)Lio/sentry/Span;
367-
public fun startChild (Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;)Lio/sentry/Span;
368-
public fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/Span;
379+
public fun startChild (Ljava/lang/String;)Lio/sentry/ISpan;
380+
public fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/ISpan;
369381
public fun toSentryTrace ()Lio/sentry/SentryTraceHeader;
370382
}
371383

@@ -394,7 +406,7 @@ public final class io/sentry/RequestDetails {
394406
public final class io/sentry/SamplingContext {
395407
public fun <init> (Lio/sentry/TransactionContext;Lio/sentry/CustomSamplingContext;)V
396408
public fun getCustomSamplingContext ()Lio/sentry/CustomSamplingContext;
397-
public fun getTransactionContexts ()Lio/sentry/TransactionContext;
409+
public fun getTransactionContext ()Lio/sentry/TransactionContext;
398410
}
399411

400412
public final class io/sentry/Scope : java/lang/Cloneable {
@@ -824,10 +836,8 @@ public final class io/sentry/SentryTransaction : io/sentry/SentryBaseEvent, io/s
824836
public fun setName (Ljava/lang/String;)V
825837
public fun setOperation (Ljava/lang/String;)V
826838
public fun setStatus (Lio/sentry/SpanStatus;)V
827-
public fun startChild ()Lio/sentry/Span;
828-
public fun startChild (Lio/sentry/SpanId;)Lio/sentry/Span;
829-
public fun startChild (Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;)Lio/sentry/Span;
830-
public fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/Span;
839+
public fun startChild (Ljava/lang/String;)Lio/sentry/ISpan;
840+
public fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/ISpan;
831841
public fun toSentryTrace ()Lio/sentry/SentryTraceHeader;
832842
}
833843

@@ -886,8 +896,8 @@ public final class io/sentry/Span : io/sentry/SpanContext, io/sentry/ISpan {
886896
public fun getThrowable ()Ljava/lang/Throwable;
887897
public fun getTimestamp ()Ljava/util/Date;
888898
public fun setThrowable (Ljava/lang/Throwable;)V
889-
public fun startChild ()Lio/sentry/Span;
890-
public fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/Span;
899+
public fun startChild (Ljava/lang/String;)Lio/sentry/ISpan;
900+
public fun startChild (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/ISpan;
891901
public fun toSentryTrace ()Lio/sentry/SentryTraceHeader;
892902
}
893903

@@ -910,7 +920,6 @@ public class io/sentry/SpanContext : java/lang/Cloneable {
910920
public fun getTags ()Ljava/util/Map;
911921
public fun setDescription (Ljava/lang/String;)V
912922
public fun setOperation (Ljava/lang/String;)V
913-
public fun setSampled (Ljava/lang/Boolean;)V
914923
public fun setStatus (Lio/sentry/SpanStatus;)V
915924
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
916925
}
@@ -958,7 +967,7 @@ public final class io/sentry/SystemOutLogger : io/sentry/ILogger {
958967

959968
public final class io/sentry/TransactionContext : io/sentry/SpanContext {
960969
public fun <init> (Ljava/lang/String;)V
961-
public fun <init> (Ljava/lang/String;Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/Boolean;)V
970+
public fun <init> (Ljava/lang/String;Ljava/lang/Boolean;)V
962971
public static fun fromSentryTrace (Ljava/lang/String;Lio/sentry/SentryTraceHeader;)Lio/sentry/TransactionContext;
963972
public fun getName ()Ljava/lang/String;
964973
public fun getParentSampled ()Ljava/lang/Boolean;

sentry/src/main/java/io/sentry/Hub.java

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ public final class Hub implements IHub {
1818
private final @NotNull SentryOptions options;
1919
private volatile boolean isEnabled;
2020
private final @NotNull Stack stack;
21-
private final @NotNull TracingSampler tracingSampler;
22-
private final @NotNull WeakHashMap<Throwable, SpanContext> throwableToSpanContext =
23-
new WeakHashMap<>();
21+
private final @NotNull TracesSampler tracesSampler;
22+
private final @NotNull WeakHashMap<Throwable, ISpan> throwableToSpan = new WeakHashMap<>();
2423

2524
public Hub(final @NotNull SentryOptions options) {
2625
this(options, createRootStackItem(options));
@@ -32,7 +31,7 @@ private Hub(final @NotNull SentryOptions options, final @NotNull Stack stack) {
3231
validateOptions(options);
3332

3433
this.options = options;
35-
this.tracingSampler = new TracingSampler(options);
34+
this.tracesSampler = new TracesSampler(options);
3635
this.stack = stack;
3736
this.lastEventId = SentryId.EMPTY_ID;
3837

@@ -171,10 +170,10 @@ public SentryId captureEnvelope(
171170

172171
private void assignTraceContext(final @NotNull SentryEvent event) {
173172
if (event.getThrowable() != null) {
174-
final SpanContext spanContext = throwableToSpanContext.get(event.getThrowable());
175-
if (spanContext != null) {
173+
final ISpan span = throwableToSpan.get(event.getThrowable());
174+
if (span != null && span.getSpanContext() != null) {
176175
if (event.getContexts().getTrace() == null) {
177-
event.getContexts().setTrace(spanContext);
176+
event.getContexts().setTrace(span.getSpanContext());
178177
}
179178
}
180179
}
@@ -556,20 +555,15 @@ public void flush(long timeoutMillis) {
556555

557556
@Override
558557
public @NotNull ITransaction startTransaction(
559-
final @NotNull TransactionContext transactionContexts) {
560-
return this.startTransaction(transactionContexts, null);
558+
final @NotNull TransactionContext transactionContext) {
559+
return this.startTransaction(transactionContext, null);
561560
}
562561

563562
@Override
564563
public @NotNull ITransaction startTransaction(
565-
final @NotNull TransactionContext transactionContexts,
564+
final @NotNull TransactionContext transactionContext,
566565
final @Nullable CustomSamplingContext customSamplingContext) {
567-
Objects.requireNonNull(transactionContexts, "transactionContexts is required");
568-
569-
final SamplingContext samplingContext =
570-
new SamplingContext(transactionContexts, customSamplingContext);
571-
boolean samplingDecision = tracingSampler.sample(samplingContext);
572-
transactionContexts.setSampled(samplingDecision);
566+
Objects.requireNonNull(transactionContext, "transactionContext is required");
573567

574568
ITransaction transaction;
575569
if (!isEnabled()) {
@@ -578,9 +572,14 @@ public void flush(long timeoutMillis) {
578572
.log(
579573
SentryLevel.WARNING,
580574
"Instance is disabled and this 'startTransaction' returns a no-op.");
581-
transaction = new NoOpTransaction();
575+
transaction = NoOpTransaction.getInstance();
582576
} else {
583-
transaction = new SentryTransaction(transactionContexts, this);
577+
final SamplingContext samplingContext =
578+
new SamplingContext(transactionContext, customSamplingContext);
579+
boolean samplingDecision = tracesSampler.sample(samplingContext);
580+
transactionContext.setSampled(samplingDecision);
581+
582+
transaction = new SentryTransaction(transactionContext, this);
584583
}
585584
return transaction;
586585
}
@@ -616,16 +615,20 @@ public void flush(long timeoutMillis) {
616615
}
617616

618617
@Override
619-
public void setSpanContext(
620-
final @NotNull Throwable throwable, final @NotNull SpanContext spanContext) {
618+
@ApiStatus.Internal
619+
public void setSpanContext(final @NotNull Throwable throwable, final @NotNull ISpan span) {
621620
Objects.requireNonNull(throwable, "throwable is required");
622-
Objects.requireNonNull(spanContext, "spanContext is required");
623-
this.throwableToSpanContext.put(throwable, spanContext);
621+
Objects.requireNonNull(span, "span is required");
622+
this.throwableToSpan.put(throwable, span);
624623
}
625624

626625
@Override
627626
public @Nullable SpanContext getSpanContext(final @NotNull Throwable throwable) {
628627
Objects.requireNonNull(throwable, "throwable is required");
629-
return this.throwableToSpanContext.get(throwable);
628+
final ISpan span = this.throwableToSpan.get(throwable);
629+
if (span != null) {
630+
return span.getSpanContext();
631+
}
632+
return null;
630633
}
631634
}

sentry/src/main/java/io/sentry/HubAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ public IHub clone() {
181181
}
182182

183183
@Override
184-
public void setSpanContext(final @NotNull Throwable t, final @NotNull SpanContext sc) {
184+
public void setSpanContext(final @NotNull Throwable t, final @NotNull ISpan sc) {
185185
Sentry.getCurrentHub().setSpanContext(t, sc);
186186
}
187187

0 commit comments

Comments
 (0)