Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,29 @@
import io.opentelemetry.semconv.HttpAttributes;
import io.opentelemetry.semconv.UrlAttributes;
import io.opentelemetry.semconv.incubating.DbIncubatingAttributes;
import io.opentelemetry.semconv.incubating.GraphqlIncubatingAttributes;
import io.opentelemetry.semconv.incubating.HttpIncubatingAttributes;
import io.sentry.protocol.TransactionNameSource;
import java.util.Arrays;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

@ApiStatus.Internal
public final class SpanDescriptionExtractor {

@SuppressWarnings("deprecation")
public @NotNull OtelSpanInfo extractSpanInfo(
final @NotNull SpanData otelSpan, final @Nullable IOtelSpanWrapper sentrySpan) {
OtelSpanInfo spanInfo = extractSpanInfoInternal(otelSpan);
if (spanInfo != null) {
return spanInfo;
}

return defaultInfo(otelSpan, sentrySpan);
}

@SuppressWarnings("deprecation")
private @Nullable OtelSpanInfo extractSpanInfoInternal(final @NotNull SpanData otelSpan) {
final @NotNull Attributes attributes = otelSpan.getAttributes();

final @Nullable String httpMethod = attributes.get(HttpAttributes.HTTP_REQUEST_METHOD);
Expand All @@ -30,6 +41,17 @@ public final class SpanDescriptionExtractor {
return descriptionForDbSystem(otelSpan);
}

final @Nullable String graphqlOperationType =
attributes.get(GraphqlIncubatingAttributes.GRAPHQL_OPERATION_TYPE);
if (graphqlOperationType != null) {
return descriptionForGraphql(otelSpan);
}

return null;
}

private @NotNull OtelSpanInfo defaultInfo(
final @NotNull SpanData otelSpan, final @Nullable IOtelSpanWrapper sentrySpan) {
final @NotNull String name = otelSpan.getName();
final @Nullable String maybeDescription =
sentrySpan != null ? sentrySpan.getDescription() : name;
Expand Down Expand Up @@ -105,4 +127,25 @@ private OtelSpanInfo descriptionForDbSystem(final @NotNull SpanData otelSpan) {

return new OtelSpanInfo("db", otelSpan.getName(), TransactionNameSource.TASK);
}

private @Nullable OtelSpanInfo descriptionForGraphql(final @NotNull SpanData otelSpan) {
final @NotNull String name = otelSpan.getName();
// do not replace span name set by customer
if (!Arrays.asList("query", "mutation", "subscription").contains(name)) {
return null;
}
final @NotNull Attributes attributes = otelSpan.getAttributes();
@Nullable
String graphqlOperationType =
attributes.get(GraphqlIncubatingAttributes.GRAPHQL_OPERATION_TYPE);
@Nullable
String graphqlOperationName =
attributes.get(GraphqlIncubatingAttributes.GRAPHQL_OPERATION_NAME);
if (graphqlOperationType != null && graphqlOperationName != null) {
String description = graphqlOperationType + " " + graphqlOperationName;
return new OtelSpanInfo(description, description, TransactionNameSource.TASK);
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import io.opentelemetry.sdk.trace.data.SpanData
import io.opentelemetry.semconv.HttpAttributes
import io.opentelemetry.semconv.UrlAttributes
import io.opentelemetry.semconv.incubating.DbIncubatingAttributes
import io.opentelemetry.semconv.incubating.GraphqlIncubatingAttributes
import io.opentelemetry.semconv.incubating.HttpIncubatingAttributes
import io.sentry.protocol.TransactionNameSource
import kotlin.test.Test
Expand Down Expand Up @@ -253,6 +254,39 @@ class SpanDescriptionExtractorTest {
assertEquals(TransactionNameSource.CUSTOM, info.transactionNameSource)
}

@Test
fun `sets op to graphql for span with graphql operation type`() {
givenAttributes(
mapOf(
GraphqlIncubatingAttributes.GRAPHQL_OPERATION_TYPE to "query",
GraphqlIncubatingAttributes.GRAPHQL_OPERATION_NAME to "GreetingQuery",
)
)

val info = whenExtractingSpanInfo()

assertEquals("query GreetingQuery", info.op)
assertEquals("query GreetingQuery", info.description)
assertEquals(TransactionNameSource.TASK, info.transactionNameSource)
}

@Test
fun `does not set op to graphql for span with graphql operation type if span name has been overridden`() {
givenAttributes(
mapOf(
GraphqlIncubatingAttributes.GRAPHQL_OPERATION_TYPE to "query",
GraphqlIncubatingAttributes.GRAPHQL_OPERATION_NAME to "GreetingQuery",
)
)
givenSpanName("my-custom-span-name")

val info = whenExtractingSpanInfo()

assertEquals("my-custom-span-name", info.op)
assertEquals("my-custom-span-name", info.description)
assertEquals(TransactionNameSource.CUSTOM, info.transactionNameSource)
}

private fun createSpanContext(
isRemote: Boolean,
traceId: String = "f9118105af4a2d42b4124532cd1065ff",
Expand Down
Loading