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