diff --git a/CHANGELOG.md b/CHANGELOG.md index f8c8e1054c..4ab40caf67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - The Spring Boot integration can now be configured to add the `SentryAppender` to specific loggers instead of the `ROOT` logger ([#2173](https://github.com/getsentry/sentry-java/pull/2173)) - You can specify the loggers using `"sentry.logging.loggers[0]=foo.bar` and `"sentry.logging.loggers[1]=baz` in your `application.properties` - Add capabilities to track Jetpack Compose composition/rendering time ([#2507](https://github.com/getsentry/sentry-java/pull/2507)) +- Adapt span op and description for graphql to fit spec ([#2607](https://github.com/getsentry/sentry-java/pull/2607)) ### Fixes diff --git a/sentry-apollo-3/src/main/java/io/sentry/apollo3/SentryApollo3HttpInterceptor.kt b/sentry-apollo-3/src/main/java/io/sentry/apollo3/SentryApollo3HttpInterceptor.kt index 46db8f7914..2c4c07cbdc 100644 --- a/sentry-apollo-3/src/main/java/io/sentry/apollo3/SentryApollo3HttpInterceptor.kt +++ b/sentry-apollo-3/src/main/java/io/sentry/apollo3/SentryApollo3HttpInterceptor.kt @@ -96,11 +96,11 @@ class SentryApollo3HttpInterceptor @JvmOverloads constructor(private val hub: IH val method = request.method val operationName = operationNameFromHeaders(request) - val operation = operationName ?: "apollo.client" - val operationType = request.valueForHeader(SENTRY_APOLLO_3_OPERATION_TYPE) ?: method + val operationType = request.valueForHeader(SENTRY_APOLLO_3_OPERATION_TYPE) + val operation = if (operationType != null) "http.graphql.$operationType" else "http.graphql" val operationId = request.valueForHeader("X-APOLLO-OPERATION-ID") val variables = request.valueForHeader(SENTRY_APOLLO_3_VARIABLES) - val description = "$operationType ${operationName ?: urlDetails.urlOrFallback}" + val description = "${operationType ?: method} ${operationName ?: urlDetails.urlOrFallback}" return activeSpan.startChild(operation, description).apply { urlDetails.applyToSpan(this) diff --git a/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorTest.kt b/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorTest.kt index f38d77d012..5266fc69af 100644 --- a/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorTest.kt +++ b/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorTest.kt @@ -258,7 +258,7 @@ class SentryApollo3InterceptorTest { private fun assertTransactionDetails(it: SentryTransaction) { assertEquals(1, it.spans.size) val httpClientSpan = it.spans.first() - assertEquals("LaunchDetails", httpClientSpan.op) + assertEquals("http.graphql", httpClientSpan.op) assertTrue { httpClientSpan.description?.startsWith("Post LaunchDetails") == true } assertNotNull(httpClientSpan.data) { assertNotNull(it["operationId"]) diff --git a/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorWithVariablesTest.kt b/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorWithVariablesTest.kt index 3de27196b6..cab0be8915 100644 --- a/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorWithVariablesTest.kt +++ b/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorWithVariablesTest.kt @@ -145,7 +145,7 @@ class SentryApollo3InterceptorWithVariablesTest { private fun assertTransactionDetails(it: SentryTransaction) { assertEquals(1, it.spans.size) val httpClientSpan = it.spans.first() - assertEquals("LaunchDetails", httpClientSpan.op) + assertEquals("http.graphql.query", httpClientSpan.op) assertEquals("query LaunchDetails", httpClientSpan.description) assertNotNull(httpClientSpan.data) { assertNotNull(it["operationId"]) diff --git a/sentry-apollo/src/main/java/io/sentry/apollo/SentryApolloInterceptor.kt b/sentry-apollo/src/main/java/io/sentry/apollo/SentryApolloInterceptor.kt index a5bb3d7ab8..a52871b8fd 100644 --- a/sentry-apollo/src/main/java/io/sentry/apollo/SentryApolloInterceptor.kt +++ b/sentry-apollo/src/main/java/io/sentry/apollo/SentryApolloInterceptor.kt @@ -108,8 +108,9 @@ class SentryApolloInterceptor( is Subscription -> "subscription" else -> request.operation.javaClass.simpleName } + val op = "http.graphql.$operationType" val description = "$operationType $operation" - return activeSpan.startChild(operation, description) + return activeSpan.startChild(op, description) } private fun finish(span: ISpan, request: InterceptorRequest, response: InterceptorResponse? = null) { diff --git a/sentry-apollo/src/test/java/io/sentry/apollo/SentryApolloInterceptorTest.kt b/sentry-apollo/src/test/java/io/sentry/apollo/SentryApolloInterceptorTest.kt index d0a883b7c6..97bb307b34 100644 --- a/sentry-apollo/src/test/java/io/sentry/apollo/SentryApolloInterceptorTest.kt +++ b/sentry-apollo/src/test/java/io/sentry/apollo/SentryApolloInterceptorTest.kt @@ -205,7 +205,7 @@ class SentryApolloInterceptorTest { private fun assertTransactionDetails(it: SentryTransaction) { assertEquals(1, it.spans.size) val httpClientSpan = it.spans.first() - assertEquals("LaunchDetails", httpClientSpan.op) + assertEquals("http.graphql.query", httpClientSpan.op) assertEquals("query LaunchDetails", httpClientSpan.description) assertNotNull(httpClientSpan.data) { assertNotNull(it["operationId"]) diff --git a/sentry-graphql/src/main/java/io/sentry/graphql/SentryInstrumentation.java b/sentry-graphql/src/main/java/io/sentry/graphql/SentryInstrumentation.java index b66f6c9c89..8def4f3a10 100644 --- a/sentry-graphql/src/main/java/io/sentry/graphql/SentryInstrumentation.java +++ b/sentry-graphql/src/main/java/io/sentry/graphql/SentryInstrumentation.java @@ -73,7 +73,7 @@ public SentryInstrumentation() { final TracingState tracingState = parameters.getInstrumentationState(); final ISpan transaction = tracingState.getTransaction(); if (transaction != null) { - final ISpan span = transaction.startChild(findDataFetcherTag(parameters)); + final ISpan span = createSpan(transaction, parameters); try { final Object result = dataFetcher.get(environment); if (result instanceof CompletableFuture) { @@ -127,8 +127,8 @@ private void finish( finish(span, environment, null); } - private @NotNull String findDataFetcherTag( - final @NotNull InstrumentationFieldFetchParameters parameters) { + private @NotNull ISpan createSpan( + @NotNull ISpan transaction, @NotNull InstrumentationFieldFetchParameters parameters) { final GraphQLOutputType type = parameters.getExecutionStepInfo().getParent().getType(); GraphQLObjectType parent; if (type instanceof GraphQLNonNull) { @@ -137,7 +137,9 @@ private void finish( parent = (GraphQLObjectType) type; } - return parent.getName() + "." + parameters.getExecutionStepInfo().getPath().getSegmentName(); + return transaction.startChild( + "graphql", + parent.getName() + "." + parameters.getExecutionStepInfo().getPath().getSegmentName()); } static final class TracingState implements InstrumentationState { diff --git a/sentry-graphql/src/test/kotlin/io/sentry/graphql/SentryInstrumentationTest.kt b/sentry-graphql/src/test/kotlin/io/sentry/graphql/SentryInstrumentationTest.kt index 6507576de0..7604bc8ff4 100644 --- a/sentry-graphql/src/test/kotlin/io/sentry/graphql/SentryInstrumentationTest.kt +++ b/sentry-graphql/src/test/kotlin/io/sentry/graphql/SentryInstrumentationTest.kt @@ -75,7 +75,8 @@ class SentryInstrumentationTest { assertTrue(result.errors.isEmpty()) assertEquals(1, fixture.activeSpan.children.size) val span = fixture.activeSpan.children.first() - assertEquals("Query.shows", span.operation) + assertEquals("graphql", span.operation) + assertEquals("Query.shows", span.description) assertTrue(span.isFinished) assertEquals(SpanStatus.OK, span.status) } @@ -89,7 +90,8 @@ class SentryInstrumentationTest { assertTrue(result.errors.isNotEmpty()) assertEquals(1, fixture.activeSpan.children.size) val span = fixture.activeSpan.children.first() - assertEquals("Query.shows", span.operation) + assertEquals("graphql", span.operation) + assertEquals("Query.shows", span.description) assertTrue(span.isFinished) assertEquals(SpanStatus.INTERNAL_ERROR, span.status) } @@ -113,7 +115,8 @@ class SentryInstrumentationTest { assertTrue(result.errors.isEmpty()) assertEquals(1, fixture.activeSpan.children.size) val span = fixture.activeSpan.children.first() - assertEquals("Query.shows", span.operation) + assertEquals("graphql", span.operation) + assertEquals("Query.shows", span.description) assertNotNull(span.isSampled) { assertFalse(it) } @@ -128,7 +131,7 @@ class SentryInstrumentationTest { assertTrue(result.errors.isEmpty()) assertEquals(1, fixture.activeSpan.children.size) val span = fixture.activeSpan.children.first() - assertEquals("Query.shows", span.operation) + assertEquals("graphql", span.operation) assertEquals("changed", span.description) assertTrue(span.isFinished) }