8877 Make KeycloakMetricsHandler aware of context-path

Adapt KeycloakMetricsHandler to consider custom relative paths via `kc.http.relative-path`
or --http-relative-path=/auth. Previously only the fixed path /metrics was allowed which did not work
with custom context-paths.

- Adapted KeycloakProcessor to Pedros proposal from 0b28d71dd0
- Removed unnecessary KeycloakMetricsHandler
- Added MetricsDistTest

Fixes #8877
This commit is contained in:
Thomas Darimont 2021-11-22 21:46:28 +01:00 committed by Pedro Igor
parent 48835576da
commit 50060775f6
4 changed files with 16 additions and 35 deletions

View file

@ -67,6 +67,7 @@ import io.quarkus.hibernate.orm.deployment.PersistenceXmlDescriptorBuildItem;
import io.quarkus.resteasy.server.common.deployment.ResteasyDeploymentCustomizerBuildItem; import io.quarkus.resteasy.server.common.deployment.ResteasyDeploymentCustomizerBuildItem;
import io.quarkus.runtime.LaunchMode; import io.quarkus.runtime.LaunchMode;
import io.quarkus.smallrye.health.runtime.SmallRyeHealthHandler; import io.quarkus.smallrye.health.runtime.SmallRyeHealthHandler;
import io.quarkus.vertx.http.deployment.NonApplicationRootPathBuildItem;
import io.quarkus.vertx.http.deployment.RouteBuildItem; import io.quarkus.vertx.http.deployment.RouteBuildItem;
import io.vertx.core.Handler; import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.RoutingContext;
@ -117,7 +118,6 @@ import org.keycloak.representations.provider.ScriptProviderDescriptor;
import org.keycloak.representations.provider.ScriptProviderMetadata; import org.keycloak.representations.provider.ScriptProviderMetadata;
import org.keycloak.quarkus.runtime.integration.web.NotFoundHandler; import org.keycloak.quarkus.runtime.integration.web.NotFoundHandler;
import org.keycloak.services.ServicesLogger; import org.keycloak.services.ServicesLogger;
import org.keycloak.quarkus.runtime.services.health.KeycloakMetricsHandler;
import org.keycloak.theme.FolderThemeProviderFactory; import org.keycloak.theme.FolderThemeProviderFactory;
import org.keycloak.transaction.JBossJtaTransactionManagerLookup; import org.keycloak.transaction.JBossJtaTransactionManagerLookup;
import org.keycloak.quarkus.runtime.Environment; import org.keycloak.quarkus.runtime.Environment;
@ -132,6 +132,7 @@ class KeycloakProcessor {
private static final String JAR_FILE_SEPARATOR = "!/"; private static final String JAR_FILE_SEPARATOR = "!/";
private static final String DEFAULT_HEALTH_ENDPOINT = "/health"; private static final String DEFAULT_HEALTH_ENDPOINT = "/health";
private static final String DEFAULT_METRICS_ENDPOINT = "/metrics";
private static final Map<String, Function<ScriptProviderMetadata, ProviderFactory>> DEPLOYEABLE_SCRIPT_PROVIDERS = new HashMap<>(); private static final Map<String, Function<ScriptProviderMetadata, ProviderFactory>> DEPLOYEABLE_SCRIPT_PROVIDERS = new HashMap<>();
private static final String KEYCLOAK_SCRIPTS_JSON_PATH = "META-INF/keycloak-scripts.json"; private static final String KEYCLOAK_SCRIPTS_JSON_PATH = "META-INF/keycloak-scripts.json";
@ -344,14 +345,16 @@ class KeycloakProcessor {
* *
* @param routes * @param routes
*/ */
@Record(ExecutionTime.STATIC_INIT)
@BuildStep @BuildStep
void initializeMetrics(BuildProducer<RouteBuildItem> routes) { void initializeMetrics(KeycloakRecorder recorder, BuildProducer<RouteBuildItem> routes, NonApplicationRootPathBuildItem nonAppRootPath) {
Handler<RoutingContext> healthHandler; Handler<RoutingContext> healthHandler;
Handler<RoutingContext> metricsHandler; Handler<RoutingContext> metricsHandler;
if (isMetricsEnabled()) { if (isMetricsEnabled()) {
healthHandler = new SmallRyeHealthHandler(); healthHandler = new SmallRyeHealthHandler();
metricsHandler = new KeycloakMetricsHandler(); String rootPath = nonAppRootPath.getNormalizedHttpRootPath();
metricsHandler = recorder.createMetricsHandler(rootPath.concat(DEFAULT_METRICS_ENDPOINT).replace("//", "/"));
} else { } else {
healthHandler = new NotFoundHandler(); healthHandler = new NotFoundHandler();
metricsHandler = new NotFoundHandler(); metricsHandler = new NotFoundHandler();
@ -360,7 +363,7 @@ class KeycloakProcessor {
routes.produce(RouteBuildItem.builder().route(DEFAULT_HEALTH_ENDPOINT).handler(healthHandler).build()); routes.produce(RouteBuildItem.builder().route(DEFAULT_HEALTH_ENDPOINT).handler(healthHandler).build());
routes.produce(RouteBuildItem.builder().route(DEFAULT_HEALTH_ENDPOINT.concat("/live")).handler(healthHandler).build()); routes.produce(RouteBuildItem.builder().route(DEFAULT_HEALTH_ENDPOINT.concat("/live")).handler(healthHandler).build());
routes.produce(RouteBuildItem.builder().route(DEFAULT_HEALTH_ENDPOINT.concat("/ready")).handler(healthHandler).build()); routes.produce(RouteBuildItem.builder().route(DEFAULT_HEALTH_ENDPOINT.concat("/ready")).handler(healthHandler).build());
routes.produce(RouteBuildItem.builder().route(KeycloakMetricsHandler.DEFAULT_METRICS_ENDPOINT).handler(metricsHandler).build()); routes.produce(RouteBuildItem.builder().route(DEFAULT_METRICS_ENDPOINT).handler(metricsHandler).build());
} }
@BuildStep @BuildStep

View file

@ -27,6 +27,9 @@ import org.infinispan.configuration.parsing.ConfigurationBuilderHolder;
import org.infinispan.configuration.parsing.ParserRegistry; import org.infinispan.configuration.parsing.ParserRegistry;
import org.infinispan.jboss.marshalling.core.JBossUserMarshaller; import org.infinispan.jboss.marshalling.core.JBossUserMarshaller;
import org.infinispan.manager.DefaultCacheManager; import org.infinispan.manager.DefaultCacheManager;
import io.quarkus.smallrye.metrics.runtime.SmallRyeMetricsHandler;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import org.keycloak.common.Profile; import org.keycloak.common.Profile;
import org.keycloak.quarkus.runtime.configuration.Configuration; import org.keycloak.quarkus.runtime.configuration.Configuration;
import org.keycloak.quarkus.runtime.integration.QuarkusKeycloakSessionFactory; import org.keycloak.quarkus.runtime.integration.QuarkusKeycloakSessionFactory;
@ -152,4 +155,10 @@ public class KeycloakRecorder {
} }
}); });
} }
public Handler<RoutingContext> createMetricsHandler(String path) {
SmallRyeMetricsHandler metricsHandler = new SmallRyeMetricsHandler();
metricsHandler.setMetricsPath(path);
return metricsHandler;
}
} }

