Remove operation name from graphql span name (#13794)
This commit is contained in:
parent
e36be4942b
commit
fffdb0b751
|
|
@ -1,8 +1,9 @@
|
||||||
# Settings for the GraphQL instrumentation
|
# Settings for the GraphQL instrumentation
|
||||||
|
|
||||||
| System property | Type | Default | Description |
|
| System property | Type | Default | Description |
|
||||||
|--------------------------------------------------------|---------|---------|--------------------------------------------------------------------------------------------|
|
|------------------------------------------------------------------------|---------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `otel.instrumentation.graphql.query-sanitizer.enabled` | Boolean | `true` | Whether to remove sensitive information from query source that is added as span attribute. |
|
| `otel.instrumentation.graphql.query-sanitizer.enabled` | Boolean | `true` | Whether to remove sensitive information from query source that is added as span attribute. |
|
||||||
|
| `otel.instrumentation.graphql.add-operation-name-to-span-name.enabled` | Boolean | `false` | Whether GraphQL operation name is added to the span name. <p>**WARNING**: GraphQL operation name is provided by the client and can have high cardinality. Use only when the server is not exposed to malicious clients. |
|
||||||
|
|
||||||
# Settings for the GraphQL 20 instrumentation
|
# Settings for the GraphQL 20 instrumentation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,3 +24,7 @@ dependencies {
|
||||||
|
|
||||||
latestDepTestLibrary("com.graphql-java:graphql-java:19.+") // see graphql-java-20.0 module
|
latestDepTestLibrary("com.graphql-java:graphql-java:19.+") // see graphql-java-20.0 module
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType<Test>().configureEach {
|
||||||
|
jvmArgs("-Dotel.instrumentation.graphql.add-operation-name-to-span-name.enabled=true")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,15 @@ public final class GraphqlSingletons {
|
||||||
private static final boolean QUERY_SANITIZATION_ENABLED =
|
private static final boolean QUERY_SANITIZATION_ENABLED =
|
||||||
AgentInstrumentationConfig.get()
|
AgentInstrumentationConfig.get()
|
||||||
.getBoolean("otel.instrumentation.graphql.query-sanitizer.enabled", true);
|
.getBoolean("otel.instrumentation.graphql.query-sanitizer.enabled", true);
|
||||||
|
private static final boolean ADD_OPERATION_NAME_TO_SPAN_NAME =
|
||||||
|
AgentInstrumentationConfig.get()
|
||||||
|
.getBoolean(
|
||||||
|
"otel.instrumentation.graphql.add-operation-name-to-span-name.enabled", false);
|
||||||
|
|
||||||
private static final GraphQLTelemetry TELEMETRY =
|
private static final GraphQLTelemetry TELEMETRY =
|
||||||
GraphQLTelemetry.builder(GlobalOpenTelemetry.get())
|
GraphQLTelemetry.builder(GlobalOpenTelemetry.get())
|
||||||
.setSanitizeQuery(QUERY_SANITIZATION_ENABLED)
|
.setSanitizeQuery(QUERY_SANITIZATION_ENABLED)
|
||||||
|
.setAddOperationNameToSpanName(ADD_OPERATION_NAME_TO_SPAN_NAME)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private GraphqlSingletons() {}
|
private GraphqlSingletons() {}
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,11 @@ public final class GraphQLTelemetry {
|
||||||
|
|
||||||
private final OpenTelemetryInstrumentationHelper helper;
|
private final OpenTelemetryInstrumentationHelper helper;
|
||||||
|
|
||||||
GraphQLTelemetry(OpenTelemetry openTelemetry, boolean sanitizeQuery) {
|
GraphQLTelemetry(
|
||||||
|
OpenTelemetry openTelemetry, boolean sanitizeQuery, boolean addOperationNameToSpanName) {
|
||||||
helper =
|
helper =
|
||||||
OpenTelemetryInstrumentationHelper.create(
|
OpenTelemetryInstrumentationHelper.create(
|
||||||
openTelemetry, INSTRUMENTATION_NAME, sanitizeQuery);
|
openTelemetry, INSTRUMENTATION_NAME, sanitizeQuery, addOperationNameToSpanName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ public final class GraphQLTelemetryBuilder {
|
||||||
private final OpenTelemetry openTelemetry;
|
private final OpenTelemetry openTelemetry;
|
||||||
|
|
||||||
private boolean sanitizeQuery = true;
|
private boolean sanitizeQuery = true;
|
||||||
|
private boolean addOperationNameToSpanName = false;
|
||||||
|
|
||||||
GraphQLTelemetryBuilder(OpenTelemetry openTelemetry) {
|
GraphQLTelemetryBuilder(OpenTelemetry openTelemetry) {
|
||||||
this.openTelemetry = openTelemetry;
|
this.openTelemetry = openTelemetry;
|
||||||
|
|
@ -27,11 +28,23 @@ public final class GraphQLTelemetryBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether GraphQL operation name is added to the span name. Default is {@code false}.
|
||||||
|
*
|
||||||
|
* <p>WARNING: GraphQL operation name is provided by the client and can have high cardinality. Use
|
||||||
|
* only when the server is not exposed to malicious clients.
|
||||||
|
*/
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public GraphQLTelemetryBuilder setAddOperationNameToSpanName(boolean addOperationNameToSpanName) {
|
||||||
|
this.addOperationNameToSpanName = addOperationNameToSpanName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new {@link GraphQLTelemetry} with the settings of this {@link
|
* Returns a new {@link GraphQLTelemetry} with the settings of this {@link
|
||||||
* GraphQLTelemetryBuilder}.
|
* GraphQLTelemetryBuilder}.
|
||||||
*/
|
*/
|
||||||
public GraphQLTelemetry build() {
|
public GraphQLTelemetry build() {
|
||||||
return new GraphQLTelemetry(openTelemetry, sanitizeQuery);
|
return new GraphQLTelemetry(openTelemetry, sanitizeQuery, addOperationNameToSpanName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,10 @@ class GraphqlTest extends AbstractGraphqlTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(GraphQL.Builder builder) {
|
protected void configure(GraphQL.Builder builder) {
|
||||||
GraphQLTelemetry telemetry = GraphQLTelemetry.builder(testing.getOpenTelemetry()).build();
|
GraphQLTelemetry telemetry =
|
||||||
|
GraphQLTelemetry.builder(testing.getOpenTelemetry())
|
||||||
|
.setAddOperationNameToSpanName(true)
|
||||||
|
.build();
|
||||||
builder.instrumentation(telemetry.newInstrumentation());
|
builder.instrumentation(telemetry.newInstrumentation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ dependencies {
|
||||||
|
|
||||||
tasks.withType<Test>().configureEach {
|
tasks.withType<Test>().configureEach {
|
||||||
jvmArgs("-Dotel.instrumentation.graphql.data-fetcher.enabled=true")
|
jvmArgs("-Dotel.instrumentation.graphql.data-fetcher.enabled=true")
|
||||||
|
jvmArgs("-Dotel.instrumentation.graphql.add-operation-name-to-span-name.enabled=true")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (findProperty("testLatestDeps") as Boolean) {
|
if (findProperty("testLatestDeps") as Boolean) {
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,17 @@ public final class GraphqlSingletons {
|
||||||
private static final boolean TRIVIAL_DATA_FETCHER_ENABLED =
|
private static final boolean TRIVIAL_DATA_FETCHER_ENABLED =
|
||||||
AgentInstrumentationConfig.get()
|
AgentInstrumentationConfig.get()
|
||||||
.getBoolean("otel.instrumentation.graphql.trivial-data-fetcher.enabled", false);
|
.getBoolean("otel.instrumentation.graphql.trivial-data-fetcher.enabled", false);
|
||||||
|
private static final boolean ADD_OPERATION_NAME_TO_SPAN_NAME =
|
||||||
|
AgentInstrumentationConfig.get()
|
||||||
|
.getBoolean(
|
||||||
|
"otel.instrumentation.graphql.add-operation-name-to-span-name.enabled", false);
|
||||||
|
|
||||||
private static final GraphQLTelemetry TELEMETRY =
|
private static final GraphQLTelemetry TELEMETRY =
|
||||||
GraphQLTelemetry.builder(GlobalOpenTelemetry.get())
|
GraphQLTelemetry.builder(GlobalOpenTelemetry.get())
|
||||||
.setSanitizeQuery(QUERY_SANITIZATION_ENABLED)
|
.setSanitizeQuery(QUERY_SANITIZATION_ENABLED)
|
||||||
.setDataFetcherInstrumentationEnabled(DATA_FETCHER_ENABLED)
|
.setDataFetcherInstrumentationEnabled(DATA_FETCHER_ENABLED)
|
||||||
.setTrivialDataFetcherInstrumentationEnabled(TRIVIAL_DATA_FETCHER_ENABLED)
|
.setTrivialDataFetcherInstrumentationEnabled(TRIVIAL_DATA_FETCHER_ENABLED)
|
||||||
|
.setAddOperationNameToSpanName(ADD_OPERATION_NAME_TO_SPAN_NAME)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private GraphqlSingletons() {}
|
private GraphqlSingletons() {}
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,11 @@ public final class GraphQLTelemetry {
|
||||||
OpenTelemetry openTelemetry,
|
OpenTelemetry openTelemetry,
|
||||||
boolean sanitizeQuery,
|
boolean sanitizeQuery,
|
||||||
Instrumenter<DataFetchingEnvironment, Void> dataFetcherInstrumenter,
|
Instrumenter<DataFetchingEnvironment, Void> dataFetcherInstrumenter,
|
||||||
boolean createSpansForTrivialDataFetcher) {
|
boolean createSpansForTrivialDataFetcher,
|
||||||
helper = GraphqlInstrumenterFactory.createInstrumentationHelper(openTelemetry, sanitizeQuery);
|
boolean addOperationNameToSpanName) {
|
||||||
|
helper =
|
||||||
|
GraphqlInstrumenterFactory.createInstrumentationHelper(
|
||||||
|
openTelemetry, sanitizeQuery, addOperationNameToSpanName);
|
||||||
this.dataFetcherInstrumenter = dataFetcherInstrumenter;
|
this.dataFetcherInstrumenter = dataFetcherInstrumenter;
|
||||||
this.createSpansForTrivialDataFetcher = createSpansForTrivialDataFetcher;
|
this.createSpansForTrivialDataFetcher = createSpansForTrivialDataFetcher;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,9 @@ public final class GraphQLTelemetryBuilder {
|
||||||
private final OpenTelemetry openTelemetry;
|
private final OpenTelemetry openTelemetry;
|
||||||
|
|
||||||
private boolean sanitizeQuery = true;
|
private boolean sanitizeQuery = true;
|
||||||
|
|
||||||
private boolean dataFetcherInstrumentationEnabled = false;
|
private boolean dataFetcherInstrumentationEnabled = false;
|
||||||
|
|
||||||
private boolean trivialDataFetcherInstrumentationEnabled = false;
|
private boolean trivialDataFetcherInstrumentationEnabled = false;
|
||||||
|
private boolean addOperationNameToSpanName = false;
|
||||||
|
|
||||||
GraphQLTelemetryBuilder(OpenTelemetry openTelemetry) {
|
GraphQLTelemetryBuilder(OpenTelemetry openTelemetry) {
|
||||||
this.openTelemetry = openTelemetry;
|
this.openTelemetry = openTelemetry;
|
||||||
|
|
@ -50,6 +49,18 @@ public final class GraphQLTelemetryBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether GraphQL operation name is added to the span name. Default is {@code false}.
|
||||||
|
*
|
||||||
|
* <p>WARNING: GraphQL operation name is provided by the client and can have high cardinality. Use
|
||||||
|
* only when the server is not exposed to malicious clients.
|
||||||
|
*/
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public GraphQLTelemetryBuilder setAddOperationNameToSpanName(boolean addOperationNameToSpanName) {
|
||||||
|
this.addOperationNameToSpanName = addOperationNameToSpanName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new {@link GraphQLTelemetry} with the settings of this {@link
|
* Returns a new {@link GraphQLTelemetry} with the settings of this {@link
|
||||||
* GraphQLTelemetryBuilder}.
|
* GraphQLTelemetryBuilder}.
|
||||||
|
|
@ -60,6 +71,7 @@ public final class GraphQLTelemetryBuilder {
|
||||||
sanitizeQuery,
|
sanitizeQuery,
|
||||||
GraphqlInstrumenterFactory.createDataFetcherInstrumenter(
|
GraphqlInstrumenterFactory.createDataFetcherInstrumenter(
|
||||||
openTelemetry, dataFetcherInstrumentationEnabled),
|
openTelemetry, dataFetcherInstrumentationEnabled),
|
||||||
trivialDataFetcherInstrumentationEnabled);
|
trivialDataFetcherInstrumentationEnabled,
|
||||||
|
addOperationNameToSpanName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@ final class GraphqlInstrumenterFactory {
|
||||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.graphql-java-20.0";
|
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.graphql-java-20.0";
|
||||||
|
|
||||||
static OpenTelemetryInstrumentationHelper createInstrumentationHelper(
|
static OpenTelemetryInstrumentationHelper createInstrumentationHelper(
|
||||||
OpenTelemetry openTelemetry, boolean sanitizeQuery) {
|
OpenTelemetry openTelemetry, boolean sanitizeQuery, boolean addOperationNameToSpanName) {
|
||||||
return OpenTelemetryInstrumentationHelper.create(
|
return OpenTelemetryInstrumentationHelper.create(
|
||||||
openTelemetry, INSTRUMENTATION_NAME, sanitizeQuery);
|
openTelemetry, INSTRUMENTATION_NAME, sanitizeQuery, addOperationNameToSpanName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instrumenter<DataFetchingEnvironment, Void> createDataFetcherInstrumenter(
|
static Instrumenter<DataFetchingEnvironment, Void> createDataFetcherInstrumenter(
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ class GraphqlTest extends AbstractGraphqlTest {
|
||||||
GraphQLTelemetry telemetry =
|
GraphQLTelemetry telemetry =
|
||||||
GraphQLTelemetry.builder(testing.getOpenTelemetry())
|
GraphQLTelemetry.builder(testing.getOpenTelemetry())
|
||||||
.setDataFetcherInstrumentationEnabled(true)
|
.setDataFetcherInstrumentationEnabled(true)
|
||||||
|
.setAddOperationNameToSpanName(true)
|
||||||
.build();
|
.build();
|
||||||
builder.instrumentation(telemetry.newInstrumentation());
|
builder.instrumentation(telemetry.newInstrumentation());
|
||||||
}
|
}
|
||||||
|
|
@ -56,6 +57,7 @@ class GraphqlTest extends AbstractGraphqlTest {
|
||||||
GraphQLTelemetry telemetry =
|
GraphQLTelemetry telemetry =
|
||||||
GraphQLTelemetry.builder(testing.getOpenTelemetry())
|
GraphQLTelemetry.builder(testing.getOpenTelemetry())
|
||||||
.setDataFetcherInstrumentationEnabled(true)
|
.setDataFetcherInstrumentationEnabled(true)
|
||||||
|
.setAddOperationNameToSpanName(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
GraphQL graphql =
|
GraphQL graphql =
|
||||||
|
|
@ -118,6 +120,7 @@ class GraphqlTest extends AbstractGraphqlTest {
|
||||||
GraphQLTelemetry.builder(testing.getOpenTelemetry())
|
GraphQLTelemetry.builder(testing.getOpenTelemetry())
|
||||||
.setDataFetcherInstrumentationEnabled(true)
|
.setDataFetcherInstrumentationEnabled(true)
|
||||||
.setTrivialDataFetcherInstrumentationEnabled(true)
|
.setTrivialDataFetcherInstrumentationEnabled(true)
|
||||||
|
.setAddOperationNameToSpanName(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
GraphQL graphql =
|
GraphQL graphql =
|
||||||
|
|
@ -194,6 +197,7 @@ class GraphqlTest extends AbstractGraphqlTest {
|
||||||
GraphQLTelemetry.builder(testing.getOpenTelemetry())
|
GraphQLTelemetry.builder(testing.getOpenTelemetry())
|
||||||
.setDataFetcherInstrumentationEnabled(false)
|
.setDataFetcherInstrumentationEnabled(false)
|
||||||
.setTrivialDataFetcherInstrumentationEnabled(true)
|
.setTrivialDataFetcherInstrumentationEnabled(true)
|
||||||
|
.setAddOperationNameToSpanName(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
GraphQL graphql =
|
GraphQL graphql =
|
||||||
|
|
|
||||||
|
|
@ -48,16 +48,22 @@ public final class OpenTelemetryInstrumentationHelper {
|
||||||
|
|
||||||
private final Instrumenter<OpenTelemetryInstrumentationState, ExecutionResult> instrumenter;
|
private final Instrumenter<OpenTelemetryInstrumentationState, ExecutionResult> instrumenter;
|
||||||
private final boolean sanitizeQuery;
|
private final boolean sanitizeQuery;
|
||||||
|
private final boolean addOperationNameToSpanName;
|
||||||
|
|
||||||
private OpenTelemetryInstrumentationHelper(
|
private OpenTelemetryInstrumentationHelper(
|
||||||
Instrumenter<OpenTelemetryInstrumentationState, ExecutionResult> instrumenter,
|
Instrumenter<OpenTelemetryInstrumentationState, ExecutionResult> instrumenter,
|
||||||
boolean sanitizeQuery) {
|
boolean sanitizeQuery,
|
||||||
|
boolean addOperationNameToSpanName) {
|
||||||
this.instrumenter = instrumenter;
|
this.instrumenter = instrumenter;
|
||||||
this.sanitizeQuery = sanitizeQuery;
|
this.sanitizeQuery = sanitizeQuery;
|
||||||
|
this.addOperationNameToSpanName = addOperationNameToSpanName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OpenTelemetryInstrumentationHelper create(
|
public static OpenTelemetryInstrumentationHelper create(
|
||||||
OpenTelemetry openTelemetry, String instrumentationName, boolean sanitizeQuery) {
|
OpenTelemetry openTelemetry,
|
||||||
|
String instrumentationName,
|
||||||
|
boolean sanitizeQuery,
|
||||||
|
boolean addOperationNameToSpanName) {
|
||||||
InstrumenterBuilder<OpenTelemetryInstrumentationState, ExecutionResult> builder =
|
InstrumenterBuilder<OpenTelemetryInstrumentationState, ExecutionResult> builder =
|
||||||
Instrumenter.<OpenTelemetryInstrumentationState, ExecutionResult>builder(
|
Instrumenter.<OpenTelemetryInstrumentationState, ExecutionResult>builder(
|
||||||
openTelemetry, instrumentationName, ignored -> "GraphQL Operation")
|
openTelemetry, instrumentationName, ignored -> "GraphQL Operation")
|
||||||
|
|
@ -76,7 +82,8 @@ public final class OpenTelemetryInstrumentationHelper {
|
||||||
});
|
});
|
||||||
builder.addAttributesExtractor(new GraphqlAttributesExtractor());
|
builder.addAttributesExtractor(new GraphqlAttributesExtractor());
|
||||||
|
|
||||||
return new OpenTelemetryInstrumentationHelper(builder.buildInstrumenter(), sanitizeQuery);
|
return new OpenTelemetryInstrumentationHelper(
|
||||||
|
builder.buildInstrumenter(), sanitizeQuery, addOperationNameToSpanName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstrumentationContext<ExecutionResult> beginExecution(
|
public InstrumentationContext<ExecutionResult> beginExecution(
|
||||||
|
|
@ -118,7 +125,7 @@ public final class OpenTelemetryInstrumentationHelper {
|
||||||
String operationName = operationDefinition.getName();
|
String operationName = operationDefinition.getName();
|
||||||
|
|
||||||
String spanName = operationType;
|
String spanName = operationType;
|
||||||
if (operationName != null && !operationName.isEmpty()) {
|
if (addOperationNameToSpanName && operationName != null && !operationName.isEmpty()) {
|
||||||
spanName += " " + operationName;
|
spanName += " " + operationName;
|
||||||
}
|
}
|
||||||
span.updateName(spanName);
|
span.updateName(spanName);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue