From b5fb528508f6e111db7f40d6e125ca4f26eef1f6 Mon Sep 17 00:00:00 2001 From: Pedro Igor Date: Tue, 31 Jan 2023 16:17:03 -0300 Subject: [PATCH] Do not enable caching metrics by default and provide a guide Closes #16751 --- docs/guides/src/main/server/caching.adoc | 27 +++++- .../main/server/configuration-metrics.adoc | 79 +++++++++++++++++ .../infinispan/CacheManagerFactory.java | 1 - .../keycloak/it/cli/dist/MetricsDistTest.java | 24 ++++- .../src/test/resources/cache-local.xml | 87 +++++++++++++++++++ 5 files changed, 215 insertions(+), 3 deletions(-) create mode 100644 docs/guides/src/main/server/configuration-metrics.adoc create mode 100644 quarkus/tests/integration/src/test/resources/cache-local.xml diff --git a/docs/guides/src/main/server/caching.adoc b/docs/guides/src/main/server/caching.adoc index bd968b828a..ff665196fe 100644 --- a/docs/guides/src/main/server/caching.adoc +++ b/docs/guides/src/main/server/caching.adoc @@ -1,6 +1,7 @@ <#import "/templates/guide.adoc" as tmpl> <#import "/templates/kc.adoc" as kc> <#import "/templates/options.adoc" as opts> +<#import "/templates/links.adoc" as links> <@tmpl.guide title="Configuring distributed caches" @@ -223,7 +224,31 @@ For more details, see https://infinispan.org/docs/stable/titles/server/server.ht By default, the value set to the `cache-stack` option has precedence over the transport stack you define in the cache configuration file. If you are defining a custom stack, make sure the `cache-stack` option is not used for the custom changes to take effect. -=== Securing cache communication +== Securing cache communication The current Infinispan cache implementation should be secured by various security measures such as RBAC, ACLs, and Transport stack encryption. For more information about securing cache communication, see the https://infinispan.org/docs/dev/titles/security/security.html#[Infinispan security guide]. +== Exposing metrics from caches + +By default, metrics from caches are not automatically exposed when the metrics are enabled. +For more details about how to enable metrics, see the <@links.server id="configuration-metrics"/> guide. + +To enable global metrics for all caches within the `cache-container`, you need to change your cache configuration file (e.g.: `conf/cache-ispn.xml`) to enable `statistics` at the `cache-container` level as follows: + +.enabling metrics for all caches +[source] +---- + + ... + +---- + +Similarly, you can enable metrics individually for each cache by enabling `statistics` as follows: + +.enabling metrics for a specific cache +---- + + ... + +---- + diff --git a/docs/guides/src/main/server/configuration-metrics.adoc b/docs/guides/src/main/server/configuration-metrics.adoc new file mode 100644 index 0000000000..a459176603 --- /dev/null +++ b/docs/guides/src/main/server/configuration-metrics.adoc @@ -0,0 +1,79 @@ +<#import "/templates/guide.adoc" as tmpl> +<#import "/templates/kc.adoc" as kc> +<#import "/templates/options.adoc" as opts> +<#import "/templates/links.adoc" as links> + +<@tmpl.guide +title="Enabling Keycloak Metrics" +summary="Learn how to enable and expose metrics from the server" +includedOptions="metrics-enabled"> + +Keycloak has built in support for metrics. This guide describes how to enable and configure server metrics. + +== Enabling Metrics + +It is possible to enable metrics using the build time option `metrics-enabled`: + +<@kc.start parameters="--metrics-enabled=true"/> + +== Querying Metrics + +Keycloak exposes metrics at the following endpoint: + +* `/metrics` + +The response from the endpoint uses a `text/plain` content type and it is based on the Prometheus text format. The snippet bellow +is an example of a response: + +[source] +---- +# HELP base_gc_total Displays the total number of collections that have occurred. This attribute lists -1 if the collection count is undefined for this collector. +# TYPE base_gc_total counter +base_gc_total{name="G1 Young Generation",} 14.0 +# HELP jvm_memory_usage_after_gc_percent The percentage of long-lived heap pool used after the last GC event, in the range [0..1] +# TYPE jvm_memory_usage_after_gc_percent gauge +jvm_memory_usage_after_gc_percent{area="heap",pool="long-lived",} 0.0 +# HELP jvm_threads_peak_threads The peak live thread count since the Java virtual machine started or peak was reset +# TYPE jvm_threads_peak_threads gauge +jvm_threads_peak_threads 113.0 +# HELP agroal_active_count Number of active connections. These connections are in use and not available to be acquired. +# TYPE agroal_active_count gauge +agroal_active_count{datasource="default",} 0.0 +# HELP base_memory_maxHeap_bytes Displays the maximum amount of memory, in bytes, that can be used for memory management. +# TYPE base_memory_maxHeap_bytes gauge +base_memory_maxHeap_bytes 1.6781410304E10 +# HELP process_start_time_seconds Start time of the process since unix epoch. +# TYPE process_start_time_seconds gauge +process_start_time_seconds 1.675188449054E9 +# HELP system_load_average_1m The sum of the number of runnable entities queued to available processors and the number of runnable entities running on the available processors averaged over a period of time +# TYPE system_load_average_1m gauge +system_load_average_1m 4.005859375 + +... +---- + +== Available Metrics + +The table below summarizes the available metrics groups: + +|=== +|*Metric* | *Description* + +|System +|A set of system-level metrics related to CPU and memory usage. + +|JVM +|A set of metrics from the Java Virtual Machine (JVM) related to GC, and heap. + +|Database +|A set of metrics from the database connection pool, if using a database. + +|HTTP +|A set of global and individual metrics from the HTTP endpoints + +|Cache +|A set of metrics from Infinispan caches. See <@links.server id="caching"/> guide for more details. + +|=== + + diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/legacy/infinispan/CacheManagerFactory.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/legacy/infinispan/CacheManagerFactory.java index 1146d623f7..2dcdb8929b 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/legacy/infinispan/CacheManagerFactory.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/legacy/infinispan/CacheManagerFactory.java @@ -84,7 +84,6 @@ public class CacheManagerFactory { } if (metricsEnabled) { - builder.getNamedConfigurationBuilders().values().stream().forEach(b -> b.statistics().enable()); builder.getGlobalConfigurationBuilder().addModule(MicrometerMeterRegisterConfigurationBuilder.class); builder.getGlobalConfigurationBuilder().module(MicrometerMeterRegisterConfigurationBuilder.class).meterRegistry(Metrics.globalRegistry); } diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/MetricsDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/MetricsDistTest.java index 03775083a0..0128bd683b 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/MetricsDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/MetricsDistTest.java @@ -19,13 +19,18 @@ package org.keycloak.it.cli.dist; import static io.restassured.RestAssured.when; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import java.nio.file.Paths; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; import org.junit.jupiter.api.Test; +import org.keycloak.it.junit5.extension.BeforeStartDistribution; import org.keycloak.it.junit5.extension.DistributionTest; import org.keycloak.it.junit5.extension.LegacyStore; +import org.keycloak.it.junit5.extension.RawDistOnly; import org.keycloak.it.utils.KeycloakDistribution; import io.quarkus.test.junit.main.Launch; @@ -49,7 +54,17 @@ public class MetricsDistTest { when().get("/metrics").then() .statusCode(200) .body(containsString("jvm_gc_")) - .body(containsString("vendor_cache_manager_keycloak_cache_realms_")); + .body(not(containsString("vendor_cache_manager_keycloak_cache_realms_"))); + } + + @Test + @Launch({ "start-dev", "--metrics-enabled=true", "--cache-config-file=cache-local.xml" }) + @BeforeStartDistribution(EnableCachingStatistics.class) + @RawDistOnly(reason = "No support mounting files to containers. Testing raw dist is enough.") + void testExposeCachingMetrics() { + when().get("/metrics").then() + .statusCode(200) + .body(containsString("vendor_cache_manager_keycloak_cache_")); } @Test @@ -101,4 +116,11 @@ public class MetricsDistTest { distribution.stop(); } } + + public static class EnableCachingStatistics implements Consumer { + @Override + public void accept(KeycloakDistribution dist) { + dist.copyOrReplaceFileFromClasspath("/cache-local.xml", Paths.get("conf", "cache-local.xml")); + } + } } diff --git a/quarkus/tests/integration/src/test/resources/cache-local.xml b/quarkus/tests/integration/src/test/resources/cache-local.xml new file mode 100644 index 0000000000..c414d55eb1 --- /dev/null +++ b/quarkus/tests/integration/src/test/resources/cache-local.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +