Skip to content

Commit

Permalink
SmallRye-GraphQL metrics rework
Browse files Browse the repository at this point in the history
  • Loading branch information
mskacelik authored and gsmet committed Aug 2, 2023
1 parent 1d678b3 commit 4874c0a
Show file tree
Hide file tree
Showing 12 changed files with 557 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.runtime.metrics.MetricsFactory;
import io.quarkus.smallrye.graphql.runtime.SmallRyeGraphQLConfig;
import io.quarkus.smallrye.graphql.runtime.SmallRyeGraphQLConfigMapping;
import io.quarkus.smallrye.graphql.runtime.SmallRyeGraphQLLocaleResolver;
Expand Down Expand Up @@ -84,10 +85,10 @@
import io.smallrye.graphql.api.federation.Requires;
import io.smallrye.graphql.api.federation.Shareable;
import io.smallrye.graphql.api.federation.Tag;
import io.smallrye.graphql.cdi.config.ConfigKey;
import io.smallrye.graphql.cdi.config.MicroProfileConfig;
import io.smallrye.graphql.cdi.producer.GraphQLProducer;
import io.smallrye.graphql.cdi.tracing.TracingService;
import io.smallrye.graphql.config.ConfigKey;
import io.smallrye.graphql.schema.Annotations;
import io.smallrye.graphql.schema.SchemaBuilder;
import io.smallrye.graphql.schema.model.Argument;
Expand All @@ -102,6 +103,7 @@
import io.smallrye.graphql.schema.model.UnionType;
import io.smallrye.graphql.spi.EventingService;
import io.smallrye.graphql.spi.LookupService;
import io.smallrye.graphql.spi.config.Config;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;

