From 471dc4fbb1c2442717277fbc16dbad1a1092e01e Mon Sep 17 00:00:00 2001 From: Bernardo Gomez Palacio Date: Wed, 30 Nov 2022 09:48:04 -0800 Subject: [PATCH] Move away from the deprecated GraphQL Java Instrumentation methods. (#1334) This commit adopts the new GraphQL Java 19 Instrumentation methods. In addition, we are adding metadata information about the properties that can be used to customize the metrics, and tags associated with those metrics, in DGS. --- .../DgsGraphQLMetricsInstrumentation.kt | 68 ++++++++++--------- ...itional-spring-configuration-metadata.json | 30 +++++++- 2 files changed, 65 insertions(+), 33 deletions(-) diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/DgsGraphQLMetricsInstrumentation.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/DgsGraphQLMetricsInstrumentation.kt index 21fef6d82..a467d0862 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/DgsGraphQLMetricsInstrumentation.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/DgsGraphQLMetricsInstrumentation.kt @@ -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 @@ -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) { - } - - 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 { - val state: MetricsInstrumentationState = parameters.getInstrumentationState() - state.startTimer() + override fun beginExecution( + parameters: InstrumentationExecutionParameters, + state: InstrumentationState + ): InstrumentationContext { + 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() { @@ -77,12 +73,12 @@ 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()) ) } } @@ -90,14 +86,15 @@ class DgsGraphQLMetricsInstrumentation( override fun instrumentExecutionResult( executionResult: ExecutionResult, - parameters: InstrumentationExecutionParameters + parameters: InstrumentationExecutionParameters, + state: InstrumentationState ): CompletableFuture { - val state = parameters.getInstrumentationState() + 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) @@ -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) ) { @@ -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 { @@ -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> { + override fun beginValidation( + parameters: InstrumentationValidationParameters, + state: InstrumentationState + ): InstrumentationContext> { 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 { - val state: MetricsInstrumentationState = parameters.getInstrumentationState() + override fun beginExecuteOperation( + parameters: InstrumentationExecuteOperationParameters, + state: InstrumentationState + ): InstrumentationContext { + val miState: MetricsInstrumentationState = state as MetricsInstrumentationState if (parameters.executionContext.getRoot() == 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) } diff --git a/graphql-dgs-spring-boot-micrometer/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/graphql-dgs-spring-boot-micrometer/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 3a3bc81cd..a5aa800d0 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/graphql-dgs-spring-boot-micrometer/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -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", @@ -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." + } + ] + } + ] } \ No newline at end of file