Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move away from the deprecated GraphQL Java Instrumentation methods. #1334

Merged
merged 1 commit into from Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -16,6 +16,7 @@ import graphql.analysis.QueryVisitorFieldEnvironment
import graphql.analysis.QueryVisitorStub
import graphql.execution.instrumentation.*
import graphql.execution.instrumentation.SimpleInstrumentationContext.whenCompleted
import graphql.execution.instrumentation.parameters.InstrumentationCreateStateParameters
import graphql.execution.instrumentation.parameters.InstrumentationExecuteOperationParameters
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters
Expand Down Expand Up @@ -46,29 +47,24 @@ class DgsGraphQLMetricsInstrumentation(

companion object {
private val log: Logger = LoggerFactory.getLogger(DgsGraphQLMetricsInstrumentation::class.java)

private object DefaultExecutionStrategyInstrumentationContext : ExecutionStrategyInstrumentationContext {
override fun onDispatched(result: CompletableFuture<ExecutionResult>) {
}

override fun onCompleted(result: ExecutionResult?, t: Throwable?) {
}
}
}

override fun createState(): InstrumentationState {
override fun createState(parameters: InstrumentationCreateStateParameters): InstrumentationState {
return MetricsInstrumentationState(
registrySupplier.get(),
limitedTagMetricResolver
)
}

override fun beginExecution(parameters: InstrumentationExecutionParameters): InstrumentationContext<ExecutionResult> {
val state: MetricsInstrumentationState = parameters.getInstrumentationState()
state.startTimer()
override fun beginExecution(
parameters: InstrumentationExecutionParameters,
state: InstrumentationState
): InstrumentationContext<ExecutionResult> {
val miState: MetricsInstrumentationState = state as MetricsInstrumentationState
miState.startTimer()

state.operationName = Optional.ofNullable(parameters.operation)
state.isIntrospectionQuery = QueryUtils.isIntrospectionQuery(parameters.executionInput)
miState.operationName = Optional.ofNullable(parameters.operation)
miState.isIntrospectionQuery = QueryUtils.isIntrospectionQuery(parameters.executionInput)

return object : SimpleInstrumentationContext<ExecutionResult>() {

Expand All @@ -77,27 +73,28 @@ class DgsGraphQLMetricsInstrumentation(
}

override fun onCompleted(result: ExecutionResult, exc: Throwable?) {
state.stopTimer(
miState.stopTimer(
properties.autotime
.builder(GqlMetric.QUERY.key)
.tags(tagsProvider.getContextualTags())
.tags(tagsProvider.getExecutionTags(parameters, result, exc))
.tags(state.tags())
.tags(miState.tags())
)
}
}
}

override fun instrumentExecutionResult(
executionResult: ExecutionResult,
parameters: InstrumentationExecutionParameters
parameters: InstrumentationExecutionParameters,
state: InstrumentationState
): CompletableFuture<ExecutionResult> {
val state = parameters.getInstrumentationState<MetricsInstrumentationState>()
val miState: MetricsInstrumentationState = state as MetricsInstrumentationState
val tags =
Tags.empty()
.and(tagsProvider.getContextualTags())
.and(tagsProvider.getExecutionTags(parameters, executionResult, null))
.and(state.tags())
.and(miState.tags())

ErrorUtils
.sanitizeErrorPaths(executionResult)
Expand All @@ -117,13 +114,14 @@ class DgsGraphQLMetricsInstrumentation(

override fun instrumentDataFetcher(
dataFetcher: DataFetcher<*>,
parameters: InstrumentationFieldFetchParameters
parameters: InstrumentationFieldFetchParameters,
state: InstrumentationState
): DataFetcher<*> {
val state: MetricsInstrumentationState = parameters.getInstrumentationState()
val miState: MetricsInstrumentationState = state as MetricsInstrumentationState
val gqlField = TagUtils.resolveDataFetcherTagValue(parameters)

if (parameters.isTrivialDataFetcher ||
state.isIntrospectionQuery ||
miState.isIntrospectionQuery ||
TagUtils.shouldIgnoreTag(gqlField) ||
!schemaProvider.isFieldInstrumentationEnabled(gqlField)
) {
Expand All @@ -135,7 +133,7 @@ class DgsGraphQLMetricsInstrumentation(
val baseTags =
Tags.of(GqlTag.FIELD.key, gqlField)
.and(tagsProvider.getContextualTags())
.and(state.tags())
.and(miState.tags())

val sampler = Timer.start(registry)
try {
Expand Down Expand Up @@ -165,28 +163,34 @@ class DgsGraphQLMetricsInstrumentation(
* Port the implementation from MaxQueryComplexityInstrumentation in graphql-java and store the computed complexity
* in the MetricsInstrumentationState for access to add tags to metrics.
*/
override fun beginValidation(parameters: InstrumentationValidationParameters): InstrumentationContext<List<ValidationError>> {
override fun beginValidation(
parameters: InstrumentationValidationParameters,
state: InstrumentationState
): InstrumentationContext<List<ValidationError>> {
return whenCompleted { errors, throwable ->
if (errors != null && errors.isNotEmpty() || throwable != null) {
return@whenCompleted
}
val state: MetricsInstrumentationState = parameters.getInstrumentationState()
val miState: MetricsInstrumentationState = state as MetricsInstrumentationState
if (parameters.document != null) {
state.querySignature = optQuerySignatureRepository.flatMap { it.get(parameters.document, parameters) }
miState.querySignature = optQuerySignatureRepository.flatMap { it.get(parameters.document, parameters) }
}
}
}

override fun beginExecuteOperation(parameters: InstrumentationExecuteOperationParameters): InstrumentationContext<ExecutionResult> {
val state: MetricsInstrumentationState = parameters.getInstrumentationState()
override fun beginExecuteOperation(
parameters: InstrumentationExecuteOperationParameters,
state: InstrumentationState
): InstrumentationContext<ExecutionResult> {
val miState: MetricsInstrumentationState = state as MetricsInstrumentationState
if (parameters.executionContext.getRoot<Any>() == null) {
state.operation = Optional.of(parameters.executionContext.operationDefinition.operation.name.uppercase())
if (!state.operationName.isPresent) {
state.operationName = Optional.ofNullable(parameters.executionContext.operationDefinition?.name)
miState.operation = Optional.of(parameters.executionContext.operationDefinition.operation.name.uppercase())
if (!miState.operationName.isPresent) {
miState.operationName = Optional.ofNullable(parameters.executionContext.operationDefinition?.name)
}
}

state.queryComplexity = ComplexityUtils.resolveComplexity(parameters)
miState.queryComplexity = ComplexityUtils.resolveComplexity(parameters)
return super.beginExecuteOperation(parameters)
}

Expand Down
Expand Up @@ -13,6 +13,12 @@
"description": "Enables DGS' GraphQL metrics, via micrometer.",
"defaultValue": true
},
{
"name": "management.metrics.dgs-graphql.autotime",
"type": "org.springframework.boot.actuate.autoconfigure.metrics.AutoTimeProperties",
"description": "Enables DGS' GraphQL metrics, via micrometer.",
"defaultValue": true
},
{
"name": "management.metrics.dgs-graphql.tag-customizers.outcome.enabled",
"type": "java.lang.Boolean",
Expand Down Expand Up @@ -44,5 +50,27 @@
"defaultValue": true
}
],
"hints": []
"hints": [
{
"name": "management.metrics.dgs-graphql.autotime.percentiles",
"values": [
{
"value": ".50",
"description": "The 50% percentile, or median."
},
{
"value": ".90",
"description": "The 90% percentile."
},
{
"value": ".95",
"description": "The 95% percentile."
},
{
"value": ".99",
"description": "The 99% percentile."
}
]
}
]
}