From 76465c824722c941dcf09c23e52444e5dd924eff Mon Sep 17 00:00:00 2001 From: Jan Martiska Date: Tue, 24 Sep 2019 11:57:09 +0200 Subject: [PATCH] Migrate Metrics extension to vert.x. Fixes #4159 --- .../smallrye-metrics/deployment/pom.xml | 2 +- .../deployment/SmallRyeMetricsProcessor.java | 29 +++++--- extensions/smallrye-metrics/runtime/pom.xml | 6 +- .../runtime/SmallRyeMetricsHandler.java | 47 ++++++++++++ .../runtime/SmallRyeMetricsRecorder.java | 18 +++++ .../runtime/SmallRyeMetricsServlet.java | 73 ------------------- 6 files changed, 84 insertions(+), 91 deletions(-) create mode 100644 extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsHandler.java delete mode 100644 extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsServlet.java diff --git a/extensions/smallrye-metrics/deployment/pom.xml b/extensions/smallrye-metrics/deployment/pom.xml index 2ce770d7f44a9..882e931391bd6 100644 --- a/extensions/smallrye-metrics/deployment/pom.xml +++ b/extensions/smallrye-metrics/deployment/pom.xml @@ -20,7 +20,7 @@ io.quarkus - quarkus-undertow-deployment + quarkus-vertx-http-deployment io.quarkus diff --git a/extensions/smallrye-metrics/deployment/src/main/java/io/quarkus/smallrye/metrics/deployment/SmallRyeMetricsProcessor.java b/extensions/smallrye-metrics/deployment/src/main/java/io/quarkus/smallrye/metrics/deployment/SmallRyeMetricsProcessor.java index 8fc2d4b23d1a4..62015c3eea35a 100644 --- a/extensions/smallrye-metrics/deployment/src/main/java/io/quarkus/smallrye/metrics/deployment/SmallRyeMetricsProcessor.java +++ b/extensions/smallrye-metrics/deployment/src/main/java/io/quarkus/smallrye/metrics/deployment/SmallRyeMetricsProcessor.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; import javax.enterprise.context.Dependent; @@ -31,6 +32,7 @@ import io.quarkus.arc.deployment.AutoInjectAnnotationBuildItem; import io.quarkus.arc.deployment.BeanArchiveIndexBuildItem; import io.quarkus.arc.deployment.BeanContainerBuildItem; +import io.quarkus.arc.deployment.UnremovableBeanBuildItem; import io.quarkus.arc.processor.AnnotationsTransformer; import io.quarkus.arc.processor.BuiltinScope; import io.quarkus.deployment.annotations.BuildProducer; @@ -45,8 +47,8 @@ import io.quarkus.smallrye.metrics.deployment.jandex.JandexBeanInfoAdapter; import io.quarkus.smallrye.metrics.deployment.jandex.JandexMemberInfoAdapter; import io.quarkus.smallrye.metrics.runtime.SmallRyeMetricsRecorder; -import io.quarkus.smallrye.metrics.runtime.SmallRyeMetricsServlet; -import io.quarkus.undertow.deployment.ServletBuildItem; +import io.quarkus.vertx.http.deployment.RouteBuildItem; +import io.quarkus.vertx.http.runtime.HandlerType; import io.smallrye.metrics.MetricProducer; import io.smallrye.metrics.MetricRegistries; import io.smallrye.metrics.MetricsRequestHandler; @@ -57,6 +59,8 @@ import io.smallrye.metrics.interceptors.MetricNameFactory; import io.smallrye.metrics.interceptors.MetricsInterceptor; import io.smallrye.metrics.interceptors.TimedInterceptor; +import io.vertx.ext.web.Route; +import io.vertx.ext.web.Router; public class SmallRyeMetricsProcessor { private static final Logger LOGGER = Logger.getLogger("io.quarkus.smallrye.metrics.deployment.SmallRyeMetricsProcessor"); @@ -65,7 +69,7 @@ public class SmallRyeMetricsProcessor { static final class SmallRyeMetricsConfig { /** - * The path to the metrics Servlet. + * The path to the metrics handler. */ @ConfigItem(defaultValue = "/metrics") String path; @@ -74,16 +78,16 @@ static final class SmallRyeMetricsConfig { SmallRyeMetricsConfig metrics; @BuildStep - ServletBuildItem createServlet() { - ServletBuildItem servletBuildItem = ServletBuildItem.builder("metrics", SmallRyeMetricsServlet.class.getName()) - .addMapping(metrics.path + (metrics.path.endsWith("/") ? "*" : "/*")) - .addInitParam("metrics.path", metrics.path) - .build(); - return servletBuildItem; + @Record(STATIC_INIT) + void createRoute(BuildProducer routes, + SmallRyeMetricsRecorder recorder) { + Function route = recorder.route(metrics.path + (metrics.path.endsWith("/") ? "*" : "/*")); + routes.produce(new RouteBuildItem(route, recorder.handler(metrics.path), HandlerType.BLOCKING)); } @BuildStep - void beans(BuildProducer additionalBeans) { + void beans(BuildProducer additionalBeans, + BuildProducer unremovableBeans) { additionalBeans.produce(new AdditionalBeanBuildItem(MetricProducer.class, MetricNameFactory.class, MetricRegistries.class, @@ -92,8 +96,9 @@ void beans(BuildProducer additionalBeans) { ConcurrentGaugeInterceptor.class, CountedInterceptor.class, TimedInterceptor.class, - MetricsRequestHandler.class, - SmallRyeMetricsServlet.class)); + MetricsRequestHandler.class)); + unremovableBeans.produce(new UnremovableBeanBuildItem( + new UnremovableBeanBuildItem.BeanClassNameExclusion(MetricsRequestHandler.class.getName()))); } @BuildStep diff --git a/extensions/smallrye-metrics/runtime/pom.xml b/extensions/smallrye-metrics/runtime/pom.xml index ff3b4e76914f1..2ef21b90fdc92 100644 --- a/extensions/smallrye-metrics/runtime/pom.xml +++ b/extensions/smallrye-metrics/runtime/pom.xml @@ -25,7 +25,7 @@ io.quarkus - quarkus-undertow + quarkus-vertx-http io.quarkus @@ -35,10 +35,6 @@ io.quarkus quarkus-jsonp - - org.jboss.spec.javax.servlet - jboss-servlet-api_4.0_spec - diff --git a/extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsHandler.java b/extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsHandler.java new file mode 100644 index 0000000000000..7a361358b6d0d --- /dev/null +++ b/extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsHandler.java @@ -0,0 +1,47 @@ +package io.quarkus.smallrye.metrics.runtime; + +import java.io.IOException; +import java.util.stream.Stream; + +import javax.enterprise.inject.spi.CDI; + +import org.jboss.logging.Logger; + +import io.smallrye.metrics.MetricsRequestHandler; +import io.vertx.core.Handler; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.core.http.HttpServerResponse; +import io.vertx.ext.web.RoutingContext; + +public class SmallRyeMetricsHandler implements Handler { + + private String metricsPath; + + private static final Logger LOGGER = Logger.getLogger(SmallRyeMetricsHandler.class.getName()); + + public void setMetricsPath(String metricsPath) { + this.metricsPath = metricsPath; + } + + @Override + public void handle(RoutingContext routingContext) { + MetricsRequestHandler internalHandler = CDI.current().select(MetricsRequestHandler.class).get(); + HttpServerResponse response = routingContext.response(); + HttpServerRequest request = routingContext.request(); + Stream acceptHeaders = request.headers().getAll("Accept").stream(); + + try { + internalHandler.handleRequest(request.path(), metricsPath, request.rawMethod(), acceptHeaders, + (status, message, headers) -> { + response.setStatusCode(status); + headers.forEach(response::putHeader); + response.end(Buffer.buffer(message)); + }); + } catch (IOException e) { + response.setStatusCode(503); + response.end(); + LOGGER.error(e); + } + } +} diff --git a/extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsRecorder.java b/extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsRecorder.java index fb387f72011fa..b2bf8d7d5262f 100644 --- a/extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsRecorder.java +++ b/extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsRecorder.java @@ -10,6 +10,7 @@ import java.lang.management.ThreadMXBean; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; import org.eclipse.microprofile.metrics.Metadata; import org.eclipse.microprofile.metrics.MetricRegistry; @@ -27,6 +28,8 @@ import io.smallrye.metrics.elementdesc.MemberInfo; import io.smallrye.metrics.interceptors.MetricResolver; import io.smallrye.metrics.setup.MetricsMetadata; +import io.vertx.ext.web.Route; +import io.vertx.ext.web.Router; @Recorder public class SmallRyeMetricsRecorder { @@ -63,6 +66,21 @@ public class SmallRyeMetricsRecorder { private static final String MEMORY_USED_HEAP = "memory.usedHeap"; private static final String MEMORY_USED_NON_HEAP = "memory.usedNonHeap"; + public Function route(String name) { + return new Function() { + @Override + public Route apply(Router router) { + return router.route(name); + } + }; + } + + public SmallRyeMetricsHandler handler(String metricsPath) { + SmallRyeMetricsHandler handler = new SmallRyeMetricsHandler(); + handler.setMetricsPath(metricsPath); + return handler; + } + public void registerVendorMetrics(ShutdownContext shutdown) { MetricRegistry registry = MetricRegistries.get(MetricRegistry.Type.VENDOR); List names = new ArrayList<>(); diff --git a/extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsServlet.java b/extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsServlet.java deleted file mode 100644 index dc103a850eedd..0000000000000 --- a/extensions/smallrye-metrics/runtime/src/main/java/io/quarkus/smallrye/metrics/runtime/SmallRyeMetricsServlet.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.quarkus.smallrye.metrics.runtime; - -import java.io.IOException; -import java.util.Collections; -import java.util.stream.Stream; - -import javax.inject.Inject; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.microprofile.config.inject.ConfigProperty; - -import io.smallrye.metrics.MetricsRequestHandler; - -@WebServlet -public class SmallRyeMetricsServlet extends HttpServlet { - - @Inject - MetricsRequestHandler metricsHandler; - - @ConfigProperty(name = "quarkus.servlet.context-path", defaultValue = "/") - String appContextPath; - - // full path where the metrics endpoint resides, by default it's /metrics, but can be /appContextPath/anything - private String contextPath; - - @Override - public void init() { - String metricsPath = getInitParameter("metrics.path"); - // add leading / if there isn't one - String metricPathSanitized = metricsPath.startsWith("/") ? metricsPath : "/" + metricsPath; - // strip off trailing / if there is - String appContextPathSanitized = appContextPath.endsWith("/") ? appContextPath.substring(0, appContextPath.length() - 1) - : appContextPath; - contextPath = appContextPathSanitized + metricPathSanitized; - } - - @Override - protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws IOException { - doGet(req, resp); - } - - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { - String requestPath = request.getRequestURI(); - String method = request.getMethod(); - Stream acceptHeaders = Collections.list(request.getHeaders("Accept")).stream(); - - metricsHandler.handleRequest(requestPath, contextPath, method, acceptHeaders, (status, message, headers) -> { - headers.forEach(response::addHeader); - response.setStatus(status); - - // FIXME: this is a workaround for issue #3673, normally just response.getWriter().write(message) should do - final int stepSize = 5000; - if (message.length() < stepSize) { - response.getWriter().write(message); - } else { - // split a string longer than 8192 characters into smaller chunks - // and feed them one by one to the writer - // and call flush() in between - for (int i = 0; i < (message.length() / stepSize) + 1; i++) { - int start = stepSize * i; - final int chars = Math.min(stepSize, message.length() - (stepSize * i)); - response.getWriter() - .write(message.substring(start, start + chars)); - response.getWriter().flush(); - } - } - }); - } -}