View file

@ -1,29 +0,0 @@
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* 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
*
* http://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.keycloak.quarkus.runtime.services.health;
import io.quarkus.smallrye.metrics.runtime.SmallRyeMetricsHandler;
public class KeycloakMetricsHandler extends SmallRyeMetricsHandler {
public static final String DEFAULT_METRICS_ENDPOINT = "/metrics";
public KeycloakMetricsHandler() {
setMetricsPath(DEFAULT_METRICS_ENDPOINT);
}
}

View file

@ -20,7 +20,6 @@ package org.keycloak.it.cli.dist;
import static io.restassured.RestAssured.when; import static io.restassured.RestAssured.when;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.keycloak.it.junit5.extension.DistributionTest; import org.keycloak.it.junit5.extension.DistributionTest;
@ -37,7 +36,6 @@ public class MetricsDistTest {
.body(containsString("base_gc_total")); .body(containsString("base_gc_total"));
} }
@Disabled("https://github.com/keycloak/keycloak/pull/8878")
@Test @Test
@Launch({ "start-dev", "--http-relative-path=/auth", "--metrics-enabled=true" }) @Launch({ "start-dev", "--http-relative-path=/auth", "--metrics-enabled=true" })
void testMetricsEndpointUsingRelativePath() { void testMetricsEndpointUsingRelativePath() {