Auto-configure GraphQL metrics

This commit auto-configures the metrics infrastructure for Spring
GraphQL.

See gh-29140
pull/29177/head
Brian Clozel 3 years ago
parent a7839bc9b9
commit 8e29eac887

@ -62,6 +62,8 @@ public class MetricsProperties {
private final Data data = new Data(); private final Data data = new Data();
private final Graphql graphql = new Graphql();
private final System system = new System(); private final System system = new System();
private final Distribution distribution = new Distribution(); private final Distribution distribution = new Distribution();
@ -90,6 +92,10 @@ public class MetricsProperties {
return this.data; return this.data;
} }
public Graphql getGraphql() {
return this.graphql;
}
public System getSystem() { public System getSystem() {
return this.system; return this.system;
} }
@ -268,6 +274,20 @@ public class MetricsProperties {
} }
public static class Graphql {
/**
* Auto-timed queries settings.
*/
@NestedConfigurationProperty
private final AutoTimeProperties autotime = new AutoTimeProperties();
public AutoTimeProperties getAutotime() {
return this.autotime;
}
}
public static class System { public static class System {
private final Diskspace diskspace = new Diskspace(); private final Diskspace diskspace = new Diskspace();

@ -0,0 +1,70 @@
/*
* Copyright 2020-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.autoconfigure.metrics.graphql;
import java.util.stream.Collectors;
import graphql.GraphQL;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.metrics.graphql.DefaultGraphQlTagsProvider;
import org.springframework.boot.actuate.metrics.graphql.GraphQlMetricsInstrumentation;
import org.springframework.boot.actuate.metrics.graphql.GraphQlTagsContributor;
import org.springframework.boot.actuate.metrics.graphql.GraphQlTagsProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.graphql.execution.GraphQlSource;
/**
* {@link EnableAutoConfiguration Auto-configuration} for instrumentation of Spring
* GraphQL endpoints.
*
* @author Brian Clozel
* @since 2.7.0
*/
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter({ MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class })
@ConditionalOnBean(MeterRegistry.class)
@ConditionalOnClass({ GraphQL.class, GraphQlSource.class })
@EnableConfigurationProperties(MetricsProperties.class)
public class GraphQlMetricsAutoConfiguration {
@Bean
@ConditionalOnMissingBean(GraphQlTagsProvider.class)
public DefaultGraphQlTagsProvider graphQlTagsProvider(ObjectProvider<GraphQlTagsContributor> contributors) {
return new DefaultGraphQlTagsProvider(contributors.orderedStream().collect(Collectors.toList()));
}
@Bean
public GraphQlMetricsInstrumentation graphQlMetricsInstrumentation(MeterRegistry meterRegistry,
GraphQlTagsProvider tagsProvider, MetricsProperties properties) {
return new GraphQlMetricsInstrumentation(meterRegistry, tagsProvider, properties.getGraphql().getAutotime());
}
}

@ -68,6 +68,7 @@ org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetri
org.springframework.boot.actuate.autoconfigure.metrics.export.stackdriver.StackdriverMetricsExportAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.export.stackdriver.StackdriverMetricsExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetricsExportAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetricsExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.graphql.GraphQlMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.integration.IntegrationMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.integration.IntegrationMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.jersey.JerseyServerMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.jersey.JerseyServerMetricsAutoConfiguration,\

@ -0,0 +1,98 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.autoconfigure.metrics.graphql;
import graphql.ExecutionResult;
import graphql.GraphQLError;
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
import graphql.schema.DataFetcher;
import io.micrometer.core.instrument.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun;
import org.springframework.boot.actuate.metrics.graphql.DefaultGraphQlTagsProvider;
import org.springframework.boot.actuate.metrics.graphql.GraphQlMetricsInstrumentation;
import org.springframework.boot.actuate.metrics.graphql.GraphQlTagsProvider;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link GraphQlMetricsAutoConfiguration}.
*
* @author Brian Clozel
*/
class GraphQlMetricsAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().with(MetricsRun.simple())
.withConfiguration(AutoConfigurations.of(GraphQlMetricsAutoConfiguration.class));
@Test
void backsOffWhenMeterRegistryIsMissing() {
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(GraphQlMetricsAutoConfiguration.class))
.run((context) -> assertThat(context).doesNotHaveBean(DefaultGraphQlTagsProvider.class)
.doesNotHaveBean(GraphQlMetricsInstrumentation.class));
}
@Test
void definesTagsProviderAndInstrumentationWhenMeterRegistryIsPresent() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(DefaultGraphQlTagsProvider.class)
.hasSingleBean(GraphQlMetricsInstrumentation.class));
}
@Test
void tagsProviderBacksOffIfAlreadyPresent() {
this.contextRunner.withUserConfiguration(TagsProviderConfiguration.class).run((context) -> assertThat(context)
.doesNotHaveBean(DefaultGraphQlTagsProvider.class).hasSingleBean(TestGraphQlTagsProvider.class));
}
@Configuration(proxyBeanMethods = false)
static class TagsProviderConfiguration {
@Bean
TestGraphQlTagsProvider tagsProvider() {
return new TestGraphQlTagsProvider();
}
}
static class TestGraphQlTagsProvider implements GraphQlTagsProvider {
@Override
public Iterable<Tag> getExecutionTags(InstrumentationExecutionParameters parameters, ExecutionResult result,
Throwable exception) {
return null;
}
@Override
public Iterable<Tag> getErrorTags(InstrumentationExecutionParameters parameters, GraphQLError error) {
return null;
}
@Override
public Iterable<Tag> getDataFetchingTags(DataFetcher<?> dataFetcher,
InstrumentationFieldFetchParameters parameters, Throwable exception) {
return null;
}
}
}
Loading…
Cancel
Save