Expand Down Expand Up @@ -592,15 +594,21 @@ void printDataFetcherExceptionInDevMode(SmallRyeGraphQLConfig graphQLConfig,
void activateMetrics(Capabilities capabilities,
Optional<MetricsCapabilityBuildItem> metricsCapability,
SmallRyeGraphQLConfig graphQLConfig,
BuildProducer<SystemPropertyBuildItem> systemProperties) {

boolean activate = shouldActivateService(graphQLConfig.metricsEnabled,
metricsCapability.isPresent(),
"quarkus-smallrye-metrics",
"metrics",
"quarkus.smallrye-graphql.metrics.enabled",
false);
if (activate) {
BuildProducer<SystemPropertyBuildItem> systemProperties, BuildProducer<ServiceProviderBuildItem> serviceProvider) {

if (graphQLConfig.metricsEnabled.orElse(false)
|| Config.get().getConfigValue(ConfigKey.ENABLE_METRICS, boolean.class, false)) {
metricsCapability.ifPresentOrElse(capability -> {
if (capability.metricsSupported(MetricsFactory.MICROMETER)) {
serviceProvider.produce(new ServiceProviderBuildItem("io.smallrye.graphql.spi.MetricsService",
"io.smallrye.graphql.cdi.metrics.MicrometerMetricsService"));
}
if (capability.metricsSupported(MetricsFactory.MP_METRICS)) {
serviceProvider.produce(new ServiceProviderBuildItem("io.smallrye.graphql.spi.MetricsService",
"io.smallrye.graphql.cdi.metrics.MPMetricsService"));
}
}, () -> LOG
.warn("GraphQL metrics are enabled but no supported metrics implementation is available on the classpath"));
systemProperties.produce(new SystemPropertyBuildItem(ConfigKey.ENABLE_METRICS, TRUE));
} else {
systemProperties.produce(new SystemPropertyBuildItem(ConfigKey.ENABLE_METRICS, FALSE));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ public class MetricsTest {
@Test
public void testQuery() {
MetricRegistry metricRegistry = MetricRegistries.get(MetricRegistry.Type.VENDOR);
SimpleTimer metric = metricRegistry.getSimpleTimers()
.get(new MetricID("mp_graphql", new Tag("type", "QUERY"), new Tag("name", "ping"), new Tag("source", "false")));
assertNotNull(metric, "Metrics should be registered eagerly");

String pingRequest = getPayload("{\n" +
" ping {\n" +
Expand All @@ -55,6 +52,10 @@ public void testQuery() {
.and()
.body(CoreMatchers.containsString("{\"data\":{\"ping\":{\"message\":\"pong\"}}}"));

SimpleTimer metric = metricRegistry.getSimpleTimers()
.get(new MetricID("mp_graphql", new Tag("name", "ping"), new Tag("source", "false"), new Tag("type", "QUERY")));
assertNotNull(metric, "Metrics should be registered eagerly");

assertEquals(1L, metric.getCount(), "Metric should be updated after querying");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import io.smallrye.config.ConfigSourceInterceptorContext;
import io.smallrye.config.RelocateConfigSourceInterceptor;
import io.smallrye.graphql.cdi.config.ConfigKey;
import io.smallrye.graphql.config.ConfigKey;

/**
* Maps config from MicroProfile and SmallRye to Quarkus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ protected <O> O invokeAndTransform(
DataFetchingEnvironment dfe,
DataFetcherResult.Builder<Object> resultBuilder,
Object[] transformedArguments) throws Exception {

ManagedContext requestContext = Arc.container().requestContext();

try {
measurementIds.add(metricsEmitter.start(c));
RequestContextHelper.reactivate(requestContext, dfe);
Uni<?> uni = handleUserMethodCall(dfe, transformedArguments);
return (O) uni
Expand Down Expand Up @@ -69,6 +70,7 @@ protected <O> O invokeAndTransform(
te.appendDataFetcherResult(resultBuilder, dfe);
} finally {
eventEmitter.fireAfterDataFetch(c);
metricsEmitter.end(measurementIds.remove());
}
}
emitter.complete(resultBuilder.build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ private <T> T invokeAndTransformBlocking(final io.smallrye.graphql.api.Context c
final Promise<T> result = Promise.promise();

// We need some make sure that we call given the context
measurementIds.add(metricsEmitter.start(c));
@SuppressWarnings("unchecked")
Callable<Object> contextualCallable = threadContext.contextualCallable(() -> {
try {
Expand All @@ -101,14 +102,14 @@ private <T> T invokeAndTransformBlocking(final io.smallrye.graphql.api.Context c
throw ex;
}
});

// Here call blocking with context
BlockingHelper.runBlocking(vc, contextualCallable, result);

return (T) Uni.createFrom().completionStage(result.future().toCompletionStage()).onItemOrFailure()
.invoke((item, error) -> {
if (item != null) {
eventEmitter.fireAfterDataFetch(c);
metricsEmitter.end(measurementIds.remove());
} else {
eventEmitter.fireOnDataFetchError(c, error);
}
Expand Down
5 changes: 4 additions & 1 deletion integration-tests/smallrye-graphql/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-fault-tolerance</artifactId>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-micrometer-registry-prometheus-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.quarkus.it.smallrye.graphql.metricresources;

/**
* Just a test pojo
*/
public class TestPojo {
private String message;

public TestPojo() {
super();
}

public TestPojo(String message) {
super();
this.message = message;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.quarkus.it.smallrye.graphql.metricresources;

/**
* Just a test pojo that contains a random number
*/
public class TestRandom {
private double value;

public TestRandom() {
this(Math.random());
}

public TestRandom(double value) {
super();
this.value = value;
}

public double getValue() {
return value;
}

public void setValue(double value) {
this.value = value;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package io.quarkus.it.smallrye.graphql.metricresources;

import java.util.List;

import org.eclipse.microprofile.graphql.GraphQLApi;
import org.eclipse.microprofile.graphql.Mutation;
import org.eclipse.microprofile.graphql.Query;
import org.eclipse.microprofile.graphql.Source;

import io.micrometer.core.instrument.Metrics;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.infrastructure.Infrastructure;

/**
* Just a test endpoint
*/
@GraphQLApi
public class TestResource {

public static final double SLEEP_TIME = 0.15;

@Query
public TestPojo foo() {
return new TestPojo("bar");
}

@Query
public TestPojo[] superMetricFoo() throws InterruptedException {
Thread.sleep(sleepTimeInMilliseconds());
return new TestPojo[] { foo(), foo(), foo() };
}

@Query
public List<TestPojo> batchFoo(@Source List<TestPojo> testPojos) throws InterruptedException {
Thread.sleep(sleepTimeInMilliseconds());
return List.of(new TestPojo("bar1"), new TestPojo("bar2"), new TestPojo("bar3"));
}

@Query
public Uni<List<TestPojo>> asyncBatchFoo(@Source List<TestPojo> testPojos) {
return Uni.createFrom().item(() -> {
try {
Thread.sleep(sleepTimeInMilliseconds());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return List.of(new TestPojo("abar1"), new TestPojo("abar2"), new TestPojo("abar3"));
});
}

// <placeholder>
@Query
public Uni<TestPojo[]> asyncSuperMetricFoo() throws InterruptedException {
return Uni.createFrom().item(() -> {
try {
Thread.sleep(sleepTimeInMilliseconds());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return new TestPojo[] { new TestPojo("async1"), new TestPojo("async2"), new TestPojo("async3") };
}).runSubscriptionOn(Infrastructure.getDefaultWorkerPool());

}

@Mutation
public void clearMetrics() {
Metrics.globalRegistry.clear();
}

public TestRandom getRandomNumber(@Source TestPojo testPojo) throws InterruptedException {
Thread.sleep(sleepTimeInMilliseconds());
return new TestRandom(123);
}

public Uni<TestRandom> getRandomNumberAsync(@Source TestPojo testPojo) throws InterruptedException {
return Uni.createFrom().item(() -> {
try {
Thread.sleep(sleepTimeInMilliseconds());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return new TestRandom(123);
});
}

private long sleepTimeInMilliseconds() {
return (long) (SLEEP_TIME * 1000);
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
message=Production
quarkus.smallrye-graphql.show-runtime-exception-message=org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException
quarkus.smallrye-graphql.show-runtime-exception-message=org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException
quarkus.smallrye-graphql.metrics.enabled=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.quarkus.it.smallrye.graphql;

import io.quarkus.test.junit.QuarkusIntegrationTest;

@QuarkusIntegrationTest
public class MicrometerMetricsIT extends MicrometerMetricsTest {

}
Loading

0 comments on commit 4874c0a

Please sign in to comment.