Skip to content

Commit 38f1bc9

Browse files
committed
Reinstate Spring for GraphQL auto-configuration
This commit adds the Spring for GraphQL auto-configuration back into Spring Boot 3.0, now that a 1.1.0 release is scheduled with the required baseline. This release also needs GraphQL Java 19.0 as a baseline. Closes gh-31809
1 parent ab469e8 commit 38f1bc9

File tree

125 files changed

+7728
-4
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+7728
-4
lines changed

buildSrc/src/main/java/org/springframework/boot/build/context/properties/DocumentConfigurationProperties.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ private void integrationPrefixes(Config prefix) {
174174
}
175175

176176
private void webPrefixes(Config prefix) {
177+
prefix.accept("spring.graphql");
177178
prefix.accept("spring.hateoas");
178179
prefix.accept("spring.http");
179180
prefix.accept("spring.servlet");

spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ dependencies {
135135
optional("org.springframework.data:spring-data-elasticsearch") {
136136
exclude group: "commons-logging", module: "commons-logging"
137137
}
138+
optional("org.springframework.graphql:spring-graphql")
138139
optional("org.springframework.integration:spring-integration-core")
139140
optional("org.springframework.kafka:spring-kafka")
140141
optional("org.springframework.security:spring-security-config")

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsProperties.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ public class MetricsProperties {
6262

6363
private final Data data = new Data();
6464

65+
private final Graphql graphql = new Graphql();
66+
6567
private final System system = new System();
6668

6769
private final Distribution distribution = new Distribution();
@@ -90,6 +92,10 @@ public Data getData() {
9092
return this.data;
9193
}
9294

95+
public Graphql getGraphql() {
96+
return this.graphql;
97+
}
98+
9399
public System getSystem() {
94100
return this.system;
95101
}
@@ -268,6 +274,20 @@ public AutoTimeProperties getAutotime() {
268274

269275
}
270276

277+
public static class Graphql {
278+
279+
/**
280+
* Auto-timed queries settings.
281+
*/
282+
@NestedConfigurationProperty
283+
private final AutoTimeProperties autotime = new AutoTimeProperties();
284+
285+
public AutoTimeProperties getAutotime() {
286+
return this.autotime;
287+
}
288+
289+
}
290+
271291
public static class System {
272292

273293
private final Diskspace diskspace = new Diskspace();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2012-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.metrics.graphql;
18+
19+
import java.util.stream.Collectors;
20+
21+
import graphql.GraphQL;
22+
import io.micrometer.core.instrument.MeterRegistry;
23+
24+
import org.springframework.beans.factory.ObjectProvider;
25+
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
26+
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
27+
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
28+
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
29+
import org.springframework.boot.actuate.metrics.graphql.DefaultGraphQlTagsProvider;
30+
import org.springframework.boot.actuate.metrics.graphql.GraphQlMetricsInstrumentation;
31+
import org.springframework.boot.actuate.metrics.graphql.GraphQlTagsContributor;
32+
import org.springframework.boot.actuate.metrics.graphql.GraphQlTagsProvider;
33+
import org.springframework.boot.autoconfigure.AutoConfiguration;
34+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
35+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
36+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
37+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
38+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
39+
import org.springframework.context.annotation.Bean;
40+
import org.springframework.graphql.execution.GraphQlSource;
41+
42+
/**
43+
* {@link EnableAutoConfiguration Auto-configuration} for instrumentation of Spring
44+
* GraphQL endpoints.
45+
*
46+
* @author Brian Clozel
47+
* @since 2.7.0
48+
*/
49+
@AutoConfiguration(after = { MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class,
50+
SimpleMetricsExportAutoConfiguration.class })
51+
@ConditionalOnBean(MeterRegistry.class)
52+
@ConditionalOnClass({ GraphQL.class, GraphQlSource.class })
53+
@EnableConfigurationProperties(MetricsProperties.class)
54+
public class GraphQlMetricsAutoConfiguration {
55+
56+
@Bean
57+
@ConditionalOnMissingBean(GraphQlTagsProvider.class)
58+
public DefaultGraphQlTagsProvider graphQlTagsProvider(ObjectProvider<GraphQlTagsContributor> contributors) {
59+
return new DefaultGraphQlTagsProvider(contributors.orderedStream().collect(Collectors.toList()));
60+
}
61+
62+
@Bean
63+
public GraphQlMetricsInstrumentation graphQlMetricsInstrumentation(MeterRegistry meterRegistry,
64+
GraphQlTagsProvider tagsProvider, MetricsProperties properties) {
65+
return new GraphQlMetricsInstrumentation(meterRegistry, tagsProvider, properties.getGraphql().getAutotime());
66+
}
67+
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2012-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Auto-configuration for Spring GraphQL metrics.
19+
*/
20+
package org.springframework.boot.actuate.autoconfigure.metrics.graphql;

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetri
6767
org.springframework.boot.actuate.autoconfigure.metrics.export.stackdriver.StackdriverMetricsExportAutoConfiguration
6868
org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetricsExportAutoConfiguration
6969
org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration
70+
org.springframework.boot.actuate.autoconfigure.metrics.graphql.GraphQlMetricsAutoConfiguration
7071
org.springframework.boot.actuate.autoconfigure.metrics.integration.IntegrationMetricsAutoConfiguration
7172
org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration
7273
org.springframework.boot.actuate.autoconfigure.metrics.mongo.MongoMetricsAutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2012-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.metrics.graphql;
18+
19+
import graphql.ExecutionResult;
20+
import graphql.GraphQLError;
21+
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
22+
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
23+
import graphql.schema.DataFetcher;
24+
import io.micrometer.core.instrument.Tag;
25+
import org.junit.jupiter.api.Test;
26+
27+
import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun;
28+
import org.springframework.boot.actuate.metrics.graphql.DefaultGraphQlTagsProvider;
29+
import org.springframework.boot.actuate.metrics.graphql.GraphQlMetricsInstrumentation;
30+
import org.springframework.boot.actuate.metrics.graphql.GraphQlTagsProvider;
31+
import org.springframework.boot.autoconfigure.AutoConfigurations;
32+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
33+
import org.springframework.context.annotation.Bean;
34+
import org.springframework.context.annotation.Configuration;
35+
36+
import static org.assertj.core.api.Assertions.assertThat;
37+
38+
/**
39+
* Tests for {@link GraphQlMetricsAutoConfiguration}.
40+
*
41+
* @author Brian Clozel
42+
*/
43+
class GraphQlMetricsAutoConfigurationTests {
44+
45+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().with(MetricsRun.simple())
46+
.withConfiguration(AutoConfigurations.of(GraphQlMetricsAutoConfiguration.class));
47+
48+
@Test
49+
void backsOffWhenMeterRegistryIsMissing() {
50+
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(GraphQlMetricsAutoConfiguration.class))
51+
.run((context) -> assertThat(context).doesNotHaveBean(DefaultGraphQlTagsProvider.class)
52+
.doesNotHaveBean(GraphQlMetricsInstrumentation.class));
53+
}
54+
55+
@Test
56+
void definesTagsProviderAndInstrumentationWhenMeterRegistryIsPresent() {
57+
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(DefaultGraphQlTagsProvider.class)
58+
.hasSingleBean(GraphQlMetricsInstrumentation.class));
59+
}
60+
61+
@Test
62+
void tagsProviderBacksOffIfAlreadyPresent() {
63+
this.contextRunner.withUserConfiguration(TagsProviderConfiguration.class).run((context) -> assertThat(context)
64+
.doesNotHaveBean(DefaultGraphQlTagsProvider.class).hasSingleBean(TestGraphQlTagsProvider.class));
65+
}
66+
67+
@Configuration(proxyBeanMethods = false)
68+
static class TagsProviderConfiguration {
69+
70+
@Bean
71+
TestGraphQlTagsProvider tagsProvider() {
72+
return new TestGraphQlTagsProvider();
73+
}
74+
75+
}
76+
77+
static class TestGraphQlTagsProvider implements GraphQlTagsProvider {
78+
79+
@Override
80+
public Iterable<Tag> getExecutionTags(InstrumentationExecutionParameters parameters, ExecutionResult result,
81+
Throwable exception) {
82+
return null;
83+
}
84+
85+
@Override
86+
public Iterable<Tag> getErrorTags(InstrumentationExecutionParameters parameters, GraphQLError error) {
87+
return null;
88+
}
89+
90+
@Override
91+
public Iterable<Tag> getDataFetchingTags(DataFetcher<?> dataFetcher,
92+
InstrumentationFieldFetchParameters parameters, Throwable exception) {
93+
return null;
94+
}
95+
96+
}
97+
98+
}

spring-boot-project/spring-boot-actuator/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ dependencies {
6161
optional("org.springframework:spring-webflux")
6262
optional("org.springframework:spring-web")
6363
optional("org.springframework:spring-webmvc")
64+
optional("org.springframework.graphql:spring-graphql")
6465
optional("org.springframework.amqp:spring-rabbit")
6566
optional("org.springframework.data:spring-data-cassandra") {
6667
exclude group: "org.slf4j", module: "jcl-over-slf4j"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2020-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.metrics.graphql;
18+
19+
import java.util.Collections;
20+
import java.util.List;
21+
22+
import graphql.ExecutionResult;
23+
import graphql.GraphQLError;
24+
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
25+
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
26+
import graphql.schema.DataFetcher;
27+
import io.micrometer.core.instrument.Tag;
28+
import io.micrometer.core.instrument.Tags;
29+
30+
/**
31+
* Default implementation for {@link GraphQlTagsProvider}.
32+
*
33+
* @author Brian Clozel
34+
* @since 2.7.0
35+
*/
36+
public class DefaultGraphQlTagsProvider implements GraphQlTagsProvider {
37+
38+
private final List<GraphQlTagsContributor> contributors;
39+
40+
public DefaultGraphQlTagsProvider(List<GraphQlTagsContributor> contributors) {
41+
this.contributors = contributors;
42+
}
43+
44+
public DefaultGraphQlTagsProvider() {
45+
this(Collections.emptyList());
46+
}
47+
48+
@Override
49+
public Iterable<Tag> getExecutionTags(InstrumentationExecutionParameters parameters, ExecutionResult result,
50+
Throwable exception) {
51+
Tags tags = Tags.of(GraphQlTags.executionOutcome(result, exception));
52+
for (GraphQlTagsContributor contributor : this.contributors) {
53+
tags = tags.and(contributor.getExecutionTags(parameters, result, exception));
54+
}
55+
return tags;
56+
}
57+
58+
@Override
59+
public Iterable<Tag> getErrorTags(InstrumentationExecutionParameters parameters, GraphQLError error) {
60+
Tags tags = Tags.of(GraphQlTags.errorType(error), GraphQlTags.errorPath(error));
61+
for (GraphQlTagsContributor contributor : this.contributors) {
62+
tags = tags.and(contributor.getErrorTags(parameters, error));
63+
}
64+
return tags;
65+
}
66+
67+
@Override
68+
public Iterable<Tag> getDataFetchingTags(DataFetcher<?> dataFetcher, InstrumentationFieldFetchParameters parameters,
69+
Throwable exception) {
70+
Tags tags = Tags.of(GraphQlTags.dataFetchingOutcome(exception), GraphQlTags.dataFetchingPath(parameters));
71+
for (GraphQlTagsContributor contributor : this.contributors) {
72+
tags = tags.and(contributor.getDataFetchingTags(dataFetcher, parameters, exception));
73+
}
74+
return tags;
75+
}
76+
77+
}

0 commit comments

Comments
 (0)