diff --git a/CHANGELOG.md b/CHANGELOG.md index a1f77ed4c76..ab3d2a904e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # vNext * Feat: Support logging via JUL (#1211) +* Fix: Fix returning Sentry trace header from Span (#1217) # 4.0.0 diff --git a/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanRestTemplateCustomizerTest.kt b/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanRestTemplateCustomizerTest.kt index 1f2f04dcdb2..5c08d8b7954 100644 --- a/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanRestTemplateCustomizerTest.kt +++ b/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanRestTemplateCustomizerTest.kt @@ -10,7 +10,6 @@ import io.sentry.SpanContext import io.sentry.SpanStatus import kotlin.test.Test import org.assertj.core.api.Assertions.assertThat -import org.hamcrest.core.IsNull import org.springframework.http.HttpMethod import org.springframework.http.HttpStatus import org.springframework.http.MediaType @@ -24,7 +23,7 @@ class SentrySpanRestTemplateCustomizerTest { val hub = mock() val restTemplate = RestTemplate() var mockServer = MockRestServiceServer.createServer(restTemplate) - val transaction = SentryTransaction("aTransaction", SpanContext(), hub) + val transaction = SentryTransaction("aTransaction", SpanContext(true), hub) internal val customizer = SentrySpanRestTemplateCustomizer(hub) fun getSut(isTransactionActive: Boolean, status: HttpStatus = HttpStatus.OK): RestTemplate { @@ -37,7 +36,12 @@ class SentrySpanRestTemplateCustomizerTest { mockServer.expect(MockRestRequestMatchers.requestTo("/test/123")) .andExpect(MockRestRequestMatchers.method(HttpMethod.GET)) - .andExpect(MockRestRequestMatchers.header("sentry-trace", IsNull.notNullValue())) + .andExpect { + // must have trace id from the parent transaction and must not contain spanId from the parent transaction + assertThat(it.headers["sentry-trace"]!!.first()).startsWith(transaction.spanContext.traceId.toString()) + .endsWith("-1") + .doesNotContain(transaction.spanContext.spanId.toString()) + } .andRespond(MockRestResponseCreators.withStatus(status).body("OK").contentType(MediaType.APPLICATION_JSON)) } else { mockServer.expect(MockRestRequestMatchers.requestTo("/test/123")) diff --git a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientHttpRequestInterceptor.java b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientHttpRequestInterceptor.java index 9e939ee5a3f..1f9ef59979a 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientHttpRequestInterceptor.java +++ b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientHttpRequestInterceptor.java @@ -45,7 +45,7 @@ public SentrySpanClientHttpRequestInterceptor(final @NotNull IHub hub) { span.setDescription( request.getMethodValue() + " " + ensureLeadingSlash(urlTemplate.get().poll())); - final SentryTraceHeader sentryTraceHeader = activeSpan.toSentryTrace(); + final SentryTraceHeader sentryTraceHeader = span.toSentryTrace(); request.getHeaders().add(sentryTraceHeader.getName(), sentryTraceHeader.getValue()); try { final ClientHttpResponse response = execution.execute(request, body); diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 187efe49d34..1ea2b32d738 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -937,8 +937,10 @@ public class io/sentry/SpanContext : java/lang/Cloneable { public fun getOperation ()Ljava/lang/String; public fun getParentSpanId ()Lio/sentry/SpanId; public fun getSampled ()Ljava/lang/Boolean; + public fun getSpanId ()Lio/sentry/SpanId; public fun getStatus ()Lio/sentry/SpanStatus; public fun getTags ()Ljava/util/Map; + public fun getTraceId ()Lio/sentry/protocol/SentryId; 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/Span.java b/sentry/src/main/java/io/sentry/Span.java index 8ce55c54133..6e9908bff17 100644 --- a/sentry/src/main/java/io/sentry/Span.java +++ b/sentry/src/main/java/io/sentry/Span.java @@ -56,7 +56,7 @@ public final class Span extends SpanContext implements ISpan { @Override public @NotNull SentryTraceHeader toSentryTrace() { - return transaction.toSentryTrace(); + return new SentryTraceHeader(getTraceId(), getSpanId(), getSampled()); } @Override diff --git a/sentry/src/main/java/io/sentry/SpanContext.java b/sentry/src/main/java/io/sentry/SpanContext.java index 5a2e051b487..3492e16eee8 100644 --- a/sentry/src/main/java/io/sentry/SpanContext.java +++ b/sentry/src/main/java/io/sentry/SpanContext.java @@ -80,12 +80,12 @@ public void setStatus(final @Nullable SpanStatus status) { } @NotNull - SentryId getTraceId() { + public SentryId getTraceId() { return traceId; } @NotNull - SpanId getSpanId() { + public SpanId getSpanId() { return spanId; } diff --git a/sentry/src/test/java/io/sentry/SpanTest.kt b/sentry/src/test/java/io/sentry/SpanTest.kt index a189e95a76b..a14ecb79044 100644 --- a/sentry/src/test/java/io/sentry/SpanTest.kt +++ b/sentry/src/test/java/io/sentry/SpanTest.kt @@ -50,6 +50,20 @@ class SpanTest { assertEquals("description", child.description) } + @Test + fun `converts to Sentry trace header`() { + val traceId = SentryId() + val parentSpanId = SpanId() + val hub = mock() + val span = Span(traceId, parentSpanId, SentryTransaction(TransactionContext("name", true), hub), hub) + val sentryTrace = span.toSentryTrace() + assertEquals(traceId, sentryTrace.traceId) + assertEquals(span.spanId, sentryTrace.spanId) + assertNotNull(sentryTrace.isSampled) { + assertTrue(it) + } + } + @Test fun `starting a child with details adds span to transaction`() { val transaction = SentryTransaction("name")