From 5fbeb49a612fdd81e31a81c17d0f35fc952ad317 Mon Sep 17 00:00:00 2001 From: "kokuwa.io Bot" Date: Mon, 24 Apr 2023 12:34:39 +0000 Subject: [PATCH 01/93] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a8bbb77..28140b1 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.kokuwa.keycloak keycloak-event-metrics - 0.2.1 + 0.2.2-SNAPSHOT Keycloak Metrics Provides metrics for Keycloak user/admin events @@ -36,7 +36,7 @@ https://github.com/kokuwaio/keycloak-event-metrics scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git - 0.2.1 + HEAD github From a3920767226ea647564faf07b54d0722e14228a4 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Mon, 24 Apr 2023 14:55:22 +0200 Subject: [PATCH 02/93] Change default value for replaceIds (#28) --- README.md | 2 +- pom.xml | 2 +- ...ventListener.java => MetricsEventListener.java} | 14 +++++++------- ...ctory.java => MetricsEventListenerFactory.java} | 14 +++++++------- ...rg.keycloak.events.EventListenerProviderFactory | 2 +- ...enerTest.java => MetricsEventListenerTest.java} | 8 ++++---- .../keycloak/metrics/junit/KeycloakExtension.java | 1 - 7 files changed, 21 insertions(+), 22 deletions(-) rename src/main/java/io/kokuwa/keycloak/metrics/{MicrometerEventListener.java => MetricsEventListener.java} (77%) rename src/main/java/io/kokuwa/keycloak/metrics/{MicrometerEventListenerFactory.java => MetricsEventListenerFactory.java} (61%) rename src/test/java/io/kokuwa/keycloak/metrics/{MicrometerEventListenerTest.java => MetricsEventListenerTest.java} (98%) diff --git a/README.md b/README.md index 6bddad3..9b1f341 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ keycloak_event_admin_total{error="",operation="CREATE",realm="9039a0b5-e8c9-437a ### `KC_METRICS_EVENT_REPLACE_IDS` -If set to `true` than replace model ids with names: +Per set to `true` (the default value) than replace model ids with names: * [RealmModel#getId()](https://github.com/keycloak/keycloak/blob/main/server-spi/src/main/java/org/keycloak/models/RealmModel.java#L82) with [RealmModel#getName()](https://github.com/keycloak/keycloak/blob/main/server-spi/src/main/java/org/keycloak/models/RealmModel.java#L84) diff --git a/pom.xml b/pom.xml index 28140b1..999fb8a 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.kokuwa.keycloak keycloak-event-metrics - 0.2.2-SNAPSHOT + 1.0.0-SNAPSHOT Keycloak Metrics Provides metrics for Keycloak user/admin events diff --git a/src/main/java/io/kokuwa/keycloak/metrics/MicrometerEventListener.java b/src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListener.java similarity index 77% rename from src/main/java/io/kokuwa/keycloak/metrics/MicrometerEventListener.java rename to src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListener.java index 7a83b3f..ea811fb 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/MicrometerEventListener.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListener.java @@ -17,23 +17,23 @@ import io.micrometer.core.instrument.MeterRegistry; * * @author Stephan Schnabel */ -public class MicrometerEventListener implements EventListenerProvider, AutoCloseable { +public class MetricsEventListener implements EventListenerProvider, AutoCloseable { - private static final Logger log = Logger.getLogger(MicrometerEventListener.class); + private static final Logger log = Logger.getLogger(MetricsEventListener.class); private final MeterRegistry registry; + private final boolean replaceIds; private final KeycloakSession session; - private final boolean replace; - MicrometerEventListener(MeterRegistry registry, KeycloakSession session, boolean replaceId) { + MetricsEventListener(MeterRegistry registry, boolean replaceIds, KeycloakSession session) { this.registry = registry; + this.replaceIds = replaceIds; this.session = session; - this.replace = replaceId; } @Override public void onEvent(Event event) { registry.counter("keycloak_event_user", - "realm", toBlank(replace ? getRealmName(event.getRealmId()) : event.getRealmId()), + "realm", toBlank(replaceIds ? getRealmName(event.getRealmId()) : event.getRealmId()), "type", toBlank(event.getType()), "client", toBlank(event.getClientId()), "error", toBlank(event.getError())) @@ -43,7 +43,7 @@ public class MicrometerEventListener implements EventListenerProvider, AutoClose @Override public void onEvent(AdminEvent event, boolean includeRepresentation) { registry.counter("keycloak_event_admin", - "realm", toBlank(replace ? getRealmName(event.getRealmId()) : event.getRealmId()), + "realm", toBlank(replaceIds ? getRealmName(event.getRealmId()) : event.getRealmId()), "resource", toBlank(event.getResourceType()), "operation", toBlank(event.getOperationType()), "error", toBlank(event.getError())) diff --git a/src/main/java/io/kokuwa/keycloak/metrics/MicrometerEventListenerFactory.java b/src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListenerFactory.java similarity index 61% rename from src/main/java/io/kokuwa/keycloak/metrics/MicrometerEventListenerFactory.java rename to src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListenerFactory.java index 8553df6..3804d21 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/MicrometerEventListenerFactory.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListenerFactory.java @@ -12,15 +12,15 @@ import org.keycloak.models.KeycloakSessionFactory; import io.micrometer.core.instrument.MeterRegistry; /** - * Factory for {@link MicrometerEventListener}, uses {@link MeterRegistry} from CDI. + * Factory for {@link MetricsEventListener}, uses {@link MeterRegistry} from CDI. * * @author Stephan Schnabel */ -public class MicrometerEventListenerFactory implements EventListenerProviderFactory { +public class MetricsEventListenerFactory implements EventListenerProviderFactory { - private static final Logger log = Logger.getLogger(MicrometerEventListener.class); + private static final Logger log = Logger.getLogger(MetricsEventListenerFactory.class); private MeterRegistry registry; - private boolean replace; + private boolean replaceIds; @Override public String getId() { @@ -29,8 +29,8 @@ public class MicrometerEventListenerFactory implements EventListenerProviderFact @Override public void init(Scope config) { - replace = "true".equals(System.getenv("KC_METRICS_EVENT_REPLACE_IDS")); - log.info(replace ? "Configured with model names." : "Configured with model ids."); + replaceIds = "true".equals(System.getenv().getOrDefault("KC_METRICS_EVENT_REPLACE_IDS", "true")); + log.info(replaceIds ? "Configured with model names." : "Configured with model ids."); } @Override @@ -40,7 +40,7 @@ public class MicrometerEventListenerFactory implements EventListenerProviderFact @Override public EventListenerProvider create(KeycloakSession session) { - return new MicrometerEventListener(registry, session, replace); + return new MetricsEventListener(registry, replaceIds, session); } @Override diff --git a/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory b/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory index a54f10d..6fca1e1 100644 --- a/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory +++ b/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory @@ -1 +1 @@ -io.kokuwa.keycloak.metrics.MicrometerEventListenerFactory +io.kokuwa.keycloak.metrics.MetricsEventListenerFactory diff --git a/src/test/java/io/kokuwa/keycloak/metrics/MicrometerEventListenerTest.java b/src/test/java/io/kokuwa/keycloak/metrics/MetricsEventListenerTest.java similarity index 98% rename from src/test/java/io/kokuwa/keycloak/metrics/MicrometerEventListenerTest.java rename to src/test/java/io/kokuwa/keycloak/metrics/MetricsEventListenerTest.java index 5d358c5..2abb9ea 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/MicrometerEventListenerTest.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/MetricsEventListenerTest.java @@ -35,12 +35,12 @@ import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; /** - * Test for {@link MicrometerEventListener} with Mockito. + * Test for {@link MetricsEventListener} with Mockito. * * @author Stephan Schnabel */ @ExtendWith(MockitoExtension.class) -public class MicrometerEventListenerTest { +public class MetricsEventListenerTest { @Mock KeycloakSession session; @@ -378,8 +378,8 @@ public class MicrometerEventListenerTest { } } - private MicrometerEventListener listener(boolean replace) { - return new MicrometerEventListener(registry, session, replace); + private MetricsEventListener listener(boolean replaceIds) { + return new MetricsEventListener(registry, replaceIds, session); } private void assertCounter(String metric, Map tags) { diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java index 892eceb..31ffe6c 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java @@ -60,7 +60,6 @@ public class KeycloakExtension implements BeforeAllCallback, ParameterResolver { .withEnv("KC_LOG_CONSOLE_COLOR", "true") .withEnv("KC_HEALTH_ENABLED", "true") .withEnv("KC_METRICS_ENABLED", "true") - .withEnv("KC_METRICS_EVENT_REPLACE_IDS", "true") .withCopyFileToContainer(MountableFile.forHostPath(jar), "/opt/keycloak/providers/metrics.jar") .withLogConsumer(out -> System.out.print(out.getUtf8String())) .withExposedPorts(8080) From 32fc7a1d5d71a03ca501b6edbf01648764861ed2 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Mon, 24 Apr 2023 14:58:23 +0200 Subject: [PATCH 03/93] Move event-listener to sub package (#29) --- .../keycloak/metrics/{ => event}/MetricsEventListener.java | 2 +- .../metrics/{ => event}/MetricsEventListenerFactory.java | 2 +- .../org.keycloak.events.EventListenerProviderFactory | 2 +- src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java | 2 +- .../metrics/{ => event}/MetricsEventListenerTest.java | 6 +++--- .../io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java | 3 --- .../keycloak/metrics/{prometheus => junit}/Prometheus.java | 2 +- .../metrics/{prometheus => junit}/PrometheusClient.java | 2 +- .../metrics/{prometheus => junit}/PrometheusMetric.java | 2 +- 9 files changed, 10 insertions(+), 13 deletions(-) rename src/main/java/io/kokuwa/keycloak/metrics/{ => event}/MetricsEventListener.java (98%) rename src/main/java/io/kokuwa/keycloak/metrics/{ => event}/MetricsEventListenerFactory.java (96%) rename src/test/java/io/kokuwa/keycloak/metrics/{ => event}/MetricsEventListenerTest.java (98%) rename src/test/java/io/kokuwa/keycloak/metrics/{prometheus => junit}/Prometheus.java (97%) rename src/test/java/io/kokuwa/keycloak/metrics/{prometheus => junit}/PrometheusClient.java (86%) rename src/test/java/io/kokuwa/keycloak/metrics/{prometheus => junit}/PrometheusMetric.java (86%) diff --git a/src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListener.java b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListener.java similarity index 98% rename from src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListener.java rename to src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListener.java index ea811fb..38bb7d0 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListener.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListener.java @@ -1,4 +1,4 @@ -package io.kokuwa.keycloak.metrics; +package io.kokuwa.keycloak.metrics.event; import java.util.Optional; diff --git a/src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListenerFactory.java b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerFactory.java similarity index 96% rename from src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListenerFactory.java rename to src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerFactory.java index 3804d21..b5e8a68 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/MetricsEventListenerFactory.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerFactory.java @@ -1,4 +1,4 @@ -package io.kokuwa.keycloak.metrics; +package io.kokuwa.keycloak.metrics.event; import javax.enterprise.inject.spi.CDI; diff --git a/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory b/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory index 6fca1e1..9984e54 100644 --- a/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory +++ b/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory @@ -1 +1 @@ -io.kokuwa.keycloak.metrics.MetricsEventListenerFactory +io.kokuwa.keycloak.metrics.event.MetricsEventListenerFactory diff --git a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java index 283f3a9..aab932e 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java @@ -14,7 +14,7 @@ import org.keycloak.events.EventType; import io.kokuwa.keycloak.metrics.junit.KeycloakClient; import io.kokuwa.keycloak.metrics.junit.KeycloakExtension; -import io.kokuwa.keycloak.metrics.prometheus.Prometheus; +import io.kokuwa.keycloak.metrics.junit.Prometheus; /** * Integration tests with Keycloak. diff --git a/src/test/java/io/kokuwa/keycloak/metrics/MetricsEventListenerTest.java b/src/test/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerTest.java similarity index 98% rename from src/test/java/io/kokuwa/keycloak/metrics/MetricsEventListenerTest.java rename to src/test/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerTest.java index 2abb9ea..f1bd995 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/MetricsEventListenerTest.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerTest.java @@ -1,4 +1,4 @@ -package io.kokuwa.keycloak.metrics; +package io.kokuwa.keycloak.metrics.event; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; @@ -378,8 +378,8 @@ public class MetricsEventListenerTest { } } - private MetricsEventListener listener(boolean replaceIds) { - return new MetricsEventListener(registry, replaceIds, session); + private MetricsEventListener listener(boolean replace) { + return new MetricsEventListener(registry, replace, session); } private void assertCounter(String metric, Map tags) { diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java index 31ffe6c..8238320 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java @@ -19,9 +19,6 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.MountableFile; -import io.kokuwa.keycloak.metrics.prometheus.Prometheus; -import io.kokuwa.keycloak.metrics.prometheus.PrometheusClient; - /** * JUnit extension to start keycloak. * diff --git a/src/test/java/io/kokuwa/keycloak/metrics/prometheus/Prometheus.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/Prometheus.java similarity index 97% rename from src/test/java/io/kokuwa/keycloak/metrics/prometheus/Prometheus.java rename to src/test/java/io/kokuwa/keycloak/metrics/junit/Prometheus.java index 8fa1483..7bcc4ff 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/prometheus/Prometheus.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/Prometheus.java @@ -1,4 +1,4 @@ -package io.kokuwa.keycloak.metrics.prometheus; +package io.kokuwa.keycloak.metrics.junit; import java.util.HashSet; import java.util.Map; diff --git a/src/test/java/io/kokuwa/keycloak/metrics/prometheus/PrometheusClient.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/PrometheusClient.java similarity index 86% rename from src/test/java/io/kokuwa/keycloak/metrics/prometheus/PrometheusClient.java rename to src/test/java/io/kokuwa/keycloak/metrics/junit/PrometheusClient.java index 2355f3f..0ce08bd 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/prometheus/PrometheusClient.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/PrometheusClient.java @@ -1,4 +1,4 @@ -package io.kokuwa.keycloak.metrics.prometheus; +package io.kokuwa.keycloak.metrics.junit; import javax.ws.rs.Consumes; import javax.ws.rs.GET; diff --git a/src/test/java/io/kokuwa/keycloak/metrics/prometheus/PrometheusMetric.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/PrometheusMetric.java similarity index 86% rename from src/test/java/io/kokuwa/keycloak/metrics/prometheus/PrometheusMetric.java rename to src/test/java/io/kokuwa/keycloak/metrics/junit/PrometheusMetric.java index a79f6c8..9996372 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/prometheus/PrometheusMetric.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/PrometheusMetric.java @@ -1,4 +1,4 @@ -package io.kokuwa.keycloak.metrics.prometheus; +package io.kokuwa.keycloak.metrics.junit; import java.util.Map; From 566f31ddc2b840cfeadb9afcd2816d88f9b34ab0 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Tue, 25 Apr 2023 08:51:48 +0200 Subject: [PATCH 04/93] Replace CDI with Micrometer global (#30) --- .../metrics/event/MetricsEventListenerFactory.java | 10 +++------- .../java/io/kokuwa/keycloak/metrics/KeycloakIT.java | 8 ++++---- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerFactory.java b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerFactory.java index b5e8a68..1cd62d4 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerFactory.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerFactory.java @@ -1,7 +1,5 @@ package io.kokuwa.keycloak.metrics.event; -import javax.enterprise.inject.spi.CDI; - import org.jboss.logging.Logger; import org.keycloak.Config.Scope; import org.keycloak.events.EventListenerProvider; @@ -10,6 +8,7 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Metrics; /** * Factory for {@link MetricsEventListener}, uses {@link MeterRegistry} from CDI. @@ -19,7 +18,6 @@ import io.micrometer.core.instrument.MeterRegistry; public class MetricsEventListenerFactory implements EventListenerProviderFactory { private static final Logger log = Logger.getLogger(MetricsEventListenerFactory.class); - private MeterRegistry registry; private boolean replaceIds; @Override @@ -34,13 +32,11 @@ public class MetricsEventListenerFactory implements EventListenerProviderFactory } @Override - public void postInit(KeycloakSessionFactory factory) { - registry = CDI.current().select(MeterRegistry.class).get(); - } + public void postInit(KeycloakSessionFactory factory) {} @Override public EventListenerProvider create(KeycloakSession session) { - return new MetricsEventListener(registry, replaceIds, session); + return new MetricsEventListener(Metrics.globalRegistry, replaceIds, session); } @Override diff --git a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java index aab932e..2423820 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java @@ -28,16 +28,16 @@ public class KeycloakIT { @Test void loginAndAttempts(KeycloakClient keycloak, Prometheus prometheus) { - var clientId1 = UUID.randomUUID().toString(); - var realmName1 = UUID.randomUUID().toString(); + var realmName1 = "loginAndAttempts_1"; + var clientId1 = realmName1 + "_client_1"; var username1 = UUID.randomUUID().toString(); var password1 = UUID.randomUUID().toString(); keycloak.createRealm(realmName1); keycloak.createClient(realmName1, clientId1); keycloak.createUser(realmName1, username1, password1); - var clientId2 = UUID.randomUUID().toString(); - var realmName2 = UUID.randomUUID().toString(); + var realmName2 = "loginAndAttempts_2"; + var clientId2 = realmName2 + "_client_2"; var username2 = UUID.randomUUID().toString(); var password2 = UUID.randomUUID().toString(); keycloak.createRealm(realmName2); From 37dcc073095dad277d2f50d9d1a1e28374a67de1 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Tue, 25 Apr 2023 10:28:30 +0200 Subject: [PATCH 05/93] Add additional metrics for user/client/session count (#31) --- README.md | 48 +++++++++- .../metrics/stats/MetricsStatsFactory.java | 10 +++ .../stats/MetricsStatsFactoryImpl.java | 69 ++++++++++++++ .../metrics/stats/MetricsStatsSpi.java | 34 +++++++ .../metrics/stats/MetricsStatsTask.java | 89 +++++++++++++++++++ ...keycloak.metrics.stats.MetricsStatsFactory | 1 + .../services/org.keycloak.provider.Spi | 1 + .../kokuwa/keycloak/metrics/KeycloakIT.java | 40 +++++++++ .../metrics/junit/KeycloakClient.java | 15 +++- .../metrics/junit/KeycloakExtension.java | 3 + .../keycloak/metrics/junit/Prometheus.java | 8 ++ 11 files changed, 312 insertions(+), 6 deletions(-) create mode 100644 src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactory.java create mode 100644 src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java create mode 100644 src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsSpi.java create mode 100644 src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java create mode 100644 src/main/resources/META-INF/services/io.kokuwa.keycloak.metrics.stats.MetricsStatsFactory create mode 100644 src/main/resources/META-INF/services/org.keycloak.provider.Spi diff --git a/README.md b/README.md index 9b1f341..f9f4236 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Keycloak Event Metrics +# Keycloak Metrics -Provides metrics for Keycloak user/admin events. Tested on Keycloak [20-21](.github/workflows/ci.yaml#L74-L77). +Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [20-21](.github/workflows/ci.yaml#L74-L77). [![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/kokuwaio/keycloak-event-metrics.svg?label=License)](http://www.apache.org/licenses/) [![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) @@ -14,7 +14,8 @@ Provides metrics for Keycloak user/admin events. Tested on Keycloak [20-21](.git * no realm specific Prometheus endpoint, only `/metrics` (from Quarkus) * no jvm/http metrics, this is [already](https://www.keycloak.org/server/configuration-metrics#_available_metrics) included in Keycloak * different metric names, can relace model ids with name (see [configuration](#kc_metrics_event_replace_ids)) -* deployed to maven central and very small (10 kb vs. 229 KB [aerogear/keycloak-metrics-spi](https://github.com/aerogear/keycloak-metrics-spi)) +* deployed to maven central and very small (15 kb vs. 151 KB [aerogear/keycloak-metrics-spi](https://github.com/aerogear/keycloak-metrics-spi)) +* gauge for active/offline sessions and user/client count ## What? @@ -57,7 +58,7 @@ keycloak_event_admin_total{error="",operation="CREATE",realm="9039a0b5-e8c9-437a ### `KC_METRICS_EVENT_REPLACE_IDS` -Per set to `true` (the default value) than replace model ids with names: +Set to `true` (the default value) than replace model ids from events with names: * [RealmModel#getId()](https://github.com/keycloak/keycloak/blob/main/server-spi/src/main/java/org/keycloak/models/RealmModel.java#L82) with [RealmModel#getName()](https://github.com/keycloak/keycloak/blob/main/server-spi/src/main/java/org/keycloak/models/RealmModel.java#L84) @@ -69,6 +70,45 @@ keycloak_event_user_total{client="other-client",error="",realm="other-realm",typ keycloak_event_user_total{client="other-client",error="invalid_user_credentials",realm="other-realm",type="LOGIN_ERROR",} 1.0 ``` +### `KC_METRICS_STATS_ENABLED` + +Set to `true` (default is `false`) to provide metrics for user/client count per realm and session count per client. Metrics: + +```txt +# HELP keycloak_users +# TYPE keycloak_users gauge +keycloak_users{realm="master",} 1.0 +keycloak_users{realm="my-realm",} 2.0 +keycloak_users{realm="other-realm",} 1.0# HELP keycloak_active_user_sessions +# TYPE keycloak_active_user_sessions gauge +keycloak_active_user_sessions{client="admin-cli",realm="userCount_1",} 0.0 +keycloak_active_user_sessions{client="admin-cli",realm="userCount_2",} 0.0 +keycloak_active_user_sessions{client="admin-cli",realm="master",} 1.0 +# TYPE keycloak_active_client_sessions gauge +keycloak_active_client_sessions{client="admin-cli",realm="userCount_1",} 0.0 +keycloak_active_client_sessions{client="admin-cli",realm="userCount_2",} 0.0 +keycloak_active_client_sessions{client="admin-cli",realm="master",} 0.0 +# TYPE keycloak_offline_sessions gauge +keycloak_offline_sessions{client="admin-cli",realm="userCount_1",} 0.0 +keycloak_offline_sessions{client="admin-cli",realm="userCount_2",} 0.0 +keycloak_offline_sessions{client="admin-cli",realm="master",} 0.0 +``` + +### `KC_METRICS_STATS_INTERVAL` + +If `KC_METRICS_STATS_ENABLED` is `true` this will define the interval for scraping. If not configured `PT60s` will be used. + +### `KC_METRICS_STATS_INFO_THRESHOLD` and `KC_METRICS_STATS_WARN_THRESHOLD` + +If `KC_METRICS_STATS_ENABLED` is `true` this envs will define logging if scraping takes to long. Both envs are parsed as `java.lang.Duration`. + +Default values: + +* `KC_METRICS_STATS_INFO_THRESHOLD`: 50% of `KC_METRICS_STATS_INTERVAL` = 30s +* `KC_METRICS_STATS_WARN_THRESHOLD`: 75% of `KC_METRICS_STATS_INTERVAL` = 45s + +If scrapping takes less than `KC_METRICS_STATS_INFO_THRESHOLD` duration will be logged on debug level. + ## Installation ### Testcontainers diff --git a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactory.java b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactory.java new file mode 100644 index 0000000..13b626e --- /dev/null +++ b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactory.java @@ -0,0 +1,10 @@ +package io.kokuwa.keycloak.metrics.stats; + +import org.keycloak.provider.ProviderFactory; + +/** + * Factory for Keycloak metrics. + * + * @author Stephan Schnabel + */ +public interface MetricsStatsFactory extends ProviderFactory {} diff --git a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java new file mode 100644 index 0000000..46cb9f5 --- /dev/null +++ b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java @@ -0,0 +1,69 @@ +package io.kokuwa.keycloak.metrics.stats; + +import java.time.Duration; +import java.util.Optional; + +import org.jboss.logging.Logger; +import org.keycloak.Config.Scope; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.models.utils.KeycloakModelUtils; +import org.keycloak.timer.TimerProvider; + +import io.micrometer.core.instrument.Metrics; + +/** + * Implementation of {@link MetricsStatsFactory}. + * + * @author Stephan Schnabel + */ +public class MetricsStatsFactoryImpl implements MetricsStatsFactory { + + private static final Logger log = Logger.getLogger(MetricsStatsFactory.class); + + @Override + public String getId() { + return "default"; + } + + @Override + public void init(Scope config) {} + + @Override + public void postInit(KeycloakSessionFactory factory) { + + if (!"true".equals(System.getenv().get("KC_METRICS_STATS_ENABLED"))) { + log.infov("Keycloak stats not enabled."); + return; + } + + var intervalDuration = Optional + .ofNullable(System.getenv("KC_METRICS_STATS_INTERVAL")) + .map(Duration::parse) + .orElse(Duration.ofSeconds(60)); + var infoThreshold = Optional + .ofNullable(System.getenv("KC_METRICS_STATS_INFO_THRESHOLD")) + .map(Duration::parse) + .orElse(Duration.ofMillis(Double.valueOf(intervalDuration.toMillis() * 0.5).longValue())); + var warnThreshold = Optional + .ofNullable(System.getenv("KC_METRICS_STATS_WARN_THRESHOLD")) + .map(Duration::parse) + .orElse(Duration.ofMillis(Double.valueOf(intervalDuration.toMillis() * 0.75).longValue())); + log.infov("Keycloak stats enabled with interval of {0} and info/warn after {1}/{2}.", + intervalDuration, infoThreshold, warnThreshold); + + var interval = intervalDuration.toMillis(); + var task = new MetricsStatsTask(Metrics.globalRegistry, intervalDuration, infoThreshold, warnThreshold); + KeycloakModelUtils.runJobInTransaction(factory, session -> session + .getProvider(TimerProvider.class) + .schedule(() -> KeycloakModelUtils.runJobInTransaction(factory, task), interval, "metrics")); + } + + @Override + public MetricsStatsTask create(KeycloakSession session) { + return null; + } + + @Override + public void close() {} +} diff --git a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsSpi.java b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsSpi.java new file mode 100644 index 0000000..35db096 --- /dev/null +++ b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsSpi.java @@ -0,0 +1,34 @@ +package io.kokuwa.keycloak.metrics.stats; + +import org.keycloak.provider.Provider; +import org.keycloak.provider.ProviderFactory; +import org.keycloak.provider.Spi; + +/** + * SPI for Keycloak metrics. + * + * @author Stephan Schnabel + */ +public class MetricsStatsSpi implements Spi { + + @Override + public boolean isInternal() { + return false; + } + + @Override + public String getName() { + return "metrics"; + } + + @Override + public Class getProviderClass() { + return MetricsStatsTask.class; + } + + @Override + public Class> getProviderFactoryClass() { + // this must be an interface, otherwise spi will be silenty ignored + return MetricsStatsFactory.class; + } +} diff --git a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java new file mode 100644 index 0000000..a0767a8 --- /dev/null +++ b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java @@ -0,0 +1,89 @@ +package io.kokuwa.keycloak.metrics.stats; + +import java.time.Duration; +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +import org.jboss.logging.Logger; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionTask; +import org.keycloak.provider.Provider; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; + +/** + * Keycloak metrics. + * + * @author Stephan Schnabel + */ +public class MetricsStatsTask implements Provider, KeycloakSessionTask { + + private static final Logger log = Logger.getLogger(MetricsStatsTask.class); + private final Map values = new HashMap<>(); + private final MeterRegistry registry; + private final Duration interval; + private final Duration infoThreshold; + private final Duration warnThreshold; + + MetricsStatsTask(MeterRegistry registry, Duration interval, Duration infoThreshold, Duration warnThreshold) { + this.registry = registry; + this.interval = interval; + this.infoThreshold = infoThreshold; + this.warnThreshold = warnThreshold; + } + + @Override + public void run(KeycloakSession session) { + log.tracev("Triggered metrics stats task."); + var start = Instant.now(); + + try { + scrape(session); + } catch (Exception e) { + if (e instanceof org.hibernate.exception.SQLGrammarException) { + log.infov("Metrics status task skipped, database not ready"); + } else { + log.errorv(e, "Failed to scrape stats."); + } + return; + } + + var duration = Duration.between(start, Instant.now()); + if (duration.compareTo(interval) > 0) { + log.errorv("Finished scrapping keycloak stats in {0}, consider to increase interval", duration); + } else if (duration.compareTo(warnThreshold) > 0) { + log.warnv("Finished scrapping keycloak stats in {0}, consider to increase interval", duration); + } else if (duration.compareTo(infoThreshold) > 0) { + log.infov("Finished scrapping keycloak stats in {0}", duration); + } else { + log.debugv("Finished scrapping keycloak stats in {0}", duration); + } + } + + @Override + public void close() {} + + private void scrape(KeycloakSession session) { + session.realms().getRealmsStream().forEach(realm -> { + var tagRealm = Tag.of("realm", realm.getName()); + gauge("keycloak_users", Set.of(tagRealm), session.users().getUsersCount(realm)); + gauge("keycloak_clients", Set.of(tagRealm), session.clients().getClientsCount(realm)); + var sessions = session.sessions(); + var activeSessions = sessions.getActiveClientSessionStats(realm, false); + realm.getClientsStream().forEach(client -> { + var tags = Set.of(tagRealm, Tag.of("client", client.getClientId())); + gauge("keycloak_offline_sessions", tags, sessions.getOfflineSessionsCount(realm, client)); + gauge("keycloak_active_user_sessions", tags, sessions.getActiveUserSessions(realm, client)); + gauge("keycloak_active_client_sessions", tags, activeSessions.getOrDefault(client.getId(), 0L)); + }); + }); + } + + private void gauge(String name, Set tags, long value) { + values.computeIfAbsent(name + tags, s -> registry.gauge(name, tags, new AtomicLong())).set(value); + } +} diff --git a/src/main/resources/META-INF/services/io.kokuwa.keycloak.metrics.stats.MetricsStatsFactory b/src/main/resources/META-INF/services/io.kokuwa.keycloak.metrics.stats.MetricsStatsFactory new file mode 100644 index 0000000..45c8b40 --- /dev/null +++ b/src/main/resources/META-INF/services/io.kokuwa.keycloak.metrics.stats.MetricsStatsFactory @@ -0,0 +1 @@ +io.kokuwa.keycloak.metrics.stats.MetricsStatsFactoryImpl diff --git a/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/src/main/resources/META-INF/services/org.keycloak.provider.Spi new file mode 100644 index 0000000..f80dc90 --- /dev/null +++ b/src/main/resources/META-INF/services/org.keycloak.provider.Spi @@ -0,0 +1 @@ +io.kokuwa.keycloak.metrics.stats.MetricsStatsSpi \ No newline at end of file diff --git a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java index 2423820..4475113 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java @@ -1,11 +1,14 @@ package io.kokuwa.keycloak.metrics; import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.time.Instant; import java.util.UUID; +import java.util.function.Supplier; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -73,4 +76,41 @@ public class KeycloakIT { () -> assertEquals(loginErrorBefore1 + 0, loginErrorAfter1, "login failure #1"), () -> assertEquals(loginErrorBefore2 + 1, loginErrorAfter2, "login failure #2")); } + + @DisplayName("user count") + @Test + void userCount(KeycloakClient keycloak, Prometheus prometheus) { + + var realmName1 = "userCount_1"; + var realmName2 = "userCount_2"; + var username = UUID.randomUUID().toString(); + + keycloak.createRealm(realmName1); + keycloak.createRealm(realmName2); + + await(() -> prometheus.userCount(realmName1) == 0, prometheus, "realm 1 not found"); + await(() -> prometheus.userCount(realmName2) == 0, prometheus, "realm 2 not found"); + + keycloak.createUser(realmName1, username, UUID.randomUUID().toString()); + keycloak.createUser(realmName1, UUID.randomUUID().toString(), UUID.randomUUID().toString()); + keycloak.createUser(realmName1, UUID.randomUUID().toString(), UUID.randomUUID().toString()); + keycloak.createUser(realmName2, UUID.randomUUID().toString(), UUID.randomUUID().toString()); + + await(() -> prometheus.userCount(realmName1) == 3, prometheus, "realm 1 shoud have 3 users"); + await(() -> prometheus.userCount(realmName2) == 1, prometheus, "realm 2 shoud have 1 users"); + + keycloak.deleteUser(realmName1, username); + + await(() -> prometheus.userCount(realmName1) == 2, prometheus, "realm 1 shoud have 2 users after deletion"); + await(() -> prometheus.userCount(realmName2) == 1, prometheus, "realm 2 shoud have 1 users"); + } + + void await(Supplier check, Prometheus prometheus, String message) { + var end = Instant.now().plusSeconds(10); + while (Instant.now().isBefore(end) && !check.get()) { + assertDoesNotThrow(() -> Thread.sleep(1000)); + prometheus.scrap(); + } + assertTrue(check.get(), message); + } } diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java index 3d8f902..6d48781 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java @@ -1,5 +1,7 @@ package io.kokuwa.keycloak.metrics.junit; +import static org.junit.jupiter.api.Assertions.assertEquals; + import java.util.List; import java.util.Map; import java.util.UUID; @@ -45,7 +47,8 @@ public class KeycloakClient { client.setClientId(clientId); client.setPublicClient(true); client.setDirectAccessGrantsEnabled(true); - keycloak.realms().realm(realmName).clients().create(client); + var response = keycloak.realms().realm(realmName).clients().create(client); + assertEquals(201, response.getStatus()); } public void createUser(String realmName, String username, String password) { @@ -59,7 +62,15 @@ public class KeycloakClient { user.setEmailVerified(true); user.setUsername(username); user.setCredentials(List.of(credential)); - keycloak.realms().realm(realmName).users().create(user); + var response = keycloak.realms().realm(realmName).users().create(user); + assertEquals(201, response.getStatus()); + } + + public void deleteUser(String realmName, String username) { + keycloak.realms().realm(realmName).users() + .searchByUsername(username, true).stream() + .map(UserRepresentation::getId) + .forEach(keycloak.realms().realm(realmName).users()::delete); } public boolean login(String clientId, String realmName, String username, String password) { diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java index 8238320..b5d7775 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java @@ -55,8 +55,11 @@ public class KeycloakExtension implements BeforeAllCallback, ParameterResolver { .withEnv("KEYCLOAK_ADMIN", "admin") .withEnv("KEYCLOAK_ADMIN_PASSWORD", "password") .withEnv("KC_LOG_CONSOLE_COLOR", "true") + .withEnv("KC_LOG_LEVEL", "io.kokuwa:trace") .withEnv("KC_HEALTH_ENABLED", "true") .withEnv("KC_METRICS_ENABLED", "true") + .withEnv("KC_METRICS_STATS_ENABLED", "true") + .withEnv("KC_METRICS_STATS_INTERVAL", "PT1s") .withCopyFileToContainer(MountableFile.forHostPath(jar), "/opt/keycloak/providers/metrics.jar") .withLogConsumer(out -> System.out.print(out.getUtf8String())) .withExposedPorts(8080) diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/Prometheus.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/Prometheus.java index 7bcc4ff..74a0cb9 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/Prometheus.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/Prometheus.java @@ -41,6 +41,14 @@ public class Prometheus { .sum(); } + public int userCount(String realm) { + return state.stream() + .filter(metric -> Objects.equals(metric.name(), "keycloak_users")) + .filter(metric -> Objects.equals(metric.tags().get("realm"), realm)) + .mapToInt(metric -> metric.value().intValue()) + .sum(); + } + public void scrap() { state.clear(); Stream.of(client.scrap().split("[\\r\\n]+")) From c0b7ab6b586b8c8de0044d515de0d099bee4ef2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 08:09:25 +0000 Subject: [PATCH 06/93] Bump maven-checkstyle-plugin from 3.2.1 to 3.2.2 (#34) Bumps [maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) from 3.2.1 to 3.2.2. - [Release notes](https://github.com/apache/maven-checkstyle-plugin/releases) - [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.2.1...maven-checkstyle-plugin-3.2.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 999fb8a..6466b05 100644 --- a/pom.xml +++ b/pom.xml @@ -78,7 +78,7 @@ - 3.2.1 + 3.2.2 3.2.0 3.11.0 3.5.0 From 52d33f1d78628f30370332114d88b70c9c6fea83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 08:10:34 +0000 Subject: [PATCH 07/93] Bump mockito-junit-jupiter from 5.2.0 to 5.3.1 (#35) Bumps [mockito-junit-jupiter](https://github.com/mockito/mockito) from 5.2.0 to 5.3.1. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v5.2.0...v5.3.1) --- updated-dependencies: - dependency-name: org.mockito:mockito-junit-jupiter dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6466b05..f874532 100644 --- a/pom.xml +++ b/pom.xml @@ -99,7 +99,7 @@ 21.1.0 - 5.2.0 + 5.3.1 1.18.0 From f17c6e5e9077c654f8faf54341ed7b9872ae3782 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 08:13:27 +0000 Subject: [PATCH 08/93] Bump checkstyle from 10.9.3 to 10.10.0 (#37) Bumps [checkstyle](https://github.com/checkstyle/checkstyle) from 10.9.3 to 10.10.0. - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.9.3...checkstyle-10.10.0) --- updated-dependencies: - dependency-name: com.puppycrawl.tools:checkstyle dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f874532..69a72d5 100644 --- a/pom.xml +++ b/pom.xml @@ -93,7 +93,7 @@ 3.0.0 1.2.0 1.6.13 - 10.9.3 + 10.10.0 0.5.6 From f836554143695e3bcde45e3f25232f8c65a3cd67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 08:23:30 +0000 Subject: [PATCH 09/93] Bump keycloak-parent from 21.1.0 to 21.1.1 (#36) Bumps [keycloak-parent](https://github.com/keycloak/keycloak) from 21.1.0 to 21.1.1. - [Release notes](https://github.com/keycloak/keycloak/releases) - [Commits](https://github.com/keycloak/keycloak/compare/21.1.0...21.1.1) --- updated-dependencies: - dependency-name: org.keycloak:keycloak-parent dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 69a72d5..559384d 100644 --- a/pom.xml +++ b/pom.xml @@ -98,7 +98,7 @@ - 21.1.0 + 21.1.1 5.3.1 1.18.0 From b4e8c3be4e7ba8fc9d6e1397b0d47c50a9137aaf Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Mon, 1 May 2023 12:45:09 +0200 Subject: [PATCH 10/93] Include 21.1.1 in ci --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8c6aab0..a1394ca 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -76,6 +76,7 @@ jobs: - 21.0.1 - 21.0.2 - 21.1.0 + - 21.1.1 steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 From cfce0dee45ffb281af396cdc85ef983726e499c9 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Tue, 2 May 2023 09:02:27 +0200 Subject: [PATCH 11/93] Refactor test: remove micrometer mocking, micrometer is testable (#32) --- pom.xml | 2 +- .../metrics/event/MetricsEventListener.java | 10 ++- .../event/MetricsEventListenerFactory.java | 7 +-- .../stats/MetricsStatsFactoryImpl.java | 6 +- .../metrics/stats/MetricsStatsTask.java | 14 ++--- .../event/MetricsEventListenerTest.java | 63 +++++-------------- .../metrics/junit/AbstractMockitoTest.java | 29 +++++++++ 7 files changed, 61 insertions(+), 70 deletions(-) create mode 100644 src/test/java/io/kokuwa/keycloak/metrics/junit/AbstractMockitoTest.java diff --git a/pom.xml b/pom.xml index 559384d..3a77f1a 100644 --- a/pom.xml +++ b/pom.xml @@ -159,7 +159,7 @@ com.openshift openshift-restclient-java - + org.keycloak keycloak-admin-ui diff --git a/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListener.java b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListener.java index 38bb7d0..4ba5144 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListener.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListener.java @@ -10,7 +10,7 @@ import org.keycloak.models.KeycloakContext; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; -import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Metrics; /** * Listener for {@link Event} and {@link AdminEvent}. @@ -20,19 +20,17 @@ import io.micrometer.core.instrument.MeterRegistry; public class MetricsEventListener implements EventListenerProvider, AutoCloseable { private static final Logger log = Logger.getLogger(MetricsEventListener.class); - private final MeterRegistry registry; private final boolean replaceIds; private final KeycloakSession session; - MetricsEventListener(MeterRegistry registry, boolean replaceIds, KeycloakSession session) { - this.registry = registry; + MetricsEventListener(boolean replaceIds, KeycloakSession session) { this.replaceIds = replaceIds; this.session = session; } @Override public void onEvent(Event event) { - registry.counter("keycloak_event_user", + Metrics.counter("keycloak_event_user", "realm", toBlank(replaceIds ? getRealmName(event.getRealmId()) : event.getRealmId()), "type", toBlank(event.getType()), "client", toBlank(event.getClientId()), @@ -42,7 +40,7 @@ public class MetricsEventListener implements EventListenerProvider, AutoCloseabl @Override public void onEvent(AdminEvent event, boolean includeRepresentation) { - registry.counter("keycloak_event_admin", + Metrics.counter("keycloak_event_admin", "realm", toBlank(replaceIds ? getRealmName(event.getRealmId()) : event.getRealmId()), "resource", toBlank(event.getResourceType()), "operation", toBlank(event.getOperationType()), diff --git a/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerFactory.java b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerFactory.java index 1cd62d4..1580be7 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerFactory.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerFactory.java @@ -7,11 +7,8 @@ import org.keycloak.events.EventListenerProviderFactory; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Metrics; - /** - * Factory for {@link MetricsEventListener}, uses {@link MeterRegistry} from CDI. + * Factory for {@link MetricsEventListener}. * * @author Stephan Schnabel */ @@ -36,7 +33,7 @@ public class MetricsEventListenerFactory implements EventListenerProviderFactory @Override public EventListenerProvider create(KeycloakSession session) { - return new MetricsEventListener(Metrics.globalRegistry, replaceIds, session); + return new MetricsEventListener(replaceIds, session); } @Override diff --git a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java index 46cb9f5..03d8f78 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java @@ -10,8 +10,6 @@ import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.timer.TimerProvider; -import io.micrometer.core.instrument.Metrics; - /** * Implementation of {@link MetricsStatsFactory}. * @@ -53,10 +51,10 @@ public class MetricsStatsFactoryImpl implements MetricsStatsFactory { intervalDuration, infoThreshold, warnThreshold); var interval = intervalDuration.toMillis(); - var task = new MetricsStatsTask(Metrics.globalRegistry, intervalDuration, infoThreshold, warnThreshold); + var task = new MetricsStatsTask(intervalDuration, infoThreshold, warnThreshold); KeycloakModelUtils.runJobInTransaction(factory, session -> session .getProvider(TimerProvider.class) - .schedule(() -> KeycloakModelUtils.runJobInTransaction(factory, task), interval, "metrics")); + .scheduleTask(task, interval, "metrics")); } @Override diff --git a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java index a0767a8..22f7c3c 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java @@ -9,10 +9,10 @@ import java.util.concurrent.atomic.AtomicLong; import org.jboss.logging.Logger; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.KeycloakSessionTask; import org.keycloak.provider.Provider; +import org.keycloak.timer.ScheduledTask; -import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Metrics; import io.micrometer.core.instrument.Tag; /** @@ -20,17 +20,15 @@ import io.micrometer.core.instrument.Tag; * * @author Stephan Schnabel */ -public class MetricsStatsTask implements Provider, KeycloakSessionTask { +public class MetricsStatsTask implements Provider, ScheduledTask { private static final Logger log = Logger.getLogger(MetricsStatsTask.class); - private final Map values = new HashMap<>(); - private final MeterRegistry registry; + private static final Map values = new HashMap<>(); private final Duration interval; private final Duration infoThreshold; private final Duration warnThreshold; - MetricsStatsTask(MeterRegistry registry, Duration interval, Duration infoThreshold, Duration warnThreshold) { - this.registry = registry; + MetricsStatsTask(Duration interval, Duration infoThreshold, Duration warnThreshold) { this.interval = interval; this.infoThreshold = infoThreshold; this.warnThreshold = warnThreshold; @@ -84,6 +82,6 @@ public class MetricsStatsTask implements Provider, KeycloakSessionTask { } private void gauge(String name, Set tags, long value) { - values.computeIfAbsent(name + tags, s -> registry.gauge(name, tags, new AtomicLong())).set(value); + values.computeIfAbsent(name + tags, s -> Metrics.gauge(name, tags, new AtomicLong())).set(value); } } diff --git a/src/test/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerTest.java b/src/test/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerTest.java index f1bd995..16684c5 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerTest.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerTest.java @@ -1,22 +1,13 @@ package io.kokuwa.keycloak.metrics.event; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.util.Map; -import java.util.TreeMap; import java.util.UUID; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.keycloak.events.Event; import org.keycloak.events.EventType; import org.keycloak.events.admin.AdminEvent; @@ -26,21 +17,18 @@ import org.keycloak.models.KeycloakContext; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import io.micrometer.core.instrument.Counter; -import io.micrometer.core.instrument.MeterRegistry; +import io.kokuwa.keycloak.metrics.junit.AbstractMockitoTest; +import io.micrometer.core.instrument.Metrics; /** * Test for {@link MetricsEventListener} with Mockito. * * @author Stephan Schnabel */ -@ExtendWith(MockitoExtension.class) -public class MetricsEventListenerTest { +@DisplayName("events: listener") +public class MetricsEventListenerTest extends AbstractMockitoTest { @Mock KeycloakSession session; @@ -50,19 +38,6 @@ public class MetricsEventListenerTest { RealmProvider realmProvider; @Mock KeycloakContext context; - @Mock - MeterRegistry registry; - @Mock - Counter counter; - @Captor - ArgumentCaptor metricCaptor; - @Captor - ArgumentCaptor tagsCaptor; - - @BeforeEach - void setup() { - when(registry.counter(metricCaptor.capture(), tagsCaptor.capture())).thenReturn(counter); - } @DisplayName("onEvent(true)") @Nested @@ -213,11 +188,11 @@ public class MetricsEventListenerTest { } private void assertEvent(String realm, String client, String type, String error) { - assertCounter("keycloak_event_user", Map.of( + assertCounter("keycloak_event_user", "realm", realm, "client", client, "type", type, - "error", error)); + "error", error); } } @@ -370,29 +345,25 @@ public class MetricsEventListenerTest { } private void assertAdminEvent(String realm, String resource, String operation, String error) { - assertCounter("keycloak_event_admin", Map.of( + assertCounter("keycloak_event_admin", "realm", realm, "resource", resource, "operation", operation, - "error", error)); + "error", error); } } private MetricsEventListener listener(boolean replace) { - return new MetricsEventListener(registry, replace, session); + return new MetricsEventListener(replace, session); } - private void assertCounter(String metric, Map tags) { - verify(registry).counter(anyString(), any(String[].class)); - verify(counter).increment(); - assertEquals(metric, metricCaptor.getValue(), "metric"); - var expectedTags = new TreeMap<>(tags); - var actualTags = IntStream - .range(0, tagsCaptor.getValue().length / 2).mapToObj(i -> i * 2) - .collect(Collectors.toMap( - i -> tagsCaptor.getValue()[i], - i -> tagsCaptor.getValue()[i + 1], - (i, j) -> i, TreeMap::new)); - assertEquals(expectedTags, actualTags, "tags"); + private static void assertCounter(String metric, String... tags) { + var counter = Metrics.globalRegistry.counter(metric, tags); + assertEquals(1D, counter.count(), "micrometer.counter.count"); + assertEquals(0, Metrics.globalRegistry + .getMeters().stream() + .filter(meter -> meter != counter) + .count(), + "other meter found"); } } diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/AbstractMockitoTest.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/AbstractMockitoTest.java new file mode 100644 index 0000000..e42de7c --- /dev/null +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/AbstractMockitoTest.java @@ -0,0 +1,29 @@ +package io.kokuwa.keycloak.metrics.junit; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.ClassOrderer; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.TestClassOrder; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +/** + * Mockito base class with configured logging. + * + * @author Stephan Schnabel + */ +@ExtendWith(MockitoExtension.class) +@TestClassOrder(ClassOrderer.DisplayName.class) +@TestMethodOrder(MethodOrderer.DisplayName.class) +public abstract class AbstractMockitoTest { + + @BeforeEach + void reset() { + Metrics.globalRegistry.clear(); + Metrics.addRegistry(new SimpleMeterRegistry()); + } +} From 99a01e5c02563239e134c8c67131e0bf68f44b7a Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Tue, 2 May 2023 09:30:58 +0200 Subject: [PATCH 12/93] Add unit tests with mockito for metric stats (#38) --- .../stats/MetricsStatsFactoryImpl.java | 12 +- .../metrics/stats/MetricsStatsTask.java | 10 +- .../metrics/junit/AbstractMockitoTest.java | 42 ++++ .../stats/MetricsStatsFactoryTest.java | 107 +++++++++ .../metrics/stats/MetricsStatsSpiTest.java | 37 +++ .../metrics/stats/MetricsStatsTaskTest.java | 225 ++++++++++++++++++ 6 files changed, 424 insertions(+), 9 deletions(-) create mode 100644 src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryTest.java create mode 100644 src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsSpiTest.java create mode 100644 src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java diff --git a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java index 03d8f78..16aeb25 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryImpl.java @@ -30,21 +30,21 @@ public class MetricsStatsFactoryImpl implements MetricsStatsFactory { @Override public void postInit(KeycloakSessionFactory factory) { - if (!"true".equals(System.getenv().get("KC_METRICS_STATS_ENABLED"))) { + if (!"true".equals(getenv("KC_METRICS_STATS_ENABLED"))) { log.infov("Keycloak stats not enabled."); return; } var intervalDuration = Optional - .ofNullable(System.getenv("KC_METRICS_STATS_INTERVAL")) + .ofNullable(getenv("KC_METRICS_STATS_INTERVAL")) .map(Duration::parse) .orElse(Duration.ofSeconds(60)); var infoThreshold = Optional - .ofNullable(System.getenv("KC_METRICS_STATS_INFO_THRESHOLD")) + .ofNullable(getenv("KC_METRICS_STATS_INFO_THRESHOLD")) .map(Duration::parse) .orElse(Duration.ofMillis(Double.valueOf(intervalDuration.toMillis() * 0.5).longValue())); var warnThreshold = Optional - .ofNullable(System.getenv("KC_METRICS_STATS_WARN_THRESHOLD")) + .ofNullable(getenv("KC_METRICS_STATS_WARN_THRESHOLD")) .map(Duration::parse) .orElse(Duration.ofMillis(Double.valueOf(intervalDuration.toMillis() * 0.75).longValue())); log.infov("Keycloak stats enabled with interval of {0} and info/warn after {1}/{2}.", @@ -64,4 +64,8 @@ public class MetricsStatsFactoryImpl implements MetricsStatsFactory { @Override public void close() {} + + String getenv(String key) { + return System.getenv().get(key); + } } diff --git a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java index 22f7c3c..eabfe2f 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java @@ -43,7 +43,7 @@ public class MetricsStatsTask implements Provider, ScheduledTask { scrape(session); } catch (Exception e) { if (e instanceof org.hibernate.exception.SQLGrammarException) { - log.infov("Metrics status task skipped, database not ready"); + log.infov("Metrics status task skipped, database not ready."); } else { log.errorv(e, "Failed to scrape stats."); } @@ -52,13 +52,13 @@ public class MetricsStatsTask implements Provider, ScheduledTask { var duration = Duration.between(start, Instant.now()); if (duration.compareTo(interval) > 0) { - log.errorv("Finished scrapping keycloak stats in {0}, consider to increase interval", duration); + log.errorv("Finished scrapping keycloak stats in {0}, consider to increase interval.", duration); } else if (duration.compareTo(warnThreshold) > 0) { - log.warnv("Finished scrapping keycloak stats in {0}, consider to increase interval", duration); + log.warnv("Finished scrapping keycloak stats in {0}, consider to increase interval.", duration); } else if (duration.compareTo(infoThreshold) > 0) { - log.infov("Finished scrapping keycloak stats in {0}", duration); + log.infov("Finished scrapping keycloak stats in {0}.", duration); } else { - log.debugv("Finished scrapping keycloak stats in {0}", duration); + log.debugv("Finished scrapping keycloak stats in {0}.", duration); } } diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/AbstractMockitoTest.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/AbstractMockitoTest.java index e42de7c..1a3d597 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/AbstractMockitoTest.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/AbstractMockitoTest.java @@ -1,5 +1,14 @@ package io.kokuwa.keycloak.metrics.junit; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.MethodOrderer; @@ -21,9 +30,42 @@ import io.micrometer.core.instrument.simple.SimpleMeterRegistry; @TestMethodOrder(MethodOrderer.DisplayName.class) public abstract class AbstractMockitoTest { + private static final List LOGS = new ArrayList<>(); + + static { + + System.setProperty("org.jboss.logging.provider", "jdk"); + System.setProperty("java.util.logging.SimpleFormatter.format", "%1$tT %4$-5s %2$s %5$s%6$s%n"); + + Logger.getLogger("org.junit").setLevel(Level.INFO); + Logger.getLogger("").setLevel(Level.ALL); + Logger.getLogger("").addHandler(new Handler() { + + @Override + public void publish(LogRecord log) { + LOGS.add(log); + } + + @Override + public void flush() {} + + @Override + public void close() {} + }); + } + @BeforeEach void reset() { Metrics.globalRegistry.clear(); Metrics.addRegistry(new SimpleMeterRegistry()); + LOGS.clear(); + } + + public static void assertLog(Level level, String message) { + assertTrue(LOGS.stream() + .filter(l -> l.getLevel().equals(level)) + .filter(l -> l.getMessage().equals(message)) + .findAny().isPresent(), + "log with level " + level + " and message " + message + " not found"); } } diff --git a/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryTest.java b/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryTest.java new file mode 100644 index 0000000..1a8a794 --- /dev/null +++ b/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsFactoryTest.java @@ -0,0 +1,107 @@ +package io.kokuwa.keycloak.metrics.stats; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.time.Duration; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.platform.commons.util.ReflectionUtils; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.models.KeycloakTransactionManager; +import org.keycloak.timer.TimerProvider; +import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; +import org.mockito.Mock; +import org.mockito.Spy; + +import io.kokuwa.keycloak.metrics.junit.AbstractMockitoTest; + +/** + * Test for {@link MetricsStatsFactory} with Mockito. + * + * @author Stephan Schnabel + */ +@DisplayName("metrics: factory") +public class MetricsStatsFactoryTest extends AbstractMockitoTest { + + @Spy + MetricsStatsFactoryImpl factory; + @Mock + KeycloakSessionFactory sessionFactory; + @Mock + KeycloakSession session; + + @DisplayName("disabled") + @Test + void disabled() { + factory.init(null); + factory.postInit(sessionFactory); + assertNull(factory.create(session)); + factory.close(); + } + + @DisplayName("enabled - with default values") + @Test + void enabledDefault() { + when(factory.getenv("KC_METRICS_STATS_ENABLED")).thenReturn("true"); + when(factory.getenv("KC_METRICS_STATS_INTERVAL")).thenReturn(null); + when(factory.getenv("KC_METRICS_STATS_INFO_THRESHOLD")).thenReturn(null); + when(factory.getenv("KC_METRICS_STATS_WARN_THRESHOLD")).thenReturn(null); + assertTask(Duration.ofSeconds(60), Duration.ofSeconds(30), Duration.ofSeconds(45)); + } + + @DisplayName("enabled - with custom interval") + @Test + void enabledCustomInterval() { + when(factory.getenv("KC_METRICS_STATS_ENABLED")).thenReturn("true"); + when(factory.getenv("KC_METRICS_STATS_INTERVAL")).thenReturn("PT300s"); + when(factory.getenv("KC_METRICS_STATS_INFO_THRESHOLD")).thenReturn(null); + when(factory.getenv("KC_METRICS_STATS_WARN_THRESHOLD")).thenReturn(null); + assertTask(Duration.ofSeconds(300), Duration.ofSeconds(150), Duration.ofSeconds(225)); + } + + @DisplayName("enabled - with custom thresholds") + @Test + void enabledCustomThresholds() { + when(factory.getenv("KC_METRICS_STATS_ENABLED")).thenReturn("true"); + when(factory.getenv("KC_METRICS_STATS_INTERVAL")).thenReturn(null); + when(factory.getenv("KC_METRICS_STATS_INFO_THRESHOLD")).thenReturn("PT40s"); + when(factory.getenv("KC_METRICS_STATS_WARN_THRESHOLD")).thenReturn("PT50s"); + assertTask(Duration.ofSeconds(60), Duration.ofSeconds(40), Duration.ofSeconds(50)); + } + + private void assertTask(Duration interval, Duration infoThreshold, Duration warnThreshold) { + + var timerProvider = mock(TimerProvider.class); + when(sessionFactory.create()).thenReturn(session); + when(session.getProvider(TimerProvider.class)).thenReturn(timerProvider); + when(session.getTransactionManager()).thenReturn(mock(KeycloakTransactionManager.class)); + + factory.postInit(sessionFactory); + + var taskCaptor = ArgumentCaptor.forClass(MetricsStatsTask.class); + verify(timerProvider).scheduleTask( + taskCaptor.capture(), + ArgumentMatchers.eq(interval.toMillis()), + ArgumentMatchers.eq("metrics")); + assertNotNull(taskCaptor.getValue(), "task"); + assertField(interval, taskCaptor.getValue(), "interval"); + assertField(infoThreshold, taskCaptor.getValue(), "infoThreshold"); + assertField(warnThreshold, taskCaptor.getValue(), "warnThreshold"); + } + + private void assertField(Duration expected, MetricsStatsTask task, String name) { + assertEquals( + expected, + assertDoesNotThrow(() -> ReflectionUtils.tryToReadFieldValue(MetricsStatsTask.class, name, task).get()), + "field " + name + " invalid"); + } +} diff --git a/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsSpiTest.java b/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsSpiTest.java new file mode 100644 index 0000000..e318262 --- /dev/null +++ b/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsSpiTest.java @@ -0,0 +1,37 @@ +package io.kokuwa.keycloak.metrics.stats; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ServiceLoader; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import io.kokuwa.keycloak.metrics.junit.AbstractMockitoTest; + +/** + * Test for {@link MetricsStatsSpi} with Mockito. + * + * @author Stephan Schnabel + */ +@DisplayName("metrics: spi") +public class MetricsStatsSpiTest extends AbstractMockitoTest { + + @Test + void test() { + + var spi = new MetricsStatsSpi(); + assertEquals("metrics", spi.getName(), "getName()"); + assertFalse(spi.isInternal(), "isInternal()"); + assertNotNull(spi.getProviderClass(), "getProviderClass()"); + assertTrue(spi.getProviderFactoryClass().isInterface(), "getProviderFactoryClass() - should be an interface"); + + var factory = ServiceLoader.load(spi.getProviderFactoryClass()).findFirst().orElse(null); + assertNotNull(factory, "failed to read factory with service loader"); + assertEquals(MetricsStatsFactoryImpl.class, factory.getClass(), "factory.class"); + assertEquals("default", factory.getId(), "factory.id"); + } +} diff --git a/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java b/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java new file mode 100644 index 0000000..7e46b8e --- /dev/null +++ b/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java @@ -0,0 +1,225 @@ +package io.kokuwa.keycloak.metrics.stats; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.time.Duration; +import java.util.Map; +import java.util.UUID; +import java.util.logging.Level; +import java.util.stream.Stream; + +import org.hibernate.exception.SQLGrammarException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.keycloak.models.ClientModel; +import org.keycloak.models.ClientProvider; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RealmProvider; +import org.keycloak.models.UserProvider; +import org.keycloak.models.UserSessionProvider; +import org.mockito.Mock; + +import io.kokuwa.keycloak.metrics.junit.AbstractMockitoTest; +import io.micrometer.core.instrument.Gauge; +import io.micrometer.core.instrument.Metrics; + +/** + * Test for {@link MetricsStatsTask} with Mockito. + * + * @author Stephan Schnabel + */ +@DisplayName("metrics: task") +public class MetricsStatsTaskTest extends AbstractMockitoTest { + + @Mock + KeycloakSession session; + @Mock + RealmProvider realmProvider; + @Mock + UserProvider userProvider; + @Mock + UserSessionProvider sessionProvider; + @Mock + ClientProvider clientProvider; + + @BeforeEach + void setup() { + when(session.realms()).thenReturn(realmProvider); + } + + @DisplayName("catch - nullpointer") + @Test + void catchNPE() { + when(session.realms()).thenThrow(NullPointerException.class); + task().run(session); + assertLog(Level.SEVERE, "Failed to scrape stats."); + } + + @DisplayName("catch - database") + @Test + void catchDatabase() { + when(session.realms()).thenThrow(SQLGrammarException.class); + task().run(session); + assertLog(Level.INFO, "Metrics status task skipped, database not ready."); + } + + @DisplayName("log - debug") + @Test + void logDebug() { + when(realmProvider.getRealmsStream()).thenReturn(Stream.of()); + task(Duration.ofMillis(300), Duration.ofMillis(100), Duration.ofMillis(200)).run(session); + assertLog(Level.FINE, "Finished scrapping keycloak stats in {0}."); + } + + @DisplayName("log - info") + @Test + void logInfo() { + when(realmProvider.getRealmsStream()).thenReturn(Stream.of()); + task(Duration.ofMillis(300), Duration.ZERO, Duration.ofMillis(200)).run(session); + assertLog(Level.INFO, "Finished scrapping keycloak stats in {0}."); + } + + @DisplayName("log - warn") + @Test + void logWarn() { + when(realmProvider.getRealmsStream()).thenReturn(Stream.of()); + task(Duration.ofMillis(300), Duration.ofMillis(100), Duration.ZERO).run(session); + assertLog(Level.WARNING, "Finished scrapping keycloak stats in {0}, consider to increase interval."); + } + + @DisplayName("log - error") + @Test + void logError() { + when(realmProvider.getRealmsStream()).thenReturn(Stream.of()); + task(Duration.ZERO, Duration.ofMillis(100), Duration.ofMillis(200)).run(session); + assertLog(Level.SEVERE, "Finished scrapping keycloak stats in {0}, consider to increase interval."); + } + + @DisplayName("scrape") + @Test + void scrape() { + + var realm = UUID.randomUUID().toString(); + var realmModel = mock(RealmModel.class); + var client1 = UUID.randomUUID().toString(); + var client1Id = UUID.randomUUID().toString(); + var client1Model = mock(ClientModel.class); + var client2 = UUID.randomUUID().toString(); + var client2Id = UUID.randomUUID().toString(); + var client2Model = mock(ClientModel.class); + when(realmModel.getName()).thenReturn(realm); + when(realmModel.getClientsStream()).then(i -> Stream.of(client1Model, client2Model)); + when(client1Model.getId()).thenReturn(client1Id); + when(client1Model.getClientId()).thenReturn(client1); + when(client2Model.getId()).thenReturn(client2Id); + when(client2Model.getClientId()).thenReturn(client2); + + when(session.clients()).thenReturn(clientProvider); + when(session.users()).thenReturn(userProvider); + when(session.sessions()).thenReturn(sessionProvider); + when(realmProvider.getRealmsStream()).then(i -> Stream.of(realmModel)); + + // empty realm + + when(userProvider.getUsersCount(realmModel)).thenReturn(0); + when(clientProvider.getClientsCount(realmModel)).thenReturn(0L); + when(sessionProvider.getOfflineSessionsCount(realmModel, client1Model)).thenReturn(0L); + when(sessionProvider.getOfflineSessionsCount(realmModel, client2Model)).thenReturn(0L); + when(sessionProvider.getActiveUserSessions(realmModel, client1Model)).thenReturn(0L); + when(sessionProvider.getActiveUserSessions(realmModel, client2Model)).thenReturn(0L); + when(sessionProvider.getActiveClientSessionStats(realmModel, false)).thenReturn(Map.of()); + task().run(session); + assertUsersCount(realmModel, 0); + assertClientsCount(realmModel, 0); + assertOfflineSessions(realmModel, client1Model, 0); + assertOfflineSessions(realmModel, client2Model, 0); + assertActiveUserSessions(realmModel, client1Model, 0); + assertActiveUserSessions(realmModel, client2Model, 0); + assertActiveClientSessions(realmModel, client1Model, 0); + assertActiveClientSessions(realmModel, client2Model, 0); + + // initial values + + when(userProvider.getUsersCount(realmModel)).thenReturn(10); + when(clientProvider.getClientsCount(realmModel)).thenReturn(20L); + when(sessionProvider.getOfflineSessionsCount(realmModel, client1Model)).thenReturn(0L); + when(sessionProvider.getOfflineSessionsCount(realmModel, client2Model)).thenReturn(1L); + when(sessionProvider.getActiveUserSessions(realmModel, client1Model)).thenReturn(2L); + when(sessionProvider.getActiveUserSessions(realmModel, client2Model)).thenReturn(3L); + when(sessionProvider.getActiveClientSessionStats(realmModel, false)) + .thenReturn(Map.of(client1Id, 5L, client2Id, 0L)); + task().run(session); + assertUsersCount(realmModel, 10); + assertClientsCount(realmModel, 20); + assertOfflineSessions(realmModel, client1Model, 0); + assertOfflineSessions(realmModel, client2Model, 1); + assertActiveUserSessions(realmModel, client1Model, 2); + assertActiveUserSessions(realmModel, client2Model, 3); + assertActiveClientSessions(realmModel, client1Model, 5); + assertActiveClientSessions(realmModel, client2Model, 0); + + // updated values + + when(userProvider.getUsersCount(realmModel)).thenReturn(11); + when(clientProvider.getClientsCount(realmModel)).thenReturn(19L); + when(sessionProvider.getOfflineSessionsCount(realmModel, client1Model)).thenReturn(3L); + when(sessionProvider.getOfflineSessionsCount(realmModel, client2Model)).thenReturn(2L); + when(sessionProvider.getActiveUserSessions(realmModel, client1Model)).thenReturn(1L); + when(sessionProvider.getActiveUserSessions(realmModel, client2Model)).thenReturn(0L); + when(sessionProvider.getActiveClientSessionStats(realmModel, false)) + .thenReturn(Map.of(client1Id, 4L, client2Id, 3L)); + task().run(session); + assertUsersCount(realmModel, 11); + assertClientsCount(realmModel, 19); + assertOfflineSessions(realmModel, client1Model, 3); + assertOfflineSessions(realmModel, client2Model, 2); + assertActiveUserSessions(realmModel, client1Model, 1); + assertActiveUserSessions(realmModel, client2Model, 0); + assertActiveClientSessions(realmModel, client1Model, 4); + assertActiveClientSessions(realmModel, client2Model, 3); + } + + private MetricsStatsTask task() { + return task(Duration.ofMillis(300), Duration.ofMillis(100), Duration.ofMillis(200)); + } + + private MetricsStatsTask task(Duration interval, Duration infoThreshold, Duration warnThreshold) { + return new MetricsStatsTask(interval, infoThreshold, warnThreshold); + } + + private static void assertUsersCount(RealmModel realm, int count) { + assertGauge("keycloak_users", realm, null, count); + } + + private static void assertClientsCount(RealmModel realm, int count) { + assertGauge("keycloak_clients", realm, null, count); + } + + private static void assertActiveClientSessions(RealmModel realm, ClientModel client, int count) { + assertGauge("keycloak_active_client_sessions", realm, client, count); + } + + private static void assertActiveUserSessions(RealmModel realm, ClientModel client, int count) { + assertGauge("keycloak_active_user_sessions", realm, client, count); + } + + private static void assertOfflineSessions(RealmModel realm, ClientModel client, int count) { + assertGauge("keycloak_offline_sessions", realm, client, count); + } + + private static void assertGauge(String name, RealmModel realm, ClientModel client, int count) { + var gauges = Metrics.globalRegistry.getMeters().stream() + .filter(Gauge.class::isInstance) + .filter(gauge -> gauge.getId().getName().equals(name)) + .filter(gauge -> gauge.getId().getTag("realm").equals(realm.getName())) + .filter(gauge -> client == null || gauge.getId().getTag("client").equals(client.getClientId())) + .map(Gauge.class::cast) + .toList(); + assertEquals(1, gauges.size()); + assertEquals(count, gauges.get(0).value()); + } +} From 131b33f31e9516509d7d05b38dc3e2dc3c66d038 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Tue, 2 May 2023 10:09:59 +0200 Subject: [PATCH 13/93] Do not add metrics for clients which never had a session (#39) --- .../metrics/stats/MetricsStatsTask.java | 18 +++++++---- .../metrics/stats/MetricsStatsTaskTest.java | 32 +++++++++++-------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java index eabfe2f..0a3c57c 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java @@ -68,20 +68,24 @@ public class MetricsStatsTask implements Provider, ScheduledTask { private void scrape(KeycloakSession session) { session.realms().getRealmsStream().forEach(realm -> { var tagRealm = Tag.of("realm", realm.getName()); - gauge("keycloak_users", Set.of(tagRealm), session.users().getUsersCount(realm)); - gauge("keycloak_clients", Set.of(tagRealm), session.clients().getClientsCount(realm)); + gauge("keycloak_users", Set.of(tagRealm), session.users().getUsersCount(realm), true); + gauge("keycloak_clients", Set.of(tagRealm), session.clients().getClientsCount(realm), true); var sessions = session.sessions(); var activeSessions = sessions.getActiveClientSessionStats(realm, false); realm.getClientsStream().forEach(client -> { var tags = Set.of(tagRealm, Tag.of("client", client.getClientId())); - gauge("keycloak_offline_sessions", tags, sessions.getOfflineSessionsCount(realm, client)); - gauge("keycloak_active_user_sessions", tags, sessions.getActiveUserSessions(realm, client)); - gauge("keycloak_active_client_sessions", tags, activeSessions.getOrDefault(client.getId(), 0L)); + gauge("keycloak_offline_sessions", tags, sessions.getOfflineSessionsCount(realm, client), false); + gauge("keycloak_active_user_sessions", tags, sessions.getActiveUserSessions(realm, client), false); + gauge("keycloak_active_client_sessions", tags, activeSessions.getOrDefault(client.getId(), 0L), false); }); }); } - private void gauge(String name, Set tags, long value) { - values.computeIfAbsent(name + tags, s -> Metrics.gauge(name, tags, new AtomicLong())).set(value); + private void gauge(String name, Set tags, long value, boolean force) { + var key = name + tags; + if (!force && value == 0 && !values.containsKey(key)) { + return; + } + values.computeIfAbsent(key, s -> Metrics.gauge(name, tags, new AtomicLong())).set(value); } } diff --git a/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java b/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java index 7e46b8e..63201ce 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java @@ -135,12 +135,12 @@ public class MetricsStatsTaskTest extends AbstractMockitoTest { task().run(session); assertUsersCount(realmModel, 0); assertClientsCount(realmModel, 0); - assertOfflineSessions(realmModel, client1Model, 0); - assertOfflineSessions(realmModel, client2Model, 0); - assertActiveUserSessions(realmModel, client1Model, 0); - assertActiveUserSessions(realmModel, client2Model, 0); - assertActiveClientSessions(realmModel, client1Model, 0); - assertActiveClientSessions(realmModel, client2Model, 0); + assertOfflineSessions(realmModel, client1Model, null); + assertOfflineSessions(realmModel, client2Model, null); + assertActiveUserSessions(realmModel, client1Model, null); + assertActiveUserSessions(realmModel, client2Model, null); + assertActiveClientSessions(realmModel, client1Model, null); + assertActiveClientSessions(realmModel, client2Model, null); // initial values @@ -155,12 +155,12 @@ public class MetricsStatsTaskTest extends AbstractMockitoTest { task().run(session); assertUsersCount(realmModel, 10); assertClientsCount(realmModel, 20); - assertOfflineSessions(realmModel, client1Model, 0); + assertOfflineSessions(realmModel, client1Model, null); assertOfflineSessions(realmModel, client2Model, 1); assertActiveUserSessions(realmModel, client1Model, 2); assertActiveUserSessions(realmModel, client2Model, 3); assertActiveClientSessions(realmModel, client1Model, 5); - assertActiveClientSessions(realmModel, client2Model, 0); + assertActiveClientSessions(realmModel, client2Model, null); // updated values @@ -199,19 +199,19 @@ public class MetricsStatsTaskTest extends AbstractMockitoTest { assertGauge("keycloak_clients", realm, null, count); } - private static void assertActiveClientSessions(RealmModel realm, ClientModel client, int count) { + private static void assertActiveClientSessions(RealmModel realm, ClientModel client, Integer count) { assertGauge("keycloak_active_client_sessions", realm, client, count); } - private static void assertActiveUserSessions(RealmModel realm, ClientModel client, int count) { + private static void assertActiveUserSessions(RealmModel realm, ClientModel client, Integer count) { assertGauge("keycloak_active_user_sessions", realm, client, count); } - private static void assertOfflineSessions(RealmModel realm, ClientModel client, int count) { + private static void assertOfflineSessions(RealmModel realm, ClientModel client, Integer count) { assertGauge("keycloak_offline_sessions", realm, client, count); } - private static void assertGauge(String name, RealmModel realm, ClientModel client, int count) { + private static void assertGauge(String name, RealmModel realm, ClientModel client, Integer count) { var gauges = Metrics.globalRegistry.getMeters().stream() .filter(Gauge.class::isInstance) .filter(gauge -> gauge.getId().getName().equals(name)) @@ -219,7 +219,11 @@ public class MetricsStatsTaskTest extends AbstractMockitoTest { .filter(gauge -> client == null || gauge.getId().getTag("client").equals(client.getClientId())) .map(Gauge.class::cast) .toList(); - assertEquals(1, gauges.size()); - assertEquals(count, gauges.get(0).value()); + if (count == null) { + assertEquals(0, gauges.size()); + } else { + assertEquals(1, gauges.size()); + assertEquals(count.doubleValue(), gauges.get(0).value()); + } } } From f005be46ccfa238c006963350eec1671309f826e Mon Sep 17 00:00:00 2001 From: "kokuwa.io Bot" Date: Tue, 2 May 2023 08:32:42 +0000 Subject: [PATCH 14/93] [maven-release-plugin] prepare release 1.0.0 [no ci] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3a77f1a..2fb36fe 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.kokuwa.keycloak keycloak-event-metrics - 1.0.0-SNAPSHOT + 1.0.0 Keycloak Metrics Provides metrics for Keycloak user/admin events @@ -36,7 +36,7 @@ https://github.com/kokuwaio/keycloak-event-metrics scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git - HEAD + 1.0.0 github From 29b573f2f7908d4de982705f8f7eb7da408cdf58 Mon Sep 17 00:00:00 2001 From: "kokuwa.io Bot" Date: Tue, 2 May 2023 08:32:45 +0000 Subject: [PATCH 15/93] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 2fb36fe..929a53f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.kokuwa.keycloak keycloak-event-metrics - 1.0.0 + 1.0.1-SNAPSHOT Keycloak Metrics Provides metrics for Keycloak user/admin events @@ -36,7 +36,7 @@ https://github.com/kokuwaio/keycloak-event-metrics scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git - 1.0.0 + HEAD github From a3784fe1f5b47abe9d002d1fed4f229e5717eded Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Mon, 3 Jul 2023 09:50:21 +0200 Subject: [PATCH 16/93] Migrate to kokuwa parent --- .github/CODEOWNERS | 2 - .github/dependabot.yml | 16 +- .github/settings.xml | 16 + .github/workflows/build.yaml | 31 ++ .github/workflows/ci.yaml | 87 ----- .github/workflows/dependabot.yaml | 17 - .github/workflows/pr.yaml | 59 +++ .github/workflows/release.yaml | 10 +- .gitignore | 5 + README.md | 4 +- pom.xml | 350 ++++-------------- .../metrics/stats/MetricsStatsTask.java | 10 +- 12 files changed, 193 insertions(+), 414 deletions(-) create mode 100644 .github/settings.xml create mode 100644 .github/workflows/build.yaml delete mode 100644 .github/workflows/ci.yaml delete mode 100644 .github/workflows/dependabot.yaml create mode 100644 .github/workflows/pr.yaml create mode 100644 .gitignore diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 164cbad..3f0ccf3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,2 @@ # https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax * @sschnabe @rpahli @fabian-schlegel @jschwarze @wistefan @monotek -.github/workflows/* @kokuwaio-bot -pom.xml @kokuwaio-bot diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 04d2ce6..415bfca 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,21 +2,13 @@ version: 2 updates: - package-ecosystem: maven directory: / - open-pull-requests-limit: 20 schedule: - interval: monthly - day: monday - # github parses time without quotes to int - # yamllint disable-line rule:quoted-strings - time: "09:00" - timezone: Europe/Berlin + interval: daily + allow: + - dependency-name: io.kokuwa.maven:maven-parent + - dependency-name: org.keycloak:keycloak-quarkus-server - package-ecosystem: github-actions directory: / - open-pull-requests-limit: 10 schedule: interval: monthly day: monday - # github parses time without quotes to int - # yamllint disable-line rule:quoted-strings - time: "09:00" - timezone: Europe/Berlin diff --git a/.github/settings.xml b/.github/settings.xml new file mode 100644 index 0000000..44fd9ea --- /dev/null +++ b/.github/settings.xml @@ -0,0 +1,16 @@ + + + + + + sonatype-nexus + ${env.SERVER_USERNAME} + ${env.SERVER_PASSWORD} + + + github.com + nope + ${env.GIT_ACTION_TOKEN} + + + diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..8ad3f78 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,31 @@ +name: Build + +on: + push: + branches: [main] + +jobs: + + build: + runs-on: ubuntu-latest + env: + MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.github/settings.xml + steps: + - run: git config --global user.name "${{ vars.KOKUWA_IO_BOT_NAME }}" + - run: git config --global user.email "${{ vars.KOKUWA_IO_BOT_EMAIL }}" + - uses: actions/checkout@v3 + with: + token: ${{ secrets.GIT_ACTION_TOKEN }} + - uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 17 + cache: maven + - run: mvn $MAVEN_ARGS dependency:go-offline + - run: mvn $MAVEN_ARGS deploy + env: + SERVER_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }} + SERVER_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} + - run: mvn $MAVEN_ARGS site-deploy + env: + GIT_ACTION_TOKEN: ${{ secrets.GIT_ACTION_TOKEN }} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml deleted file mode 100644 index a1394ca..0000000 --- a/.github/workflows/ci.yaml +++ /dev/null @@ -1,87 +0,0 @@ -name: CI - -on: - push: - branches: [main] - pull_request: {} - -jobs: - - yaml: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: ibiqlik/action-yamllint@v3 - with: - format: colored - strict: true - - markdown: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: avto-dev/markdown-lint@v1 - with: - args: /github/workspace - - javadoc: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 17 - cache: maven - - run: mvn -B -ntp javadoc:javadoc-no-fork -Ddoclint=all - - checkstyle: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 17 - cache: maven - - run: mvn -B -ntp checkstyle:check - - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 17 - cache: maven - server-id: sonatype-nexus - server-username: SERVER_USERNAME - server-password: SERVER_PASSWORD - - run: mvn -B -ntp verify -Dcheckstyle.skip -Dmaven.test.redirectTestOutputToFile=false - if: ${{ github.ref != 'refs/heads/main' }} - - run: mvn -B -ntp deploy -Dcheckstyle.skip -Dmaven.test.redirectTestOutputToFile=false - if: ${{ github.ref == 'refs/heads/main' }} - env: - SERVER_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }} - SERVER_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} - - versions: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - version: - - 21.0.0 - - 21.0.1 - - 21.0.2 - - 21.1.0 - - 21.1.1 - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 17 - cache: maven - - run: mvn -B -ntp verify -Dcheckstyle.skip -Dmaven.test.redirectTestOutputToFile=false -Dversion.org.keycloak=${{ matrix.version }} diff --git a/.github/workflows/dependabot.yaml b/.github/workflows/dependabot.yaml deleted file mode 100644 index ed63eca..0000000 --- a/.github/workflows/dependabot.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: Dependabot - -on: pull_request_target - -jobs: - auto-merge: - runs-on: ubuntu-latest - if: ${{ github.actor == 'dependabot[bot]' }} - steps: - - run: gh pr review --approve "$PR_URL" - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GITHUB_TOKEN: ${{ secrets.GIT_ACTION_TOKEN }} - - run: gh pr merge --auto --squash "$PR_URL" - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GITHUB_TOKEN: ${{ secrets.GIT_ACTION_TOKEN }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 0000000..54c2bba --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,59 @@ +name: PullRequest + +on: pull_request + +env: + MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress -Dmaven.test.redirectTestOutputToFile=false + +jobs: + + yaml: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: ibiqlik/action-yamllint@v3 + with: + format: colored + strict: true + + markdown: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: avto-dev/markdown-lint@v1 + with: + args: /github/workspace + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 17 + cache: maven + - run: mvn $MAVEN_ARGS dependency:go-offline + - run: mvn $MAVEN_ARGS verify + - run: mvn $MAVEN_ARGS site + - uses: actions/upload-artifact@v3 + if: always() + with: + path: target/site + + versions: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + version: + - 21.0.2 + - 21.1.1 + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 17 + cache: maven + - run: mvn $MAVEN_ARGS verify -Dcheck.skip -Dversion.org.keycloak=${{ matrix.version }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8329bb7..4c719f1 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -5,7 +5,11 @@ on: workflow_dispatch jobs: build: runs-on: ubuntu-latest + env: + MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.github/settings.xml steps: + - run: git config --global user.name "${{ vars.KOKUWA_IO_BOT_NAME }}" + - run: git config --global user.email "${{ vars.KOKUWA_IO_BOT_EMAIL }}" - uses: actions/checkout@v3 with: token: ${{ secrets.GIT_ACTION_TOKEN }} @@ -25,9 +29,11 @@ jobs: server-password: SERVER_PASSWORD gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} gpg-passphrase: GPG_PASSPHRASE - - run: mvn -B -ntp release:prepare - - run: mvn -B -ntp release:perform + - run: mvn $MAVEN_ARGS dependency:go-offline + - run: mvn $MAVEN_ARGS release:prepare -Darguments="$MAVEN_ARGS" + - run: mvn $MAVEN_ARGS release:perform -Darguments="$MAVEN_ARGS" env: SERVER_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }} SERVER_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} + GIT_ACTION_TOKEN: ${{ secrets.GIT_ACTION_TOKEN }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1939404 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# do not include developer stuff here, use `git config --global core.excludesFile ~/.gitignore` for your setup + +target +pom.xml.releaseBackup +release.properties diff --git a/README.md b/README.md index f9f4236..e18c360 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Keycloak Metrics -Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [20-21](.github/workflows/ci.yaml#L74-L77). +Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [21](.github/workflows/pr.yaml#L49-L51). [![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/kokuwaio/keycloak-event-metrics.svg?label=License)](http://www.apache.org/licenses/) [![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) -[![CI](https://img.shields.io/github/actions/workflow/status/kokuwaio/keycloak-event-metrics/ci.yaml?branch=main&label=CI)](https://github.com/kokuwaio/keycloak-event-metrics/actions/workflows/ci.yaml?query=branch%3Amain) +[![Build](https://img.shields.io/github/actions/workflow/status/kokuwaio/keycloak-event-metrics/build.yaml?label=Build)](https://github.com/kokuwaio/keycloak-event-metrics/actions/workflows/build.yaml) ## Why? diff --git a/pom.xml b/pom.xml index 929a53f..5fe8e38 100644 --- a/pom.xml +++ b/pom.xml @@ -2,6 +2,13 @@ 4.0.0 + + io.kokuwa.maven + maven-parent + 0.6.10 + + + io.kokuwa.keycloak keycloak-event-metrics 1.0.1-SNAPSHOT @@ -16,19 +23,21 @@ - Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0 + Apache-2.0 + https://www.apache.org/licenses/LICENSE-2.0.txt + repo - stephanschnabel + sschnabe Stephan Schnabel https://github.com/sschnabe stephan@grayc.de GrayC GmbH https://grayc.de + Europe/Berlin @@ -46,16 +55,6 @@ github https://github.com/kokuwaio/keycloak-event-metrics/actions - - - sonatype-nexus - https://oss.sonatype.org/content/repositories/snapshots - - - sonatype-nexus - https://oss.sonatype.org/service/local/staging/deploy/maven2 - - @@ -63,73 +62,27 @@ - UTF-8 - 17 17 - true - true - true - true - - - 3.2.2 - 3.2.0 - 3.11.0 - 3.5.0 - 3.1.1 - 3.0.1 - 3.1.1 - 3.3.0 - 1.0.0 - 3.0.0 - 3.3.1 - 3.2.1 - 3.0.0 - 1.2.0 - 1.6.13 - 10.10.0 - 0.5.6 - - - 21.1.1 - 5.3.1 - 1.18.0 + 1.18.3 - - org.keycloak - keycloak-parent + keycloak-quarkus-server ${version.org.keycloak} pom import - - - - org.mockito - mockito-junit-jupiter - ${version.org.mockito} - - - org.testcontainers - testcontainers-bom - ${version.org.testcontainers} - pom - import - - @@ -152,27 +105,61 @@ org.keycloak - keycloak-quarkus-server - provided + keycloak-admin-client + test - - com.openshift - openshift-restclient-java - - - org.keycloak - keycloak-admin-ui + + org.glassfish.jaxb + jaxb-runtime - org.keycloak - keycloak-account-ui + org.jboss.resteasy + resteasy-multipart-provider + + + + + + + org.jboss.logging + jboss-logging + provided + + + org.hibernate + hibernate-core + provided + + + javax.xml.bind + jaxb-api + + + org.glassfish.jaxb + jaxb-runtime + + + org.hibernate.common + hibernate-commons-annotations + + + org.jboss + jandex + + + antlr + antlr + + + com.fasterxml + classmate - org.keycloak - keycloak-admin-client - test + io.micrometer + micrometer-core + provided @@ -183,13 +170,7 @@ org.testcontainers - junit-jupiter - test - - - org.wildfly.client - wildfly-client-config - 1.0.1.Final + testcontainers test @@ -202,151 +183,8 @@ true - - - - org.apache.maven.plugins - maven-checkstyle-plugin - ${version.org.apache.maven.plugins.checkstyle} - - checkstyle.xml - checkstyle-suppression.xml - true - - - - com.puppycrawl.tools - checkstyle - ${version.com.puppycrawl.tools.checkstyle} - - - io.kokuwa - maven-parent - ${version.io.kokuwa.checkstyle} - zip - checkstyle - - - - - org.apache.maven.plugins - maven-clean-plugin - ${version.org.apache.maven.plugins.clean} - - - org.apache.maven.plugins - maven-compiler-plugin - ${version.org.apache.maven.plugins.compiler} - - - org.apache.maven.plugins - maven-dependency-plugin - ${version.org.apache.maven.plugins.dependency} - - - org.apache.maven.plugins - maven-deploy-plugin - ${version.org.apache.maven.plugins.deploy} - - - org.apache.maven.plugins - maven-failsafe-plugin - ${version.org.apache.maven.plugins.surefire} - - true - ${maven.test.redirectTestOutputToFile} - - - - org.apache.maven.plugins - maven-gpg-plugin - ${version.org.apache.maven.plugins.gpg} - - - org.apache.maven.plugins - maven-install-plugin - ${version.org.apache.maven.plugins.install} - - - org.apache.maven.plugins - maven-jar-plugin - ${version.org.apache.maven.plugins.jar} - - - org.apache.maven.plugins - maven-javadoc-plugin - ${version.org.apache.maven.plugins.jar} - - - org.apache.maven.plugins - maven-release-plugin - ${version.org.apache.maven.plugins.release} - - @{project.version} - release - true - true - @{prefix} prepare release @{releaseLabel} [no ci] - - - - org.apache.maven.plugins - maven-source-plugin - ${version.org.apache.maven.plugins.source} - - - org.apache.maven.plugins - maven-resources-plugin - ${version.org.apache.maven.plugins.resources} - - UTF-8 - - - - org.apache.maven.plugins - maven-surefire-plugin - ${version.org.apache.maven.plugins.surefire} - - - org.codehaus.mojo - tidy-maven-plugin - ${version.org.codehaus.mojo.tidy} - - - org.sonatype.plugins - nexus-staging-maven-plugin - ${version.org.sonatype.plugins.nexus-staging} - - - - - - org.codehaus.mojo - tidy-maven-plugin - - - - check - - - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - - - check - - - - - org.apache.maven.plugins @@ -363,66 +201,4 @@ - - - - release - - - - - - org.apache.maven.plugins - maven-source-plugin - - - - jar-no-fork - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - - jar - - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - - - - sign - - - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - true - - sonatype-nexus - https://oss.sonatype.org/ - true - - - - - - - diff --git a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java index 0a3c57c..db75da8 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java @@ -41,12 +41,11 @@ public class MetricsStatsTask implements Provider, ScheduledTask { try { scrape(session); + } catch (org.hibernate.exception.SQLGrammarException e) { + log.infov("Metrics status task skipped, database not ready."); + return; } catch (Exception e) { - if (e instanceof org.hibernate.exception.SQLGrammarException) { - log.infov("Metrics status task skipped, database not ready."); - } else { - log.errorv(e, "Failed to scrape stats."); - } + log.errorv(e, "Failed to scrape stats."); return; } @@ -67,6 +66,7 @@ public class MetricsStatsTask implements Provider, ScheduledTask { private void scrape(KeycloakSession session) { session.realms().getRealmsStream().forEach(realm -> { + log.tracev("Scrape for realm {0}.", realm.getName()); var tagRealm = Tag.of("realm", realm.getName()); gauge("keycloak_users", Set.of(tagRealm), session.users().getUsersCount(realm), true); gauge("keycloak_clients", Set.of(tagRealm), session.clients().getClientsCount(realm), true); From 1800ef9abfa0ed741194bc1fea6771522db98380 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jul 2023 07:59:27 +0000 Subject: [PATCH 17/93] Bump keycloak-quarkus-server from 21.1.1 to 21.1.2 (#52) * Bump keycloak-quarkus-server from 21.1.1 to 21.1.2 Bumps keycloak-quarkus-server from 21.1.1 to 21.1.2. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump build too --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stephan Schnabel --- .github/workflows/pr.yaml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 54c2bba..9d30847 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -48,7 +48,7 @@ jobs: matrix: version: - 21.0.2 - - 21.1.1 + - 21.1.2 steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 diff --git a/pom.xml b/pom.xml index 5fe8e38..39476b9 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 21.1.1 + 21.1.2 1.18.3 From ee01b2562b86e2c72e0778b641204d126d402840 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Jul 2023 14:54:23 +0000 Subject: [PATCH 18/93] Bump keycloak-quarkus-server from 21.1.2 to 22.0.0 Bumps keycloak-quarkus-server from 21.1.2 to 22.0.0. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 39476b9..7e7bc8d 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 21.1.2 + 22.0.0 1.18.3 From 398239d79cac61e4b503807ea3f6269c00308bee Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Wed, 12 Jul 2023 11:19:08 +0200 Subject: [PATCH 19/93] Migrate from `javax`to `jakarta` --- .../io/kokuwa/keycloak/metrics/junit/KeycloakClient.java | 6 +++--- .../kokuwa/keycloak/metrics/junit/KeycloakExtension.java | 4 ++-- .../kokuwa/keycloak/metrics/junit/PrometheusClient.java | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java index 6d48781..098516d 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java @@ -6,9 +6,6 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import javax.ws.rs.NotAuthorizedException; -import javax.ws.rs.core.MultivaluedHashMap; - import org.keycloak.OAuth2Constants; import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.token.TokenService; @@ -17,6 +14,9 @@ import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.UserRepresentation; +import jakarta.ws.rs.NotAuthorizedException; +import jakarta.ws.rs.core.MultivaluedHashMap; + /** * Client for keycloak. * diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java index b5d7775..729bd9b 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java @@ -7,8 +7,6 @@ import java.time.Duration; import java.util.Properties; import java.util.Set; -import javax.ws.rs.client.ClientBuilder; - import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; @@ -19,6 +17,8 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.MountableFile; +import jakarta.ws.rs.client.ClientBuilder; + /** * JUnit extension to start keycloak. * diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/PrometheusClient.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/PrometheusClient.java index 0ce08bd..94f17e8 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/PrometheusClient.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/PrometheusClient.java @@ -1,9 +1,9 @@ package io.kokuwa.keycloak.metrics.junit; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.MediaType; /** * JAX-RS client for prometheus endpoint. From ed7b7ef82a0d24745ad73b2567c7622110703b67 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Wed, 12 Jul 2023 11:19:32 +0200 Subject: [PATCH 20/93] Migrate from `org.hibernate` to `org.hibernate.orm` --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7e7bc8d..c2fbcdb 100644 --- a/pom.xml +++ b/pom.xml @@ -126,7 +126,7 @@ provided - org.hibernate + org.hibernate.orm hibernate-core provided From 8314d8fab05fadc8007ca857c02e63bc68a8cfe7 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Wed, 12 Jul 2023 11:20:22 +0200 Subject: [PATCH 21/93] Add testing for multiple version from one base version --- .github/workflows/pr.yaml | 3 ++- README.md | 2 +- pom.xml | 1 + src/test/resources/test.properties | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 9d30847..094ca78 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -49,6 +49,7 @@ jobs: version: - 21.0.2 - 21.1.2 + - 22.0.0 steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 @@ -56,4 +57,4 @@ jobs: distribution: temurin java-version: 17 cache: maven - - run: mvn $MAVEN_ARGS verify -Dcheck.skip -Dversion.org.keycloak=${{ matrix.version }} + - run: mvn $MAVEN_ARGS verify -Dcheck.skip -Dversion.org.keycloak.test=${{ matrix.version }} diff --git a/README.md b/README.md index e18c360..cef8079 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Keycloak Metrics -Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [21](.github/workflows/pr.yaml#L49-L51). +Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [21-22](.github/workflows/pr.yaml#L49-L51). [![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/kokuwaio/keycloak-event-metrics.svg?label=License)](http://www.apache.org/licenses/) [![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) diff --git a/pom.xml b/pom.xml index c2fbcdb..ba4e39c 100644 --- a/pom.xml +++ b/pom.xml @@ -70,6 +70,7 @@ 22.0.0 + ${version.org.keycloak} 1.18.3 diff --git a/src/test/resources/test.properties b/src/test/resources/test.properties index d66d19f..9d19498 100644 --- a/src/test/resources/test.properties +++ b/src/test/resources/test.properties @@ -1,3 +1,3 @@ -version=${version.org.keycloak} +version=${version.org.keycloak.test} timeout=PT5m jar=${project.build.directory}/${project.build.finalName}.jar From 3b895500a5847c9bf98af0301913a06a013968b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jul 2023 19:47:14 +0200 Subject: [PATCH 22/93] Bump keycloak-quarkus-server from 22.0.0 to 22.0.1 (#54) Bumps keycloak-quarkus-server from 22.0.0 to 22.0.1. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ba4e39c..f4b98b3 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 22.0.0 + 22.0.1 ${version.org.keycloak} 1.18.3 From 355ca8cc61c732f78899eb84b65861661b36159f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 31 Aug 2023 17:25:13 +0200 Subject: [PATCH 23/93] Bump io.kokuwa.maven:maven-parent from 0.6.10 to 0.6.12 (#55) Bumps [io.kokuwa.maven:maven-parent](https://github.com/kokuwaio/maven-parent) from 0.6.10 to 0.6.12. - [Commits](https://github.com/kokuwaio/maven-parent/compare/0.6.10...0.6.12) --- updated-dependencies: - dependency-name: io.kokuwa.maven:maven-parent dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f4b98b3..ca59a8a 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.kokuwa.maven maven-parent - 0.6.10 + 0.6.12 From 79fada6ce88a6bae5ac7e8abd6fa838159b08390 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 18:33:54 +0000 Subject: [PATCH 24/93] Bump org.keycloak:keycloak-quarkus-server from 22.0.1 to 22.0.2 (#56) * Bump org.keycloak:keycloak-quarkus-server from 22.0.1 to 22.0.2 Bumps org.keycloak:keycloak-quarkus-server from 22.0.1 to 22.0.2. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Add 22.0.2 to ci --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stephan Schnabel --- .github/workflows/pr.yaml | 2 +- pom.xml | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 094ca78..8a17c98 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -49,7 +49,7 @@ jobs: version: - 21.0.2 - 21.1.2 - - 22.0.0 + - 22.0.2 steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 diff --git a/pom.xml b/pom.xml index ca59a8a..867db42 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 22.0.1 + 22.0.2 ${version.org.keycloak} 1.18.3 @@ -199,6 +199,18 @@ + + + + org.codehaus.mojo + flatten-maven-plugin + + + default + + + + From fab113d91207870fab54702344727fbffc056213 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Sep 2023 11:47:38 +0200 Subject: [PATCH 25/93] Bump org.keycloak:keycloak-quarkus-server from 22.0.2 to 22.0.3 (#57) * Bump org.keycloak:keycloak-quarkus-server from 22.0.2 to 22.0.3 Bumps org.keycloak:keycloak-quarkus-server from 22.0.2 to 22.0.3. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Use java http client because keycloak api in incompatible --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stephan Schnabel --- .github/workflows/pr.yaml | 2 +- pom.xml | 2 +- .../kokuwa/keycloak/metrics/KeycloakIT.java | 11 +-- .../metrics/junit/KeycloakClient.java | 74 ++++++++++++------- .../metrics/junit/KeycloakExtension.java | 2 +- 5 files changed, 56 insertions(+), 35 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 8a17c98..009c366 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -49,7 +49,7 @@ jobs: version: - 21.0.2 - 21.1.2 - - 22.0.2 + - 22.0.3 steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 diff --git a/pom.xml b/pom.xml index 867db42..e8dffba 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 22.0.2 + 22.0.3 ${version.org.keycloak} 1.18.3 diff --git a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java index 4475113..1eaa0b1 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java @@ -3,7 +3,7 @@ package io.kokuwa.keycloak.metrics; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.Instant; @@ -18,6 +18,7 @@ import org.keycloak.events.EventType; import io.kokuwa.keycloak.metrics.junit.KeycloakClient; import io.kokuwa.keycloak.metrics.junit.KeycloakExtension; import io.kokuwa.keycloak.metrics.junit.Prometheus; +import jakarta.ws.rs.NotAuthorizedException; /** * Integration tests with Keycloak. @@ -55,10 +56,10 @@ public class KeycloakIT { var loginErrorBefore1 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName1, clientId1); var loginErrorBefore2 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName2, clientId2); - assertTrue(keycloak.login(clientId1, realmName1, username1, password1)); - assertTrue(keycloak.login(clientId1, realmName1, username1, password1)); - assertTrue(keycloak.login(clientId2, realmName2, username2, password2)); - assertFalse(keycloak.login(clientId2, realmName2, username2, "nope")); + assertDoesNotThrow(() -> keycloak.login(clientId1, realmName1, username1, password1)); + assertDoesNotThrow(() -> keycloak.login(clientId1, realmName1, username1, password1)); + assertDoesNotThrow(() -> keycloak.login(clientId2, realmName2, username2, password2)); + assertThrows(NotAuthorizedException.class, () -> keycloak.login(clientId2, realmName2, username2, "nope")); prometheus.scrap(); var loginAfter = prometheus.userEvent(EventType.LOGIN); diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java index 098516d..9f66fbd 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java @@ -1,7 +1,14 @@ package io.kokuwa.keycloak.metrics.junit; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse.BodyHandlers; import java.util.List; import java.util.Map; import java.util.UUID; @@ -9,12 +16,16 @@ import java.util.UUID; import org.keycloak.OAuth2Constants; import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.token.TokenService; +import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.UserRepresentation; -import jakarta.ws.rs.NotAuthorizedException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MultivaluedHashMap; /** @@ -25,11 +36,18 @@ import jakarta.ws.rs.core.MultivaluedHashMap; public class KeycloakClient { private final Keycloak keycloak; - private final TokenService token; + private final TokenService tokenService; - KeycloakClient(Keycloak keycloak, TokenService token) { + private final ObjectMapper mapper = new ObjectMapper(); + private final HttpClient client = HttpClient.newHttpClient(); + private final String url; + private final String adminToken; + + KeycloakClient(String url, Keycloak keycloak, TokenService tokenService) { this.keycloak = keycloak; - this.token = token; + this.tokenService = tokenService; + this.url = url; + this.adminToken = login("admin-cli", "master", "admin", "password").getToken(); } public void createRealm(String realmName) { @@ -52,18 +70,25 @@ public class KeycloakClient { } public void createUser(String realmName, String username, String password) { - var credential = new CredentialRepresentation(); - credential.setType(CredentialRepresentation.PASSWORD); - credential.setValue(password); - credential.setTemporary(false); - var user = new UserRepresentation(); - user.setEnabled(true); - user.setEmail(username + "@example.org"); - user.setEmailVerified(true); - user.setUsername(username); - user.setCredentials(List.of(credential)); - var response = keycloak.realms().realm(realmName).users().create(user); - assertEquals(201, response.getStatus()); + try { + var response = client.send(HttpRequest.newBuilder() + .uri(URI.create(url + "/admin/realms/" + realmName + "/users")) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + adminToken) + .POST(BodyPublishers.ofString(mapper.writeValueAsString(Map.of( + "enabled", true, + "emailVerified", true, + "email", username + "@example.org", + "username", username, + "credentials", List.of(Map.of( + "type", CredentialRepresentation.PASSWORD, + "value", password, + "temporary", false)))))) + .build(), BodyHandlers.ofString()); + assertEquals(201, response.statusCode(), "Body: " + response.body()); + } catch (IOException | InterruptedException e) { + fail("Failed to create user", e); + } } public void deleteUser(String realmName, String username) { @@ -73,16 +98,11 @@ public class KeycloakClient { .forEach(keycloak.realms().realm(realmName).users()::delete); } - public boolean login(String clientId, String realmName, String username, String password) { - try { - token.grantToken(realmName, new MultivaluedHashMap<>(Map.of( - OAuth2Constants.CLIENT_ID, clientId, - OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD, - OAuth2Constants.USERNAME, username, - OAuth2Constants.PASSWORD, password))); - return true; - } catch (NotAuthorizedException e) { - return false; - } + public AccessTokenResponse login(String clientId, String realmName, String username, String password) { + return tokenService.grantToken(realmName, new MultivaluedHashMap<>(Map.of( + OAuth2Constants.CLIENT_ID, clientId, + OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD, + OAuth2Constants.USERNAME, username, + OAuth2Constants.PASSWORD, password))); } } diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java index 729bd9b..c06c8f3 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java @@ -80,7 +80,7 @@ public class KeycloakExtension implements BeforeAllCallback, ParameterResolver { var target = ClientBuilder.newClient().target(url); var token = Keycloak.getClientProvider().targetProxy(target, TokenService.class); prometheus = new Prometheus(Keycloak.getClientProvider().targetProxy(target, PrometheusClient.class)); - client = new KeycloakClient(keycloak, token); + client = new KeycloakClient(url, keycloak, token); } @Override From 1a9a3b371470bc49ab11c836c2fa82432cf750c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:28:42 +0200 Subject: [PATCH 26/93] Bump actions/checkout from 3 to 4 (#59) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yaml | 2 +- .github/workflows/pr.yaml | 8 ++++---- .github/workflows/release.yaml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8ad3f78..8aba1c5 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -13,7 +13,7 @@ jobs: steps: - run: git config --global user.name "${{ vars.KOKUWA_IO_BOT_NAME }}" - run: git config --global user.email "${{ vars.KOKUWA_IO_BOT_EMAIL }}" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: token: ${{ secrets.GIT_ACTION_TOKEN }} - uses: actions/setup-java@v3 diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 009c366..9e8da2c 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -10,7 +10,7 @@ jobs: yaml: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ibiqlik/action-yamllint@v3 with: format: colored @@ -19,7 +19,7 @@ jobs: markdown: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: avto-dev/markdown-lint@v1 with: args: /github/workspace @@ -27,7 +27,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: temurin @@ -51,7 +51,7 @@ jobs: - 21.1.2 - 22.0.3 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: temurin diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4c719f1..3debf4e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,7 +10,7 @@ jobs: steps: - run: git config --global user.name "${{ vars.KOKUWA_IO_BOT_NAME }}" - run: git config --global user.email "${{ vars.KOKUWA_IO_BOT_EMAIL }}" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: token: ${{ secrets.GIT_ACTION_TOKEN }} - uses: crazy-max/ghaction-import-gpg@v5 From a42447fc285c647d31a6ae8cbe960b44ade27f47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:29:01 +0200 Subject: [PATCH 27/93] Bump crazy-max/ghaction-import-gpg from 5 to 6 (#58) Bumps [crazy-max/ghaction-import-gpg](https://github.com/crazy-max/ghaction-import-gpg) from 5 to 6. - [Release notes](https://github.com/crazy-max/ghaction-import-gpg/releases) - [Commits](https://github.com/crazy-max/ghaction-import-gpg/compare/v5...v6) --- updated-dependencies: - dependency-name: crazy-max/ghaction-import-gpg dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3debf4e..e040ba9 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4 with: token: ${{ secrets.GIT_ACTION_TOKEN }} - - uses: crazy-max/ghaction-import-gpg@v5 + - uses: crazy-max/ghaction-import-gpg@v6 with: gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} passphrase: ${{ secrets.GPG_PASSPHRASE }} From 40edc83dc7ea1da5b24c6252cb6cbc384095c07c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Oct 2023 20:06:36 +0200 Subject: [PATCH 28/93] Bump org.keycloak:keycloak-quarkus-server from 22.0.3 to 22.0.4 (#60) Bumps org.keycloak:keycloak-quarkus-server from 22.0.3 to 22.0.4. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e8dffba..f649721 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 22.0.3 + 22.0.4 ${version.org.keycloak} 1.18.3 From 110c27774f1581daf30d233ff43bdff2f1f35c5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 20:10:07 +0200 Subject: [PATCH 29/93] Bump io.kokuwa.maven:maven-parent from 0.6.12 to 0.6.13 (#61) Bumps [io.kokuwa.maven:maven-parent](https://github.com/kokuwaio/maven-parent) from 0.6.12 to 0.6.13. - [Commits](https://github.com/kokuwaio/maven-parent/compare/0.6.12...0.6.13) --- updated-dependencies: - dependency-name: io.kokuwa.maven:maven-parent dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f649721..def01e3 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.kokuwa.maven maven-parent - 0.6.12 + 0.6.13 From e3cfb12b9900051f21f49a36271df9b26e5c2fcf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 22:22:50 +0200 Subject: [PATCH 30/93] Bump org.keycloak:keycloak-quarkus-server from 22.0.4 to 22.0.5 (#62) Bumps org.keycloak:keycloak-quarkus-server from 22.0.4 to 22.0.5. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index def01e3..0470cf3 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 22.0.4 + 22.0.5 ${version.org.keycloak} 1.18.3 From 19930672f0b8a685121b6ed8c7da30bdd1b00554 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Nov 2023 13:31:22 +0000 Subject: [PATCH 31/93] Bump org.keycloak:keycloak-quarkus-server from 22.0.5 to 23.0.0 (#64) Bumps org.keycloak:keycloak-quarkus-server from 22.0.5 to 23.0.0. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0470cf3..c4c68e2 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 22.0.5 + 23.0.0 ${version.org.keycloak} 1.18.3 @@ -92,6 +92,7 @@ org.keycloak keycloak-core + ${version.org.keycloak.test} provided From 30aaccc056ad3aa31258d5ef0cb53841b507ddc5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:07:46 +0100 Subject: [PATCH 32/93] Bump org.keycloak:keycloak-quarkus-server from 23.0.0 to 23.0.1 (#65) Bumps org.keycloak:keycloak-quarkus-server from 23.0.0 to 23.0.1. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/pr.yaml | 3 ++- README.md | 2 +- pom.xml | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 9e8da2c..6006e83 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -49,7 +49,8 @@ jobs: version: - 21.0.2 - 21.1.2 - - 22.0.3 + - 22.0.5 + - 23.0.1 steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v3 diff --git a/README.md b/README.md index cef8079..0c08e8e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Keycloak Metrics -Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [21-22](.github/workflows/pr.yaml#L49-L51). +Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [21-23](.github/workflows/pr.yaml#L50-L53). [![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/kokuwaio/keycloak-event-metrics.svg?label=License)](http://www.apache.org/licenses/) [![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) diff --git a/pom.xml b/pom.xml index c4c68e2..68a2089 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 23.0.0 + 23.0.1 ${version.org.keycloak} 1.18.3 From f8edc06eb20f4346cfd8afe99eb0c1160b25cec4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Dec 2023 16:40:37 +0100 Subject: [PATCH 33/93] Bump actions/setup-java from 3 to 4 (#66) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yaml | 2 +- .github/workflows/pr.yaml | 4 ++-- .github/workflows/release.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8aba1c5..e87924e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v4 with: token: ${{ secrets.GIT_ACTION_TOKEN }} - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 17 diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 6006e83..b45031c 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 17 @@ -53,7 +53,7 @@ jobs: - 23.0.1 steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 17 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e040ba9..0e5bda9 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -19,7 +19,7 @@ jobs: passphrase: ${{ secrets.GPG_PASSPHRASE }} git_user_signingkey: true git_commit_gpgsign: true - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 17 From 2099257d1240c90be2044e82e354929e49d250f7 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Wed, 13 Dec 2023 20:56:35 +0100 Subject: [PATCH 34/93] Add docu for dashboard, fix #2 (#67) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 0c08e8e..83218e6 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,10 @@ If scrapping takes less than `KC_METRICS_STATS_INFO_THRESHOLD` duration will be ## Installation +### Grafana Dashboard + +Can be found here: [kokuwaio/keycloak keycloak-metrics.json](https://github.com/kokuwaio/keycloak/blob/main/src/test/k3s/dev/grafana/files/dashboards/keycloak-metrics.json) + ### Testcontainers For usage in [Testcontainers](https://www.testcontainers.org/) see [KeycloakExtension.java](src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java#L57-L68) From d95e5997c6c3208e9a7302740a7b90c46cfe3b56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Dec 2023 12:46:03 +0100 Subject: [PATCH 35/93] Bump org.keycloak:keycloak-quarkus-server from 23.0.1 to 23.0.3 (#68) Bumps org.keycloak:keycloak-quarkus-server from 23.0.1 to 23.0.3. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 68a2089..7556ddd 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 23.0.1 + 23.0.3 ${version.org.keycloak} 1.18.3 From a76e28edaa31607705bd723963c489147d9f7f51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Dec 2023 21:55:50 +0100 Subject: [PATCH 36/93] Bump io.kokuwa.maven:maven-parent from 0.6.13 to 0.6.14 (#69) Bumps [io.kokuwa.maven:maven-parent](https://github.com/kokuwaio/maven-parent) from 0.6.13 to 0.6.14. - [Commits](https://github.com/kokuwaio/maven-parent/compare/0.6.13...0.6.14) --- updated-dependencies: - dependency-name: io.kokuwa.maven:maven-parent dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7556ddd..fcc5db1 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.kokuwa.maven maven-parent - 0.6.13 + 0.6.14 From 30f4685751c9d5205fd7bf8a415b8e62ac1deeec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 17:42:54 +0100 Subject: [PATCH 37/93] Bump actions/upload-artifact from 3 to 4 (#70) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/pr.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index b45031c..64e7dcb 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -36,7 +36,7 @@ jobs: - run: mvn $MAVEN_ARGS dependency:go-offline - run: mvn $MAVEN_ARGS verify - run: mvn $MAVEN_ARGS site - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: always() with: path: target/site From f9729181ba1bfe2e4483d03471c1ea64157deb3e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 17:09:06 +0100 Subject: [PATCH 38/93] Bump org.keycloak:keycloak-quarkus-server from 23.0.3 to 23.0.4 (#71) Bumps org.keycloak:keycloak-quarkus-server from 23.0.3 to 23.0.4. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fcc5db1..28840d9 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 23.0.3 + 23.0.4 ${version.org.keycloak} 1.18.3 From 267747f24e2fb056ddc4ecdf54cf781cbf66f60a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 17:34:05 +0100 Subject: [PATCH 39/93] Bump org.keycloak:keycloak-quarkus-server from 23.0.4 to 23.0.5 (#72) Bumps org.keycloak:keycloak-quarkus-server from 23.0.4 to 23.0.5. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 28840d9..7a683be 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 23.0.4 + 23.0.5 ${version.org.keycloak} 1.18.3 From cc6964009583e112f283a0f1ad97df6b18a89492 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Feb 2024 17:01:02 +0100 Subject: [PATCH 40/93] Bump org.keycloak:keycloak-quarkus-server from 23.0.5 to 23.0.6 (#73) Bumps org.keycloak:keycloak-quarkus-server from 23.0.5 to 23.0.6. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7a683be..bf55ab6 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 23.0.5 + 23.0.6 ${version.org.keycloak} 1.18.3 From 6d995a51c9aa8e0a4292f737b2c4d9d51326e3a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Feb 2024 16:02:57 +0100 Subject: [PATCH 41/93] Bump io.kokuwa.maven:maven-parent from 0.6.14 to 0.6.15 (#74) Bumps [io.kokuwa.maven:maven-parent](https://github.com/kokuwaio/maven-parent) from 0.6.14 to 0.6.15. - [Commits](https://github.com/kokuwaio/maven-parent/compare/0.6.14...0.6.15) --- updated-dependencies: - dependency-name: io.kokuwa.maven:maven-parent dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bf55ab6..9db7156 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.kokuwa.maven maven-parent - 0.6.14 + 0.6.15 From fb20a3409442e22aac5f3e57ea8e2e01458c7d80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Feb 2024 16:03:10 +0100 Subject: [PATCH 42/93] Bump org.keycloak:keycloak-quarkus-server from 23.0.6 to 23.0.7 (#75) Bumps org.keycloak:keycloak-quarkus-server from 23.0.6 to 23.0.7. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9db7156..e0ef498 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 23.0.6 + 23.0.7 ${version.org.keycloak} 1.18.3 From f8d1acbc8f6cb1282bd5da398a501635f2841a49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:24:13 +0100 Subject: [PATCH 43/93] Bump org.keycloak:keycloak-quarkus-server from 23.0.7 to 24.0.0 (#78) * Bump org.keycloak:keycloak-quarkus-server from 23.0.7 to 24.0.0 Bumps org.keycloak:keycloak-quarkus-server from 23.0.7 to 24.0.0. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Adjust docs and ci --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stephan Schnabel --- .github/workflows/pr.yaml | 3 ++- README.md | 2 +- pom.xml | 2 +- .../java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 64e7dcb..86076da 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -50,7 +50,8 @@ jobs: - 21.0.2 - 21.1.2 - 22.0.5 - - 23.0.1 + - 23.0.7 + - 24.0.0 steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 diff --git a/README.md b/README.md index 83218e6..e4a020c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Keycloak Metrics -Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [21-23](.github/workflows/pr.yaml#L50-L53). +Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [21-24](.github/workflows/pr.yaml#L50-L54). [![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/kokuwaio/keycloak-event-metrics.svg?label=License)](http://www.apache.org/licenses/) [![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) diff --git a/pom.xml b/pom.xml index e0ef498..cb7b775 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 23.0.7 + 24.0.0 ${version.org.keycloak} 1.18.3 diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java index 9f66fbd..029ffde 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java @@ -80,6 +80,8 @@ public class KeycloakClient { "emailVerified", true, "email", username + "@example.org", "username", username, + "firstName", username, + "lastName", username, "credentials", List.of(Map.of( "type", CredentialRepresentation.PASSWORD, "value", password, From c6a1cfd065875bc244bb8940ce807fb539496d91 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Tue, 5 Mar 2024 09:05:46 +0100 Subject: [PATCH 44/93] Add more sophisticated docker example, rel #76 (#77) * Add more sophisticated docker example, rel #76 * Update README.md --- README.md | 27 +++++++++++++++++++++++++-- pom.xml | 2 +- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e4a020c..8ecb716 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,30 @@ Check: [kokuwaio/keycloak](https://github.com/kokuwaio/keycloak) Dockerfile: ```Dockerfile -FROM quay.io/keycloak/keycloak:21.0.1 +### +### download keycloak event metrics +### + +FROM debian:stable-slim AS metrics + +RUN apt-get -qq update +RUN apt-get -qq install --yes --no-install-recommends ca-certificates wget + +ARG METRICS_VERSION=1.0.0 +ARG METRICS_FILE=keycloak-event-metrics-${METRICS_VERSION}.jar +ARG METRICS_URL=https://repo1.maven.org/maven2/io/kokuwa/keycloak/keycloak-event-metrics/${METRICS_VERSION} + +RUN wget --quiet --no-hsts ${METRICS_URL}/${METRICS_FILE} +RUN wget --quiet --no-hsts ${METRICS_URL}/${METRICS_FILE}.sha1 +RUN echo "$(cat ${METRICS_FILE}.sha1) ${METRICS_FILE}" sha1sum --quiet --check --strict - +RUN mkdir -p /opt/keycloak/providers +RUN mv ${METRICS_FILE} /opt/keycloak/providers + +### +### build keycloak with metrics +### + +FROM quay.io/keycloak/keycloak:23.0.7 ENV KEYCLOAK_ADMIN=admin ENV KEYCLOAK_ADMIN_PASSWORD=password @@ -134,7 +157,7 @@ ENV KC_HEALTH_ENABLED=true ENV KC_METRICS_ENABLED=true ENV KC_LOG_CONSOLE_COLOR=true -ADD target/keycloak-event-metrics-0.0.1-SNAPSHOT.jar /opt/keycloak/providers +COPY --from=metrics /opt/keycloak/providers /opt/keycloak/providers RUN /opt/keycloak/bin/kc.sh build ``` diff --git a/pom.xml b/pom.xml index cb7b775..b54adbf 100644 --- a/pom.xml +++ b/pom.xml @@ -200,7 +200,7 @@ - + org.codehaus.mojo From 6026d4ed18677e0f69151ccf7e5ab46129990307 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 09:37:26 +0100 Subject: [PATCH 45/93] Bump org.keycloak:keycloak-quarkus-server from 24.0.0 to 24.0.1 (#79) Bumps org.keycloak:keycloak-quarkus-server from 24.0.0 to 24.0.1. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b54adbf..12fe149 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 24.0.0 + 24.0.1 ${version.org.keycloak} 1.18.3 From 3d5cdae223c0a4d8c550a3adc489c901e6b493f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bauer?= Date: Mon, 25 Mar 2024 16:55:03 +0100 Subject: [PATCH 46/93] add dependabot automerge for minor changes (#81) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Bauer --- .github/auto-merge.yml | 3 +++ .github/workflows/dependabot-auto-merge.yaml | 14 ++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 .github/auto-merge.yml create mode 100644 .github/workflows/dependabot-auto-merge.yaml diff --git a/.github/auto-merge.yml b/.github/auto-merge.yml new file mode 100644 index 0000000..64ecc2d --- /dev/null +++ b/.github/auto-merge.yml @@ -0,0 +1,3 @@ +- match: + dependency_type: all + update_type: "semver:minor" diff --git a/.github/workflows/dependabot-auto-merge.yaml b/.github/workflows/dependabot-auto-merge.yaml new file mode 100644 index 0000000..c0fd636 --- /dev/null +++ b/.github/workflows/dependabot-auto-merge.yaml @@ -0,0 +1,14 @@ +name: dependabot-auto-merge + +on: + pull_request: + +jobs: + auto-merge: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v2 + - uses: ahmadnassri/action-dependabot-auto-merge@v2 + with: + github-token: ${{ secrets.DEPENDABOT_AUTOMERGE }} + target: minor From e59271dfa18bf436ee8a7f81e7bfadd86818c10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bauer?= Date: Mon, 25 Mar 2024 16:57:58 +0100 Subject: [PATCH 47/93] fix yaml lint --- .github/auto-merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/auto-merge.yml b/.github/auto-merge.yml index 64ecc2d..bd686d5 100644 --- a/.github/auto-merge.yml +++ b/.github/auto-merge.yml @@ -1,3 +1,3 @@ - match: dependency_type: all - update_type: "semver:minor" + update_type: semver:minor From 6753255024b5fbad7a90973e765ae22aadbe4e4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 17:02:25 +0100 Subject: [PATCH 48/93] Bump actions/checkout from 2 to 4 (#82) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependabot-auto-merge.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependabot-auto-merge.yaml b/.github/workflows/dependabot-auto-merge.yaml index c0fd636..4550fa7 100644 --- a/.github/workflows/dependabot-auto-merge.yaml +++ b/.github/workflows/dependabot-auto-merge.yaml @@ -7,7 +7,7 @@ jobs: auto-merge: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: ahmadnassri/action-dependabot-auto-merge@v2 with: github-token: ${{ secrets.DEPENDABOT_AUTOMERGE }} From aaa87db10f8e5a265015df7bf5583220de837add Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 17:11:41 +0100 Subject: [PATCH 49/93] Bump org.keycloak:keycloak-quarkus-server from 24.0.1 to 24.0.2 (#80) Bumps org.keycloak:keycloak-quarkus-server from 24.0.1 to 24.0.2. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 12fe149..354f410 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 24.0.1 + 24.0.2 ${version.org.keycloak} 1.18.3 From 22c462c5075f7d8917e67a82b90ba24e12d7b517 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 08:47:01 +0000 Subject: [PATCH 50/93] Bump org.keycloak:keycloak-quarkus-server from 24.0.2 to 24.0.3 (#83) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 354f410..ea1cc92 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 24.0.2 + 24.0.3 ${version.org.keycloak} 1.18.3 From aea3fd1cd891ff39d619cf93c9fb5ba6d48d0704 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Thu, 18 Apr 2024 13:38:16 +0200 Subject: [PATCH 51/93] Use kokuwa bot token --- .github/workflows/dependabot-auto-merge.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/dependabot-auto-merge.yaml b/.github/workflows/dependabot-auto-merge.yaml index 4550fa7..1509e34 100644 --- a/.github/workflows/dependabot-auto-merge.yaml +++ b/.github/workflows/dependabot-auto-merge.yaml @@ -1,14 +1,13 @@ name: dependabot-auto-merge -on: - pull_request: +on: pull_request jobs: auto-merge: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: ahmadnassri/action-dependabot-auto-merge@v2 with: - github-token: ${{ secrets.DEPENDABOT_AUTOMERGE }} + github-token: ${{ secrets.GIT_ACTION_TOKEN }} target: minor From ef92f6df24fdcb7ee15a30b4b8eea52164607ae2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 10:27:39 +0200 Subject: [PATCH 52/93] Bump org.keycloak:keycloak-quarkus-server from 24.0.3 to 24.0.4 (#84) Bumps org.keycloak:keycloak-quarkus-server from 24.0.3 to 24.0.4. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ea1cc92..017f96a 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 24.0.3 + 24.0.4 ${version.org.keycloak} 1.18.3 From bdf9159f8e09132cdbe7e01712b0dc1f1abb584a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jun 2024 14:08:26 +0200 Subject: [PATCH 53/93] Bump org.keycloak:keycloak-quarkus-server from 24.0.4 to 24.0.5 (#85) Bumps org.keycloak:keycloak-quarkus-server from 24.0.4 to 24.0.5. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 017f96a..f9d03e7 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 24.0.4 + 24.0.5 ${version.org.keycloak} 1.18.3 From da73c9d2f105e87effbca5b989f6231b2050d4c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 09:17:28 +0200 Subject: [PATCH 54/93] Bump org.keycloak:keycloak-quarkus-server from 24.0.5 to 25.0.1 (#87) * Bump org.keycloak:keycloak-quarkus-server from 24.0.5 to 25.0.1 Bumps org.keycloak:keycloak-quarkus-server from 24.0.5 to 25.0.1. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * fix build --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stephan Schnabel --- .github/workflows/pr.yaml | 3 ++- README.md | 5 ++--- pom.xml | 7 ++++++- .../kokuwa/keycloak/metrics/junit/KeycloakExtension.java | 3 ++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 86076da..f7def1a 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -51,7 +51,8 @@ jobs: - 21.1.2 - 22.0.5 - 23.0.7 - - 24.0.0 + - 24.0.5 + - 25.0.1 steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 diff --git a/README.md b/README.md index 8ecb716..7a0a58b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Keycloak Metrics -Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [21-24](.github/workflows/pr.yaml#L50-L54). +Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [21-25](.github/workflows/pr.yaml#L50-L55). [![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/kokuwaio/keycloak-event-metrics.svg?label=License)](http://www.apache.org/licenses/) [![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) @@ -149,13 +149,12 @@ RUN mv ${METRICS_FILE} /opt/keycloak/providers ### build keycloak with metrics ### -FROM quay.io/keycloak/keycloak:23.0.7 +FROM quay.io/keycloak/keycloak:25.0.1 ENV KEYCLOAK_ADMIN=admin ENV KEYCLOAK_ADMIN_PASSWORD=password ENV KC_HEALTH_ENABLED=true ENV KC_METRICS_ENABLED=true -ENV KC_LOG_CONSOLE_COLOR=true COPY --from=metrics /opt/keycloak/providers /opt/keycloak/providers RUN /opt/keycloak/bin/kc.sh build diff --git a/pom.xml b/pom.xml index f9d03e7..9c8a3ec 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ - 24.0.5 + 25.0.1 ${version.org.keycloak} 1.18.3 @@ -127,6 +127,11 @@ jboss-logging provided + + org.jboss.logging + commons-logging-jboss-logging + test + org.hibernate.orm hibernate-core diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java index c06c8f3..e2b1175 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java @@ -54,8 +54,9 @@ public class KeycloakExtension implements BeforeAllCallback, ParameterResolver { var container = new GenericContainer<>("quay.io/keycloak/keycloak:" + version) .withEnv("KEYCLOAK_ADMIN", "admin") .withEnv("KEYCLOAK_ADMIN_PASSWORD", "password") - .withEnv("KC_LOG_CONSOLE_COLOR", "true") .withEnv("KC_LOG_LEVEL", "io.kokuwa:trace") + // otherwise port 9000 will be used, with this config we can test different keycloak versions + .withEnv("KC_LEGACY_OBSERVABILITY_INTERFACE", "true") .withEnv("KC_HEALTH_ENABLED", "true") .withEnv("KC_METRICS_ENABLED", "true") .withEnv("KC_METRICS_STATS_ENABLED", "true") From c7bae85e40d52a261757a4bdbdcafa3963423931 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Mon, 24 Jun 2024 10:54:56 +0200 Subject: [PATCH 55/93] Reviewed build --- .github/workflows/build.yaml | 1 - .github/workflows/pr.yaml | 1 - .github/workflows/release.yaml | 1 - .yamllint => .yamllint.yaml | 0 pom.xml | 2 +- 5 files changed, 1 insertion(+), 4 deletions(-) rename .yamllint => .yamllint.yaml (100%) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e87924e..5ed003d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -21,7 +21,6 @@ jobs: distribution: temurin java-version: 17 cache: maven - - run: mvn $MAVEN_ARGS dependency:go-offline - run: mvn $MAVEN_ARGS deploy env: SERVER_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index f7def1a..0a4e59d 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -33,7 +33,6 @@ jobs: distribution: temurin java-version: 17 cache: maven - - run: mvn $MAVEN_ARGS dependency:go-offline - run: mvn $MAVEN_ARGS verify - run: mvn $MAVEN_ARGS site - uses: actions/upload-artifact@v4 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0e5bda9..3afdbf8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -29,7 +29,6 @@ jobs: server-password: SERVER_PASSWORD gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} gpg-passphrase: GPG_PASSPHRASE - - run: mvn $MAVEN_ARGS dependency:go-offline - run: mvn $MAVEN_ARGS release:prepare -Darguments="$MAVEN_ARGS" - run: mvn $MAVEN_ARGS release:perform -Darguments="$MAVEN_ARGS" env: diff --git a/.yamllint b/.yamllint.yaml similarity index 100% rename from .yamllint rename to .yamllint.yaml diff --git a/pom.xml b/pom.xml index 9c8a3ec..387577d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.kokuwa.maven maven-parent - 0.6.15 + 0.6.16 From 957713286a69761560817af07ce83aa05a4cd389 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Mon, 24 Jun 2024 15:15:47 +0200 Subject: [PATCH 56/93] Add container image (#89) --- .github/workflows/release.yaml | 12 +++++++ README.md | 9 ++++++ pom.xml | 58 ++++++++++++++++++++++++++++++++++ src/main/docker/Dockerfile | 14 ++++++++ 4 files changed, 93 insertions(+) create mode 100644 src/main/docker/Dockerfile diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3afdbf8..61f46be 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -8,6 +8,18 @@ jobs: env: MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.github/settings.xml steps: + - name: docker/login-action docker.io + uses: docker/login-action@v3.2.0 + with: + registry: docker.io + username: ${{ secrets.DOCKERIO_USERNAME }} + password: ${{ secrets.DOCKERIO_TOKEN }} + - name: docker/login-action ghcr.io + uses: docker/login-action@v3.2.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GIT_ACTION_TOKEN }} - run: git config --global user.name "${{ vars.KOKUWA_IO_BOT_NAME }}" - run: git config --global user.email "${{ vars.KOKUWA_IO_BOT_EMAIL }}" - uses: actions/checkout@v4 diff --git a/README.md b/README.md index 7a0a58b..3530a0e 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,15 @@ Can be found here: [kokuwaio/keycloak keycloak-metrics.json](https://github.com/ For usage in [Testcontainers](https://www.testcontainers.org/) see [KeycloakExtension.java](src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java#L57-L68) +### Container Image + +Registries: + +* [ghcr.io/kokuwaio/keycloak-event-metrics](https://github.com/kokuwaio/keycloak-event-metrics/pkgs/container/keycloak-event-metrics) +* [docker.io/kokuwaio/keycloak-event-metrics](https://hub.docker.com/r/kokuwaio/keycloak-event-metrics) + +This images are based on busybox, so you can use cp to copy the jar into your keycloak. + ### Docker Check: [kokuwaio/keycloak](https://github.com/kokuwaio/keycloak) diff --git a/pom.xml b/pom.xml index 387577d..7baf1cb 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,8 @@ 17 17 + deploy,site,ossrh,release + @@ -220,4 +222,60 @@ + + + + release + + + + org.apache.maven.plugins + maven-resources-plugin + + + prepare-package + + copy-resources + + + + + ${project.basedir}/src/main/docker + true + + + ${project.build.directory} + + + + + + org.codehaus.mojo + exec-maven-plugin + + + deploy + + exec + + + docker + + build + ${project.build.directory} + --tag=ghcr.io/kokuwaio/keycloak-event-metrics:latest + --tag=ghcr.io/kokuwaio/keycloak-event-metrics:${project.version} + --tag=docker.io/kokuwaio/keycloak-event-metrics:latest + --tag=docker.io/kokuwaio/keycloak-event-metrics:${project.version} + --push + + + + + + + + + + diff --git a/src/main/docker/Dockerfile b/src/main/docker/Dockerfile new file mode 100644 index 0000000..b1aeb9a --- /dev/null +++ b/src/main/docker/Dockerfile @@ -0,0 +1,14 @@ +FROM busybox:latest + +# https://github.com/opencontainers/image-spec/blob/main/annotations.md +LABEL org.opencontainers.image.title ${project.name} +LABEL org.opencontainers.image.description ${project.description} +LABEL org.opencontainers.image.url ${project.url} +LABEL org.opencontainers.image.source ${project.url}/src/main/docker/Dockerfile +LABEL org.opencontainers.image.vendor ${project.organization.name} +LABEL org.opencontainers.image.authors https://github.com/orgs/kokuwaio/people +LABEL org.opencontainers.image.licenses Apache-2.0 +LABEL org.opencontainers.image.version ${project.version} +LABEL org.opencontainers.image.base.name busybox:latest + +COPY ${project.build.finalName}.jar /keycloak-event-metrics.jar From 8b1834d373d34e3165a4e71780ae78c6100e28b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 23:38:00 +0200 Subject: [PATCH 57/93] Bump org.keycloak:keycloak-quarkus-server from 25.0.1 to 25.0.2 (#91) Bumps org.keycloak:keycloak-quarkus-server from 25.0.1 to 25.0.2. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7baf1cb..f6f7155 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 25.0.1 + 25.0.2 ${version.org.keycloak} 1.18.3 From 5bd2d9477e7660d6702e6be8077a294b5aebc736 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 23:47:13 +0200 Subject: [PATCH 58/93] Bump docker/login-action from 3.2.0 to 3.3.0 (#92) Bumps [docker/login-action](https://github.com/docker/login-action) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v3.2.0...v3.3.0) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 61f46be..a203b52 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,13 +9,13 @@ jobs: MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.github/settings.xml steps: - name: docker/login-action docker.io - uses: docker/login-action@v3.2.0 + uses: docker/login-action@v3.3.0 with: registry: docker.io username: ${{ secrets.DOCKERIO_USERNAME }} password: ${{ secrets.DOCKERIO_TOKEN }} - name: docker/login-action ghcr.io - uses: docker/login-action@v3.2.0 + uses: docker/login-action@v3.3.0 with: registry: ghcr.io username: ${{ github.actor }} From a2773d6742957d6028ed3caec8c8938f50795340 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:23:14 +0200 Subject: [PATCH 59/93] Bump org.keycloak:keycloak-quarkus-server from 25.0.2 to 25.0.4 (#93) Bumps org.keycloak:keycloak-quarkus-server from 25.0.2 to 25.0.4. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f6f7155..3907780 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 25.0.2 + 25.0.4 ${version.org.keycloak} 1.18.3 From c885dc70b69f89dab47f89d33ab9a82a35c8584e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:49:41 +0200 Subject: [PATCH 60/93] Bump io.kokuwa.maven:maven-parent from 0.6.16 to 0.6.17 (#94) Bumps [io.kokuwa.maven:maven-parent](https://github.com/kokuwaio/maven-parent) from 0.6.16 to 0.6.17. - [Commits](https://github.com/kokuwaio/maven-parent/compare/0.6.16...0.6.17) --- updated-dependencies: - dependency-name: io.kokuwa.maven:maven-parent dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3907780..f288e13 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.kokuwa.maven maven-parent - 0.6.16 + 0.6.17 From 57e651f57e88b497dc961c015d91ce08b1fe4743 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:49:50 +0200 Subject: [PATCH 61/93] Bump org.keycloak:keycloak-quarkus-server from 25.0.4 to 25.0.5 (#95) Bumps org.keycloak:keycloak-quarkus-server from 25.0.4 to 25.0.5. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f288e13..85d0cef 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 25.0.4 + 25.0.5 ${version.org.keycloak} 1.18.3 From 62a47a74194faf3a7f958a22e35390e9e6214932 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:26:26 +0200 Subject: [PATCH 62/93] Bump org.keycloak:keycloak-quarkus-server from 25.0.5 to 25.0.6 (#96) Bumps org.keycloak:keycloak-quarkus-server from 25.0.5 to 25.0.6. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 85d0cef..1e5cb65 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 25.0.5 + 25.0.6 ${version.org.keycloak} 1.18.3 From 8c44012e94ef657751a7d188ad939dd013df80fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:22:37 +0200 Subject: [PATCH 63/93] Bump org.keycloak:keycloak-quarkus-server from 25.0.6 to 26.0.2 (#99) * Bump org.keycloak:keycloak-quarkus-server from 25.0.6 to 26.0.2 Bumps org.keycloak:keycloak-quarkus-server from 25.0.6 to 26.0.2. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * adjust --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stephan Schnabel --- .github/auto-merge.yml | 3 --- .github/workflows/pr.yaml | 3 ++- pom.xml | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) delete mode 100644 .github/auto-merge.yml diff --git a/.github/auto-merge.yml b/.github/auto-merge.yml deleted file mode 100644 index bd686d5..0000000 --- a/.github/auto-merge.yml +++ /dev/null @@ -1,3 +0,0 @@ -- match: - dependency_type: all - update_type: semver:minor diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 0a4e59d..3ef129f 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -51,7 +51,8 @@ jobs: - 22.0.5 - 23.0.7 - 24.0.5 - - 25.0.1 + - 25.0.6 + - 26.0.2 steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 diff --git a/pom.xml b/pom.xml index 1e5cb65..7ac1c3b 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 25.0.6 + 26.0.2 ${version.org.keycloak} 1.18.3 From 7aeb1b9e252023200203862f1c45c8b3d609fbb9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Dec 2024 08:30:06 +0000 Subject: [PATCH 64/93] Bump org.keycloak:keycloak-quarkus-server from 26.0.2 to 26.0.7 Bumps org.keycloak:keycloak-quarkus-server from 26.0.2 to 26.0.7. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7ac1c3b..69362fd 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 26.0.2 + 26.0.7 ${version.org.keycloak} 1.18.3 From b4fad32161066ef3a3367614c4efb6cd156d4edc Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Mon, 2 Dec 2024 17:22:27 +0100 Subject: [PATCH 65/93] Collect all unknown client ids as UNKNOWN. Fix #100 --- README.md | 3 ++- pom.xml | 2 +- .../metrics/event/MetricsEventListener.java | 15 ++++++++++++- .../kokuwa/keycloak/metrics/KeycloakIT.java | 16 ++++++++++++-- .../event/MetricsEventListenerTest.java | 21 +++++++++++++------ 5 files changed, 46 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 3530a0e..2eb12ed 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ User events are added with key `keycloak_event_user_total` and tags: * `type`: [EventType](https://github.com/keycloak/keycloak/blob/main/server-spi-private/src/main/java/org/keycloak/events/EventType.java#L27) from [Event#type](https://github.com/keycloak/keycloak/blob/main/server-spi-private/src/main/java/org/keycloak/events/Event.java#L44) * `realm`: realm id from [Event#realmId](https://github.com/keycloak/keycloak/blob/main/server-spi-private/src/main/java/org/keycloak/events/Event.java#L46) -* `client`: client id from [Event#clientId](https://github.com/keycloak/keycloak/blob/main/server-spi-private/src/main/java/org/keycloak/events/Event.java#L48) +* `client`: client id from [Event#clientId](https://github.com/keycloak/keycloak/blob/main/server-spi-private/src/main/java/org/keycloak/events/Event.java#L48), unknown client_ids are grouped into UNKOWN * `error`: error from [Event#error](https://github.com/keycloak/keycloak/blob/main/server-spi-private/src/main/java/org/keycloak/events/Event.java#L56), only present for error types Examples: @@ -36,6 +36,7 @@ Examples: keycloak_event_user_total{client="test",realm="9039a0b5-e8c9-437a-a02e-9d91b04548a4",type="LOGIN",error="",} 2.0 keycloak_event_user_total{client="test",realm="1fdb3465-1675-49e8-88ad-292e2f42ee72",type="LOGIN",error="",} 1.0 keycloak_event_user_total{client="test",realm="1fdb3465-1675-49e8-88ad-292e2f42ee72",type="LOGIN_ERROR",error="invalid_user_credentials",} 1.0 +keycloak_event_user_total{client="UNKNOWN",realm="1fdb3465-1675-49e8-88ad-292e2f42ee72",type="LOGIN_ERROR",error="invalid_user_credentials",} 1.0 ``` ### Admin Events diff --git a/pom.xml b/pom.xml index 69362fd..3dfa01b 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ io.kokuwa.keycloak keycloak-event-metrics - 1.0.1-SNAPSHOT + 1.1.0-SNAPSHOT Keycloak Metrics Provides metrics for Keycloak user/admin events diff --git a/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListener.java b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListener.java index 4ba5144..0bed727 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListener.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/event/MetricsEventListener.java @@ -1,11 +1,13 @@ package io.kokuwa.keycloak.metrics.event; +import java.util.Objects; import java.util.Optional; import org.jboss.logging.Logger; import org.keycloak.events.Event; import org.keycloak.events.EventListenerProvider; import org.keycloak.events.admin.AdminEvent; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakContext; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -33,7 +35,7 @@ public class MetricsEventListener implements EventListenerProvider, AutoCloseabl Metrics.counter("keycloak_event_user", "realm", toBlank(replaceIds ? getRealmName(event.getRealmId()) : event.getRealmId()), "type", toBlank(event.getType()), - "client", toBlank(event.getClientId()), + "client", getClientId(event.getClientId()), "error", toBlank(event.getError())) .increment(); } @@ -65,6 +67,17 @@ public class MetricsEventListener implements EventListenerProvider, AutoCloseabl }); } + private String getClientId(String clientId) { + return Optional.ofNullable(session.getContext()) + .map(KeycloakContext::getClient) + .filter(model -> Objects.equals(model.getClientId(), clientId)) + .map(ClientModel::getClientId) + .orElseGet(() -> { + log.tracev("Client for id {0} is unknown", clientId); + return "UNKNOWN"; + }); + } + private String toBlank(Object value) { return value == null ? "" : value.toString(); } diff --git a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java index 1eaa0b1..cd4ebf4 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java @@ -48,6 +48,9 @@ public class KeycloakIT { keycloak.createClient(realmName2, clientId2); keycloak.createUser(realmName2, username2, password2); + var clientId3 = realmName2 + "_" + UUID.randomUUID(); + var clientId4 = realmName2 + "_" + UUID.randomUUID(); + prometheus.scrap(); var loginBefore = prometheus.userEvent(EventType.LOGIN); var loginBefore1 = prometheus.userEvent(EventType.LOGIN, realmName1, clientId1); @@ -55,10 +58,13 @@ public class KeycloakIT { var loginErrorBefore = prometheus.userEvent(EventType.LOGIN_ERROR); var loginErrorBefore1 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName1, clientId1); var loginErrorBefore2 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName2, clientId2); + var loginErrorBeforeUNKNOWN = prometheus.userEvent(EventType.LOGIN_ERROR, realmName2, "UNKNOWN"); assertDoesNotThrow(() -> keycloak.login(clientId1, realmName1, username1, password1)); assertDoesNotThrow(() -> keycloak.login(clientId1, realmName1, username1, password1)); assertDoesNotThrow(() -> keycloak.login(clientId2, realmName2, username2, password2)); + assertThrows(NotAuthorizedException.class, () -> keycloak.login(clientId3, realmName2, "nope", "nö")); + assertThrows(NotAuthorizedException.class, () -> keycloak.login(clientId4, realmName2, "foo", "bar")); assertThrows(NotAuthorizedException.class, () -> keycloak.login(clientId2, realmName2, username2, "nope")); prometheus.scrap(); @@ -68,14 +74,20 @@ public class KeycloakIT { var loginErrorAfter = prometheus.userEvent(EventType.LOGIN_ERROR); var loginErrorAfter1 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName1, clientId1); var loginErrorAfter2 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName2, clientId2); + var loginErrorAfter3 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName2, clientId3); + var loginErrorAfter4 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName2, clientId4); + var loginErrorAfterUNKNOWN = prometheus.userEvent(EventType.LOGIN_ERROR, realmName2, "UNKNOWN"); assertAll("prometheus", () -> assertEquals(loginBefore + 3, loginAfter, "login success total"), () -> assertEquals(loginBefore1 + 2, loginAfter1, "login success #1"), () -> assertEquals(loginBefore2 + 1, loginAfter2, "login success #2"), - () -> assertEquals(loginErrorBefore + 1, loginErrorAfter, "login failure total"), + () -> assertEquals(loginErrorBefore + 3, loginErrorAfter, "login failure total"), () -> assertEquals(loginErrorBefore1 + 0, loginErrorAfter1, "login failure #1"), - () -> assertEquals(loginErrorBefore2 + 1, loginErrorAfter2, "login failure #2")); + () -> assertEquals(loginErrorBefore2 + 1, loginErrorAfter2, "login failure #2"), + () -> assertEquals(0, loginErrorAfter3, "login failure #3"), + () -> assertEquals(0, loginErrorAfter4, "login failure #4"), + () -> assertEquals(loginErrorBeforeUNKNOWN + 2 , loginErrorAfterUNKNOWN, "login failure UNKNOWN")); } @DisplayName("user count") diff --git a/src/test/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerTest.java b/src/test/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerTest.java index 16684c5..d54fd36 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerTest.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/event/MetricsEventListenerTest.java @@ -13,6 +13,7 @@ import org.keycloak.events.EventType; import org.keycloak.events.admin.AdminEvent; import org.keycloak.events.admin.OperationType; import org.keycloak.events.admin.ResourceType; +import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakContext; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -37,6 +38,8 @@ public class MetricsEventListenerTest extends AbstractMockitoTest { @Mock RealmProvider realmProvider; @Mock + ClientModel clientModel; + @Mock KeycloakContext context; @DisplayName("onEvent(true)") @@ -54,8 +57,10 @@ public class MetricsEventListenerTest extends AbstractMockitoTest { when(session.getContext()).thenReturn(context); when(context.getRealm()).thenReturn(realmModel); + when(context.getClient()).thenReturn(clientModel); when(realmModel.getId()).thenReturn(realmId); when(realmModel.getName()).thenReturn(realmName); + when(clientModel.getClientId()).thenReturn(clientId); listener(true).onEvent(toEvent(realmId, clientId, type, null)); assertEvent(realmName, clientId, type.toString(), ""); @@ -73,8 +78,10 @@ public class MetricsEventListenerTest extends AbstractMockitoTest { when(session.getContext()).thenReturn(context); when(context.getRealm()).thenReturn(realmModel); + when(context.getClient()).thenReturn(clientModel); when(realmModel.getId()).thenReturn(realmId); when(realmModel.getName()).thenReturn(realmName); + when(clientModel.getClientId()).thenReturn(clientId); listener(true).onEvent(toEvent(realmId, clientId, type, error)); assertEvent(realmName, clientId, type.toString(), error); @@ -91,7 +98,7 @@ public class MetricsEventListenerTest extends AbstractMockitoTest { when(realmModel.getName()).thenReturn(realmName); listener(true).onEvent(toEvent(null, null, null, null)); - assertEvent(realmName, "", "", ""); + assertEvent(realmName, "UNKNOWN", "", ""); } @DisplayName("replace(true) - context is null") @@ -108,7 +115,7 @@ public class MetricsEventListenerTest extends AbstractMockitoTest { when(realmModel.getName()).thenReturn(realmName); listener(true).onEvent(toEvent(realmId, clientId, type, null)); - assertEvent(realmName, clientId, type.toString(), ""); + assertEvent(realmName, "UNKNOWN", type.toString(), ""); } @DisplayName("replace(true) - context is empty") @@ -126,7 +133,7 @@ public class MetricsEventListenerTest extends AbstractMockitoTest { when(realmModel.getName()).thenReturn(realmName); listener(true).onEvent(toEvent(realmId, clientId, type, null)); - assertEvent(realmName, clientId, type.toString(), ""); + assertEvent(realmName, "UNKNOWN", type.toString(), ""); } @DisplayName("replace(true) - realmId is unknown") @@ -140,7 +147,9 @@ public class MetricsEventListenerTest extends AbstractMockitoTest { when(session.getContext()).thenReturn(context); when(session.realms()).thenReturn(realmProvider); when(context.getRealm()).thenReturn(realmModel); + when(context.getClient()).thenReturn(clientModel); when(realmModel.getId()).thenReturn(UUID.randomUUID().toString()); + when(clientModel.getClientId()).thenReturn(clientId); listener(true).onEvent(toEvent(realmId, clientId, type, null)); assertEvent(realmId, clientId, type.toString(), ""); @@ -155,7 +164,7 @@ public class MetricsEventListenerTest extends AbstractMockitoTest { var type = EventType.LOGIN; listener(false).onEvent(toEvent(realmId, clientId, type, null)); - assertEvent(realmId, clientId, type.toString(), ""); + assertEvent(realmId, "UNKNOWN", type.toString(), ""); } @DisplayName("replace(false) - with error") @@ -168,14 +177,14 @@ public class MetricsEventListenerTest extends AbstractMockitoTest { var error = UUID.randomUUID().toString(); listener(false).onEvent(toEvent(realmId, clientId, type, error)); - assertEvent(realmId, clientId, type.toString(), error); + assertEvent(realmId, "UNKNOWN", type.toString(), error); } @DisplayName("replace(false) - all fields empty") @Test void notReplaceFieldsEmpty() { listener(false).onEvent(toEvent(null, null, null, null)); - assertEvent("", "", "", ""); + assertEvent("", "UNKNOWN", "", ""); } private Event toEvent(String realmId, String clientId, EventType type, String error) { From 29edb09cff5eec1da3d7154a4b9a77b2ee746a8f Mon Sep 17 00:00:00 2001 From: "kokuwa.io Bot" Date: Tue, 3 Dec 2024 13:05:29 +0000 Subject: [PATCH 66/93] [maven-release-plugin] prepare release 1.1.0 [no ci] --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 3dfa01b..007c4e9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,12 +6,12 @@ io.kokuwa.maven maven-parent 0.6.17 - + io.kokuwa.keycloak keycloak-event-metrics - 1.1.0-SNAPSHOT + 1.1.0 Keycloak Metrics Provides metrics for Keycloak user/admin events @@ -45,7 +45,7 @@ https://github.com/kokuwaio/keycloak-event-metrics scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git - HEAD + 1.1.0 github @@ -215,7 +215,7 @@ default - + From bb996faa6f472977347f6746093a191e5e4b7d48 Mon Sep 17 00:00:00 2001 From: "kokuwa.io Bot" Date: Tue, 3 Dec 2024 13:05:32 +0000 Subject: [PATCH 67/93] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 007c4e9..9f03bc3 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ io.kokuwa.keycloak keycloak-event-metrics - 1.1.0 + 1.1.1-SNAPSHOT Keycloak Metrics Provides metrics for Keycloak user/admin events @@ -45,7 +45,7 @@ https://github.com/kokuwaio/keycloak-event-metrics scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git - 1.1.0 + HEAD github From c735477d6f20243b1fbcd274862026dbe6fe11e3 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Thu, 19 Dec 2024 09:39:21 +0100 Subject: [PATCH 68/93] Fix build, align keycloak dependencies to avoid mockito classpath issues (#108) --- .github/workflows/dependabot-auto-merge.yaml | 13 ------------- .github/workflows/pr.yaml | 4 +--- README.md | 2 +- pom.xml | 2 ++ 4 files changed, 4 insertions(+), 17 deletions(-) delete mode 100644 .github/workflows/dependabot-auto-merge.yaml diff --git a/.github/workflows/dependabot-auto-merge.yaml b/.github/workflows/dependabot-auto-merge.yaml deleted file mode 100644 index 1509e34..0000000 --- a/.github/workflows/dependabot-auto-merge.yaml +++ /dev/null @@ -1,13 +0,0 @@ -name: dependabot-auto-merge - -on: pull_request - -jobs: - auto-merge: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: ahmadnassri/action-dependabot-auto-merge@v2 - with: - github-token: ${{ secrets.GIT_ACTION_TOKEN }} - target: minor diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 3ef129f..dd84d43 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -46,13 +46,11 @@ jobs: fail-fast: false matrix: version: - - 21.0.2 - - 21.1.2 - 22.0.5 - 23.0.7 - 24.0.5 - 25.0.6 - - 26.0.2 + - 26.0.7 steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 diff --git a/README.md b/README.md index 2eb12ed..d57d9b6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Keycloak Metrics -Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [21-25](.github/workflows/pr.yaml#L50-L55). +Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [22-26](.github/workflows/pr.yaml#L48-L53). [![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/kokuwaio/keycloak-event-metrics.svg?label=License)](http://www.apache.org/licenses/) [![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) diff --git a/pom.xml b/pom.xml index 9f03bc3..2bef6be 100644 --- a/pom.xml +++ b/pom.xml @@ -100,11 +100,13 @@ org.keycloak keycloak-server-spi + ${version.org.keycloak.test} provided org.keycloak keycloak-server-spi-private + ${version.org.keycloak.test} provided From c190433f33e5aa5a177859c18f1f24d1b5f01ac5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 08:53:46 +0000 Subject: [PATCH 69/93] Bump io.kokuwa.maven:maven-parent from 0.6.17 to 0.6.18 (#107) Bumps [io.kokuwa.maven:maven-parent](https://github.com/kokuwaio/maven-parent) from 0.6.17 to 0.6.18. - [Commits](https://github.com/kokuwaio/maven-parent/compare/0.6.17...0.6.18) --- updated-dependencies: - dependency-name: io.kokuwa.maven:maven-parent dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2bef6be..68f644e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.kokuwa.maven maven-parent - 0.6.17 + 0.6.18 From eb1dc0ce349f2485966b06a4e128f48f6a259bd9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 09:18:22 +0100 Subject: [PATCH 70/93] Bump org.keycloak:keycloak-quarkus-server from 26.0.7 to 26.0.8 (#109) Bumps org.keycloak:keycloak-quarkus-server from 26.0.7 to 26.0.8. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 68f644e..81ecd02 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 26.0.7 + 26.0.8 ${version.org.keycloak} 1.18.3 From 90f00379ea48bdfc5960c397346ad323cf6ae962 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:32:52 +0100 Subject: [PATCH 71/93] Bump org.keycloak:keycloak-quarkus-server from 26.0.8 to 26.1.0 (#110) Bumps org.keycloak:keycloak-quarkus-server from 26.0.8 to 26.1.0. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 81ecd02..cbd2e82 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 26.0.8 + 26.1.0 ${version.org.keycloak} 1.18.3 From ba55b8fc8e1a003aa43855f644f1d40459ca5a15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Feb 2025 08:03:08 +0100 Subject: [PATCH 72/93] Bump org.keycloak:keycloak-quarkus-server from 26.1.0 to 26.1.1 (#112) Bumps org.keycloak:keycloak-quarkus-server from 26.1.0 to 26.1.1. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cbd2e82..04dccf1 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 26.1.0 + 26.1.1 ${version.org.keycloak} 1.18.3 From fbf1da4b8246e10d5b32c353aea81eed18532934 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:44:44 +0100 Subject: [PATCH 73/93] Bump org.keycloak:keycloak-quarkus-server from 26.1.1 to 26.1.2 (#113) Bumps org.keycloak:keycloak-quarkus-server from 26.1.1 to 26.1.2. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 04dccf1..86a63e1 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 26.1.1 + 26.1.2 ${version.org.keycloak} 1.18.3 From 1a028e766ca814ccc6468965b0bda2a1ae17a1a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Mar 2025 13:40:18 +0100 Subject: [PATCH 74/93] Bump org.keycloak:keycloak-quarkus-server from 26.1.2 to 26.1.4 (#115) Bumps org.keycloak:keycloak-quarkus-server from 26.1.2 to 26.1.4. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 86a63e1..0115bd3 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 26.1.2 + 26.1.4 ${version.org.keycloak} 1.18.3 From 47c78e5b87f214896c30e273f28a9a70a4e74524 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:11:43 +0200 Subject: [PATCH 75/93] Bump docker/login-action from 3.3.0 to 3.4.0 (#117) Bumps [docker/login-action](https://github.com/docker/login-action) from 3.3.0 to 3.4.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v3.3.0...v3.4.0) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a203b52..e3240ed 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,13 +9,13 @@ jobs: MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.github/settings.xml steps: - name: docker/login-action docker.io - uses: docker/login-action@v3.3.0 + uses: docker/login-action@v3.4.0 with: registry: docker.io username: ${{ secrets.DOCKERIO_USERNAME }} password: ${{ secrets.DOCKERIO_TOKEN }} - name: docker/login-action ghcr.io - uses: docker/login-action@v3.3.0 + uses: docker/login-action@v3.4.0 with: registry: ghcr.io username: ${{ github.actor }} From 3362a18708660b7a0836c02925d5e0ba91db3813 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 09:53:27 +0000 Subject: [PATCH 76/93] Bump org.keycloak:keycloak-quarkus-server from 26.1.4 to 26.2.1 (#119) Co-authored-by: Stephan Schnabel --- .github/workflows/pr.yaml | 4 +++- pom.xml | 2 +- .../io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java | 1 + .../kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index dd84d43..86a8eb1 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -50,7 +50,9 @@ jobs: - 23.0.7 - 24.0.5 - 25.0.6 - - 26.0.7 + - 26.0.8 + - 26.1.5 + - 26.2.1 steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 diff --git a/pom.xml b/pom.xml index 0115bd3..a5d8e5d 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 26.1.4 + 26.2.1 ${version.org.keycloak} 1.18.3 diff --git a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java index db75da8..e16188d 100644 --- a/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java +++ b/src/main/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTask.java @@ -66,6 +66,7 @@ public class MetricsStatsTask implements Provider, ScheduledTask { private void scrape(KeycloakSession session) { session.realms().getRealmsStream().forEach(realm -> { + session.getContext().setRealm(realm); log.tracev("Scrape for realm {0}.", realm.getName()); var tagRealm = Tag.of("realm", realm.getName()); gauge("keycloak_users", Set.of(tagRealm), session.users().getUsersCount(realm), true); diff --git a/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java b/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java index 63201ce..9d696e7 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/stats/MetricsStatsTaskTest.java @@ -16,6 +16,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientProvider; +import org.keycloak.models.KeycloakContext; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; @@ -121,6 +122,7 @@ public class MetricsStatsTaskTest extends AbstractMockitoTest { when(session.clients()).thenReturn(clientProvider); when(session.users()).thenReturn(userProvider); when(session.sessions()).thenReturn(sessionProvider); + when(session.getContext()).thenReturn(mock(KeycloakContext.class)); when(realmProvider.getRealmsStream()).then(i -> Stream.of(realmModel)); // empty realm From 0e4181e3b18e168d62d2fb2b37b12c3db7a788b1 Mon Sep 17 00:00:00 2001 From: "kokuwa.io Bot" Date: Mon, 28 Apr 2025 12:25:43 +0000 Subject: [PATCH 77/93] [maven-release-plugin] prepare release 1.1.1 [no ci] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a5d8e5d..d1f1cb2 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ io.kokuwa.keycloak keycloak-event-metrics - 1.1.1-SNAPSHOT + 1.1.1 Keycloak Metrics Provides metrics for Keycloak user/admin events @@ -45,7 +45,7 @@ https://github.com/kokuwaio/keycloak-event-metrics scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git - HEAD + 1.1.1 github From 48e4939a5dec13012386334d57f15ff29d550d87 Mon Sep 17 00:00:00 2001 From: "kokuwa.io Bot" Date: Mon, 28 Apr 2025 12:25:45 +0000 Subject: [PATCH 78/93] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d1f1cb2..fea881a 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ io.kokuwa.keycloak keycloak-event-metrics - 1.1.1 + 1.1.2-SNAPSHOT Keycloak Metrics Provides metrics for Keycloak user/admin events @@ -45,7 +45,7 @@ https://github.com/kokuwaio/keycloak-event-metrics scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git - 1.1.1 + HEAD github From 1a1a9d3ae08d0a793ee93346f1f10bdb0ec309f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 May 2025 20:31:32 +0200 Subject: [PATCH 79/93] Bump org.keycloak:keycloak-quarkus-server from 26.2.1 to 26.2.2 (#120) Bumps org.keycloak:keycloak-quarkus-server from 26.2.1 to 26.2.2. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-version: 26.2.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fea881a..5688557 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 26.2.1 + 26.2.2 ${version.org.keycloak} 1.18.3 From c9f13d961d2e7ccd090ee91530d3d561cd0e3f49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 19:38:06 +0200 Subject: [PATCH 80/93] Bump org.keycloak:keycloak-quarkus-server from 26.2.2 to 26.2.3 (#121) Bumps org.keycloak:keycloak-quarkus-server from 26.2.2 to 26.2.3. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-version: 26.2.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5688557..712f93a 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 26.2.2 + 26.2.3 ${version.org.keycloak} 1.18.3 From 75d4e33c2fdd7c90b9112f2f5538d7d593e419ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 06:48:34 +0200 Subject: [PATCH 81/93] Bump org.keycloak:keycloak-quarkus-server from 26.2.3 to 26.2.4 (#122) Bumps org.keycloak:keycloak-quarkus-server from 26.2.3 to 26.2.4. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-version: 26.2.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 712f93a..bc0373e 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 26.2.3 + 26.2.4 ${version.org.keycloak} 1.18.3 From f421be47afc9ab252b196258533123bd0c0feeaa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 19:21:27 +0200 Subject: [PATCH 82/93] Bump org.keycloak:keycloak-quarkus-server from 26.2.4 to 26.2.5 (#123) Bumps org.keycloak:keycloak-quarkus-server from 26.2.4 to 26.2.5. --- updated-dependencies: - dependency-name: org.keycloak:keycloak-quarkus-server dependency-version: 26.2.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bc0373e..2f4ae93 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ - 26.2.4 + 26.2.5 ${version.org.keycloak} 1.18.3 From 83db6728277373963c5b557e9dd6ee403e4c962a Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Fri, 30 May 2025 20:36:25 +0200 Subject: [PATCH 83/93] Migrate from parent to local config only --- .github/workflows/build.yaml | 26 +- .github/workflows/pr.yaml | 9 +- pom.xml | 360 +++++++++++++++- src/eclipse/formatter.xml | 404 ++++++++++++++++++ .../kokuwa/keycloak/metrics/KeycloakIT.java | 5 +- .../metrics/junit/KeycloakClient.java | 8 +- .../metrics/junit/KeycloakExtension.java | 4 +- 7 files changed, 777 insertions(+), 39 deletions(-) create mode 100644 src/eclipse/formatter.xml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5ed003d..4da10a5 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -11,20 +11,40 @@ jobs: env: MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.github/settings.xml steps: + - name: docker/login-action docker.io + uses: docker/login-action@v3.4.0 + with: + registry: docker.io + username: ${{ secrets.DOCKERIO_USERNAME }} + password: ${{ secrets.DOCKERIO_TOKEN }} + - name: docker/login-action ghcr.io + uses: docker/login-action@v3.4.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GIT_ACTION_TOKEN }} - run: git config --global user.name "${{ vars.KOKUWA_IO_BOT_NAME }}" - run: git config --global user.email "${{ vars.KOKUWA_IO_BOT_EMAIL }}" - uses: actions/checkout@v4 with: token: ${{ secrets.GIT_ACTION_TOKEN }} + - uses: crazy-max/ghaction-import-gpg@v6 + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.GPG_PASSPHRASE }} + git_user_signingkey: true + git_commit_gpgsign: true - uses: actions/setup-java@v4 with: distribution: temurin java-version: 17 cache: maven + server-id: sonatype-nexus + server-username: SERVER_USERNAME + server-password: SERVER_PASSWORD + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-passphrase: GPG_PASSPHRASE - run: mvn $MAVEN_ARGS deploy env: SERVER_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }} SERVER_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} - - run: mvn $MAVEN_ARGS site-deploy - env: - GIT_ACTION_TOKEN: ${{ secrets.GIT_ACTION_TOKEN }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 86a8eb1..3548e88 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -3,7 +3,7 @@ name: PullRequest on: pull_request env: - MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress -Dmaven.test.redirectTestOutputToFile=false + MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress jobs: @@ -34,11 +34,6 @@ jobs: java-version: 17 cache: maven - run: mvn $MAVEN_ARGS verify - - run: mvn $MAVEN_ARGS site - - uses: actions/upload-artifact@v4 - if: always() - with: - path: target/site versions: runs-on: ubuntu-latest @@ -52,7 +47,7 @@ jobs: - 25.0.6 - 26.0.8 - 26.1.5 - - 26.2.1 + - 26.2.5 steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 diff --git a/pom.xml b/pom.xml index 2f4ae93..3d2ef55 100644 --- a/pom.xml +++ b/pom.xml @@ -2,13 +2,6 @@ 4.0.0 - - io.kokuwa.maven - maven-parent - 0.6.18 - - - io.kokuwa.keycloak keycloak-event-metrics 1.1.2-SNAPSHOT @@ -31,12 +24,10 @@ - sschnabe + stephan.schnabel Stephan Schnabel - https://github.com/sschnabe - stephan@grayc.de - GrayC GmbH - https://grayc.de + https://schnabel.org + stephan@schnabel.org Europe/Berlin @@ -55,6 +46,16 @@ github https://github.com/kokuwaio/keycloak-event-metrics/actions + + + sonatype-nexus + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + sonatype-nexus + https://oss.sonatype.org/content/repositories/snapshots/ + + @@ -62,15 +63,45 @@ - 17 - 17 + 2025-04-28T12:25:49Z + UTF-8 + ISO-8859-1 - deploy,site,ossrh,release + 17 + ${maven.compiler.release} + ${maven.compiler.release} + -Xlint:all + true + true + true + + true + java.,javax.,jakarta.,org. + ${project.basedir}/src/eclipse/formatter.xml - + + 3.4.1 + 3.14.0 + 3.1.4 + 3.2.7 + 3.1.4 + 3.4.2 + 3.11.2 + 3.1.1 + 3.3.1 + 3.21.0 + 3.3.1 + 3.5.3 + 3.5.1 + 1.4.0 + 2.18.0 + 1.7.0 + 2.26.0 + 1.12.0 + 26.2.5 ${version.org.keycloak} 1.18.3 @@ -188,12 +219,136 @@ + ${project.artifactId} ${project.basedir}/src/test/resources true + + + + org.apache.maven.plugins + maven-clean-plugin + ${version.org.apache.maven.plugins.clean} + + + org.apache.maven.plugins + maven-compiler-plugin + ${version.org.apache.maven.plugins.compiler} + + ${maven.compiler.compilerArgument} + + + + org.apache.maven.plugins + maven-deploy-plugin + ${version.org.apache.maven.plugins.deploy} + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.org.apache.maven.plugins.surefire} + + + org.apache.maven.plugins + maven-gpg-plugin + ${version.org.apache.maven.plugins.gpg} + + + org.apache.maven.plugins + maven-install-plugin + ${version.org.apache.maven.plugins.install} + + + org.apache.maven.plugins + maven-jar-plugin + ${version.org.apache.maven.plugins.jar} + + + org.apache.maven.plugins + maven-javadoc-plugin + ${version.org.apache.maven.plugins.javadoc} + + + org.apache.maven.plugins + maven-release-plugin + ${version.org.apache.maven.plugins.release} + + clean verify + check + deploy + deploy,release + true + @{prefix} prepare release @{releaseLabel} [CI SKIP] + @{project.version} + + + + org.apache.maven.plugins + maven-resources-plugin + ${version.org.apache.maven.plugins.resources} + + ${project.build.propertiesEncoding} + + + + org.apache.maven.plugins + maven-site-plugin + ${version.org.apache.maven.plugins.site} + + + org.apache.maven.plugins + maven-source-plugin + ${version.org.apache.maven.plugins.source} + + + org.apache.maven.plugins + maven-surefire-plugin + ${version.org.apache.maven.plugins.surefire} + + + org.codehaus.mojo + exec-maven-plugin + ${version.org.codehaus.mojo.exec} + + + org.codehaus.mojo + tidy-maven-plugin + ${version.org.codehaus.mojo.tidy} + + + org.codehaus.mojo + versions-maven-plugin + ${version.org.codehaus.mojo.versions} + + false + + ^.*-(alpha|beta|M)-?[0-9]+$ + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + ${version.org.sonatype.plugins.nexus} + + + net.revelc.code.formatter + formatter-maven-plugin + ${version.net.revelc.code.formatter} + + ${formatter.configFile} + + + + net.revelc.code + impsort-maven-plugin + ${version.net.revelc.code.impsort} + + + @@ -210,13 +365,13 @@ - + - org.codehaus.mojo - flatten-maven-plugin + org.apache.maven.plugins + maven-install-plugin - default + default-install @@ -227,9 +382,139 @@ - release + dev + + + !env.CI + + + + true + + + org.codehaus.mojo + tidy-maven-plugin + + + validate + + pom + + + + + + net.revelc.code + impsort-maven-plugin + + + validate + + sort + + + + + + net.revelc.code.formatter + formatter-maven-plugin + + + validate + + format + + + + + + + + + check + + + env.CI + + + + + + org.codehaus.mojo + tidy-maven-plugin + + + validate + + check + + + + + + net.revelc.code + impsort-maven-plugin + + + validate + + check + + + + + + net.revelc.code.formatter + formatter-maven-plugin + + + validate + + validate + + + + + + + + + deploy + + + env.CI + + + + + + + + org.apache.maven.plugins + maven-source-plugin + + + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + javadoc-no-fork + + + + + + org.apache.maven.plugins maven-resources-plugin @@ -279,5 +564,38 @@ + + release + + + + + + org.apache.maven.plugins + maven-gpg-plugin + + + + sign + + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + true + + sonatype-nexus + https://oss.sonatype.org/ + true + + + + + + diff --git a/src/eclipse/formatter.xml b/src/eclipse/formatter.xml new file mode 100644 index 0000000..61186a2 --- /dev/null +++ b/src/eclipse/formatter.xml @@ -0,0 +1,404 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java index cd4ebf4..a9ffeaa 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/KeycloakIT.java @@ -10,6 +10,8 @@ import java.time.Instant; import java.util.UUID; import java.util.function.Supplier; +import jakarta.ws.rs.NotAuthorizedException; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -18,7 +20,6 @@ import org.keycloak.events.EventType; import io.kokuwa.keycloak.metrics.junit.KeycloakClient; import io.kokuwa.keycloak.metrics.junit.KeycloakExtension; import io.kokuwa.keycloak.metrics.junit.Prometheus; -import jakarta.ws.rs.NotAuthorizedException; /** * Integration tests with Keycloak. @@ -87,7 +88,7 @@ public class KeycloakIT { () -> assertEquals(loginErrorBefore2 + 1, loginErrorAfter2, "login failure #2"), () -> assertEquals(0, loginErrorAfter3, "login failure #3"), () -> assertEquals(0, loginErrorAfter4, "login failure #4"), - () -> assertEquals(loginErrorBeforeUNKNOWN + 2 , loginErrorAfterUNKNOWN, "login failure UNKNOWN")); + () -> assertEquals(loginErrorBeforeUNKNOWN + 2, loginErrorAfterUNKNOWN, "login failure UNKNOWN")); } @DisplayName("user count") diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java index 029ffde..b79ca14 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakClient.java @@ -13,6 +13,10 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedHashMap; + import org.keycloak.OAuth2Constants; import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.token.TokenService; @@ -24,10 +28,6 @@ import org.keycloak.representations.idm.UserRepresentation; import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.MultivaluedHashMap; - /** * Client for keycloak. * diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java index e2b1175..91f013f 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java @@ -7,6 +7,8 @@ import java.time.Duration; import java.util.Properties; import java.util.Set; +import jakarta.ws.rs.client.ClientBuilder; + import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; @@ -17,8 +19,6 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.MountableFile; -import jakarta.ws.rs.client.ClientBuilder; - /** * JUnit extension to start keycloak. * From 9552221cc4c7c1fabf49de066c442cd6b46a2247 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Fri, 30 May 2025 22:18:34 +0200 Subject: [PATCH 84/93] Replace docker invocation with maven plugin --- pom.xml | 119 +++++++++++++++++++++++++------------ src/main/docker/Dockerfile | 14 ----- 2 files changed, 80 insertions(+), 53 deletions(-) delete mode 100644 src/main/docker/Dockerfile diff --git a/pom.xml b/pom.xml index 3d2ef55..8e26d7f 100644 --- a/pom.xml +++ b/pom.xml @@ -95,12 +95,12 @@ 3.21.0 3.3.1 3.5.3 - 3.5.1 1.4.0 2.18.0 1.7.0 2.26.0 1.12.0 + 0.46.0 26.2.5 ${version.org.keycloak} @@ -219,7 +219,6 @@ - ${project.artifactId} ${project.basedir}/src/test/resources @@ -308,11 +307,6 @@ maven-surefire-plugin ${version.org.apache.maven.plugins.surefire} - - org.codehaus.mojo - exec-maven-plugin - ${version.org.codehaus.mojo.exec} - org.codehaus.mojo tidy-maven-plugin @@ -347,6 +341,11 @@ impsort-maven-plugin ${version.net.revelc.code.impsort} + + io.fabric8 + docker-maven-plugin + ${version.io.fabric8.docker} + @@ -516,49 +515,91 @@ - org.apache.maven.plugins - maven-resources-plugin + io.fabric8 + docker-maven-plugin - prepare-package + build + install - copy-resources + build - - - - ${project.basedir}/src/main/docker - true - - - ${project.build.directory} - - - - - org.codehaus.mojo - exec-maven-plugin - + push deploy - exec + push - - docker - - build - ${project.build.directory} - --tag=ghcr.io/kokuwaio/keycloak-event-metrics:latest - --tag=ghcr.io/kokuwaio/keycloak-event-metrics:${project.version} - --tag=docker.io/kokuwaio/keycloak-event-metrics:latest - --tag=docker.io/kokuwaio/keycloak-event-metrics:${project.version} - --push - - + + build + + + docker.io/kokuwaio/keycloak-event-metrics:${project.version} + + docker.io/library/busybox:1.37.0-uclibc@sha256:cc57e0ff4b6d3138931ff5c7180d18078813300e2508a25fb767a4d36df30d4d + + ${file.separator} + + + + ${project.build.directory}/${project.build.finalName}.jar + ${project.artifactId}.jar + 444 + + + + + + + ${project.name} + ${project.description} + ${project.url} + ${project.scm.url} + ${project.organization.name} + https://github.com/orgs/kokuwaio/people + ${project.licenses[0].name} + ${project.version} + docker.io/library/busybox:1.37.0-uclibc + sha256:cc57e0ff4b6d3138931ff5c7180d18078813300e2508a25fb767a4d36df30d4d + + + + + ghcr.io/kokuwaio/keycloak-event-metrics:${project.version} + + docker.io/library/busybox:1.37.0-uclibc@sha256:cc57e0ff4b6d3138931ff5c7180d18078813300e2508a25fb767a4d36df30d4d + + ${file.separator} + + + + ${project.build.directory}/${project.build.finalName}.jar + ${project.artifactId}.jar + 444 + + + + + + + ${project.name} + ${project.description} + ${project.url} + ${project.scm.url} + ${project.organization.name} + https://github.com/orgs/kokuwaio/people + ${project.licenses[0].name} + ${project.version} + docker.io/library/busybox:1.37.0-uclibc + sha256:cc57e0ff4b6d3138931ff5c7180d18078813300e2508a25fb767a4d36df30d4d + + + + + diff --git a/src/main/docker/Dockerfile b/src/main/docker/Dockerfile deleted file mode 100644 index b1aeb9a..0000000 --- a/src/main/docker/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM busybox:latest - -# https://github.com/opencontainers/image-spec/blob/main/annotations.md -LABEL org.opencontainers.image.title ${project.name} -LABEL org.opencontainers.image.description ${project.description} -LABEL org.opencontainers.image.url ${project.url} -LABEL org.opencontainers.image.source ${project.url}/src/main/docker/Dockerfile -LABEL org.opencontainers.image.vendor ${project.organization.name} -LABEL org.opencontainers.image.authors https://github.com/orgs/kokuwaio/people -LABEL org.opencontainers.image.licenses Apache-2.0 -LABEL org.opencontainers.image.version ${project.version} -LABEL org.opencontainers.image.base.name busybox:latest - -COPY ${project.build.finalName}.jar /keycloak-event-metrics.jar From a523f7ba6eb7bfb643e22c789892d17726907a68 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Mon, 23 Jun 2025 16:54:42 +0200 Subject: [PATCH 85/93] Moved repository to git.kokuwa.io --- .github/CODEOWNERS | 2 - .github/dependabot.yml | 14 - .github/settings.xml | 16 - .github/workflows/build.yaml | 68 ++- .github/workflows/lint.yaml | 23 + .github/workflows/pr.yaml | 58 --- .github/workflows/release.yaml | 50 --- .justfile | 21 + .woodpecker/deploy.yaml | 50 +++ .woodpecker/dockerhub.yaml | 17 + .woodpecker/lint.yaml | 26 ++ .woodpecker/maven/settings.xml | 33 ++ .woodpecker/release.yaml | 61 +++ .woodpecker/verify.yaml | 24 + .woodpecker/versions.yaml | 26 ++ Dockerfile | 15 + Dockerfile.dockerignore | 5 + LICENSE | 425 +++++++++++------- README.md | 19 +- pom.xml | 255 +++-------- renovate.json | 5 + .../metrics/junit/KeycloakExtension.java | 42 +- 22 files changed, 693 insertions(+), 562 deletions(-) delete mode 100644 .github/CODEOWNERS delete mode 100644 .github/dependabot.yml delete mode 100644 .github/settings.xml create mode 100644 .github/workflows/lint.yaml delete mode 100644 .github/workflows/pr.yaml delete mode 100644 .github/workflows/release.yaml create mode 100644 .justfile create mode 100644 .woodpecker/deploy.yaml create mode 100644 .woodpecker/dockerhub.yaml create mode 100644 .woodpecker/lint.yaml create mode 100644 .woodpecker/maven/settings.xml create mode 100644 .woodpecker/release.yaml create mode 100644 .woodpecker/verify.yaml create mode 100644 .woodpecker/versions.yaml create mode 100644 Dockerfile create mode 100644 Dockerfile.dockerignore create mode 100644 renovate.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 3f0ccf3..0000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,2 +0,0 @@ -# https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax -* @sschnabe @rpahli @fabian-schlegel @jschwarze @wistefan @monotek diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 415bfca..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: 2 -updates: - - package-ecosystem: maven - directory: / - schedule: - interval: daily - allow: - - dependency-name: io.kokuwa.maven:maven-parent - - dependency-name: org.keycloak:keycloak-quarkus-server - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - day: monday diff --git a/.github/settings.xml b/.github/settings.xml deleted file mode 100644 index 44fd9ea..0000000 --- a/.github/settings.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - sonatype-nexus - ${env.SERVER_USERNAME} - ${env.SERVER_PASSWORD} - - - github.com - nope - ${env.GIT_ACTION_TOKEN} - - - diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4da10a5..5d30921 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,50 +1,42 @@ -name: Build +name: Verify on: - push: - branches: [main] + - pull_request + - push: + branches: [main] + +env: + MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress jobs: build: runs-on: ubuntu-latest - env: - MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.github/settings.xml steps: - - name: docker/login-action docker.io - uses: docker/login-action@v3.4.0 - with: - registry: docker.io - username: ${{ secrets.DOCKERIO_USERNAME }} - password: ${{ secrets.DOCKERIO_TOKEN }} - - name: docker/login-action ghcr.io - uses: docker/login-action@v3.4.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GIT_ACTION_TOKEN }} - - run: git config --global user.name "${{ vars.KOKUWA_IO_BOT_NAME }}" - - run: git config --global user.email "${{ vars.KOKUWA_IO_BOT_EMAIL }}" - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GIT_ACTION_TOKEN }} - - uses: crazy-max/ghaction-import-gpg@v6 - with: - gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} - passphrase: ${{ secrets.GPG_PASSPHRASE }} - git_user_signingkey: true - git_commit_gpgsign: true - - uses: actions/setup-java@v4 + - uses: actions/checkout@main + - uses: actions/setup-java@main with: distribution: temurin java-version: 17 cache: maven - server-id: sonatype-nexus - server-username: SERVER_USERNAME - server-password: SERVER_PASSWORD - gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} - gpg-passphrase: GPG_PASSPHRASE - - run: mvn $MAVEN_ARGS deploy - env: - SERVER_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }} - SERVER_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} + - run: mvn verify + + versions: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + version: + - 22.0.5 + - 23.0.7 + - 24.0.5 + - 25.0.6 + - 26.2.5 + steps: + - uses: actions/checkout@main + - uses: actions/setup-java@main + with: + distribution: temurin + java-version: 17 + cache: maven + - run: mvn verify -Dversion.org.keycloak.test=${{ matrix.version }} diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..af980fa --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,23 @@ +name: Lint + +on: push + +jobs: + + renovate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - uses: docker://kokuwaio/renovate-config-validator + + markdownlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - uses: docker://kokuwaio/markdownlint + + yamllint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - uses: docker://kokuwaio/yamllint diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml deleted file mode 100644 index 3548e88..0000000 --- a/.github/workflows/pr.yaml +++ /dev/null @@ -1,58 +0,0 @@ -name: PullRequest - -on: pull_request - -env: - MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress - -jobs: - - yaml: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: ibiqlik/action-yamllint@v3 - with: - format: colored - strict: true - - markdown: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: avto-dev/markdown-lint@v1 - with: - args: /github/workspace - - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 17 - cache: maven - - run: mvn $MAVEN_ARGS verify - - versions: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - version: - - 22.0.5 - - 23.0.7 - - 24.0.5 - - 25.0.6 - - 26.0.8 - - 26.1.5 - - 26.2.5 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 17 - cache: maven - - run: mvn $MAVEN_ARGS verify -Dcheck.skip -Dversion.org.keycloak.test=${{ matrix.version }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml deleted file mode 100644 index e3240ed..0000000 --- a/.github/workflows/release.yaml +++ /dev/null @@ -1,50 +0,0 @@ -name: Release - -on: workflow_dispatch - -jobs: - build: - runs-on: ubuntu-latest - env: - MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.github/settings.xml - steps: - - name: docker/login-action docker.io - uses: docker/login-action@v3.4.0 - with: - registry: docker.io - username: ${{ secrets.DOCKERIO_USERNAME }} - password: ${{ secrets.DOCKERIO_TOKEN }} - - name: docker/login-action ghcr.io - uses: docker/login-action@v3.4.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GIT_ACTION_TOKEN }} - - run: git config --global user.name "${{ vars.KOKUWA_IO_BOT_NAME }}" - - run: git config --global user.email "${{ vars.KOKUWA_IO_BOT_EMAIL }}" - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GIT_ACTION_TOKEN }} - - uses: crazy-max/ghaction-import-gpg@v6 - with: - gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} - passphrase: ${{ secrets.GPG_PASSPHRASE }} - git_user_signingkey: true - git_commit_gpgsign: true - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 17 - cache: maven - server-id: sonatype-nexus - server-username: SERVER_USERNAME - server-password: SERVER_PASSWORD - gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} - gpg-passphrase: GPG_PASSPHRASE - - run: mvn $MAVEN_ARGS release:prepare -Darguments="$MAVEN_ARGS" - - run: mvn $MAVEN_ARGS release:perform -Darguments="$MAVEN_ARGS" - env: - SERVER_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }} - SERVER_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} - GIT_ACTION_TOKEN: ${{ secrets.GIT_ACTION_TOKEN }} - GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} diff --git a/.justfile b/.justfile new file mode 100644 index 0000000..c751e60 --- /dev/null +++ b/.justfile @@ -0,0 +1,21 @@ +# https://just.systems/man/en/ + +[private] +@default: + just --list --unsorted + +# Run linter. +@lint: + docker run --rm --read-only --volume=$(pwd):$(pwd):ro --workdir=$(pwd) kokuwaio/hadolint + docker run --rm --read-only --volume=$(pwd):$(pwd):ro --workdir=$(pwd) kokuwaio/yamllint + docker run --rm --read-only --volume=$(pwd):$(pwd):rw --workdir=$(pwd) kokuwaio/markdownlint --fix + docker run --rm --read-only --volume=$(pwd):$(pwd):ro --workdir=$(pwd) kokuwaio/renovate + docker run --rm --read-only --volume=$(pwd):$(pwd):ro --workdir=$(pwd) woodpeckerci/woodpecker-cli lint + +# Build image with local docker daemon. +@build: + docker build . --tag=kokuwaio/keycloak-event-metrics:dev + +# Inspect image layers with `dive`. +@dive: build + dive build . diff --git a/.woodpecker/deploy.yaml b/.woodpecker/deploy.yaml new file mode 100644 index 0000000..53976dc --- /dev/null +++ b/.woodpecker/deploy.yaml @@ -0,0 +1,50 @@ +when: + instance: ci.kokuwa.io + repo: keycloak/keycloak-event-metrics + event: [manual, push] + branch: main + path: [.woodpecker/deploy.yaml, Dockerfile, pom.xml, src/main/**] + +services: + - name: dockerd + image: kokuwaio/dockerd + privileged: true + ports: [2375, 8080] + +steps: + + maven: + image: maven:3.9.10-eclipse-temurin-17 + commands: mvn deploy + environment: + MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.woodpecker/maven/settings.xml + MAVEN_GPG_KEY: {from_secret: woodpecker_gpg_key} + SONATYPE_ORG_USERNAME: {from_secret: sonatype_org_username} + SONATYPE_ORG_PASSWORD: {from_secret: sonatype_org_password} + + image: + image: kokuwaio/buildctl + settings: + name: + - docker.io/kokuwaio/keycloak-event-metrics:snapshot + - ghcr.io/kokuwaio/keycloak-event-metrics:snapshot + build-args: {MAVEN_MIRROR_CENTRAL: "${MAVEN_MIRROR_CENTRAL}"} + platform: [linux/amd64, linux/arm64] + auth: + "https://index.docker.io/v1/": + username: {from_secret: docker_io_username} + password: {from_secret: docker_io_password} + ghcr.io: + username: {from_secret: ghcr_io_username} + password: {from_secret: ghcr_io_password} + annotation: + org.opencontainers.image.title: Keycloak Metrics + org.opencontainers.image.description: Provides metrics for Keycloak user/admin events and user/client/session count. + org.opencontainers.image.url: $CI_REPO_URL + org.opencontainers.image.documentation: $CI_REPO_URL/README.md + org.opencontainers.image.source: $CI_REPO_CLONE_URL + org.opencontainers.image.revision: $CI_COMMIT_SHA + org.opencontainers.image.vendor: kokuwa.io + org.opencontainers.image.licenses: EUPL-1.2 + org.opencontainers.image.ref.name: kokuwaio/keycloak-event-metrics + org.opencontainers.image.version: snapshot diff --git a/.woodpecker/dockerhub.yaml b/.woodpecker/dockerhub.yaml new file mode 100644 index 0000000..a443560 --- /dev/null +++ b/.woodpecker/dockerhub.yaml @@ -0,0 +1,17 @@ +when: + instance: ci.kokuwa.io + repo: keycloak/keycloak-event-metrics + event: [manual, push] + branch: main + path: [.woodpecker/dockerhub.yaml, README.md] + +steps: + + metadata: + image: kokuwaio/dockerhub-metadata + settings: + repository: kokuwaio/keycloak-event-metrics + description-short: Provides metrics for Keycloak user/admin events and user/client/session count. + categories: monitoring-and-observability + username: {from_secret: dockerhub_username} + password: {from_secret: dockerhub_password} diff --git a/.woodpecker/lint.yaml b/.woodpecker/lint.yaml new file mode 100644 index 0000000..7de51db --- /dev/null +++ b/.woodpecker/lint.yaml @@ -0,0 +1,26 @@ +when: + event: [manual, pull_request, push] + branch: main + path: [.woodpecker/lint.yaml, renovate.json, Dockerfile, "**/*.y*ml", "**/*.md"] + +steps: + + renovate: + image: kokuwaio/renovate-config-validator + depends_on: [] + when: [path: [.woodpecker/lint.yaml, renovate.json]] + + yaml: + image: kokuwaio/yamllint + depends_on: [] + when: [path: [.woodpecker/lint.yaml, .yamllint.yaml, "**/*.y*ml"]] + + markdown: + image: kokuwaio/markdownlint + depends_on: [] + when: [path: [.woodpecker/lint.yaml, .markdownlint.yaml, "**/*.md"]] + + dockerfile: + image: kokuwaio/hadolint + depends_on: [] + when: [path: [.woodpecker/lint.yaml, Dockerfile]] diff --git a/.woodpecker/maven/settings.xml b/.woodpecker/maven/settings.xml new file mode 100644 index 0000000..4542205 --- /dev/null +++ b/.woodpecker/maven/settings.xml @@ -0,0 +1,33 @@ + + + false + /woodpecker/.m2 + + + git.kokuwa.io + ${env.FORGEJO_USERNAME} + ${env.FORGEJO_PASSWORD} + + + sonatype.org + ${env.SONATYPE_ORG_USERNAME} + ${env.SONATYPE_ORG_PASSWORD} + + + docker.io + ${env.DOCKER_IO_USERNAME} + ${env.DOCKER_IO_PASSWORD} + + + ghcr.io + ${env.GHCR_IO_USERNAME} + ${env.GHCR_IO_PASSWORD} + + + + + http://mirror.woodpecker.svc.cluster.local/maven2 + central + + + diff --git a/.woodpecker/release.yaml b/.woodpecker/release.yaml new file mode 100644 index 0000000..8ec3522 --- /dev/null +++ b/.woodpecker/release.yaml @@ -0,0 +1,61 @@ +when: + instance: ci.kokuwa.io + repo: keycloak/keycloak-event-metrics + event: deployment + branch: main + +steps: + + maven: + image: maven:3.9.10-eclipse-temurin-17 + commands: + # setup git with ssk key signing + - git config user.email "$GIT_USER_EMAIL" + - git config user.name "$GIT_USER_NAME" + - git config commit.gpgsign true + - git config gpg.format ssh + - git config user.signingkey /run/secrets/sign.pub + - install -m 400 /dev/null /run/secrets/sign && echo "$GIT_SIGN_KEY" > /run/secrets/sign + - install -m 444 /dev/null /run/secrets/sign.pub && echo "$GIT_SIGN_PUB" > /run/secrets/sign.pub + # release & write version to env file for image + - mvn release:prepare release:perform + - echo "VERSION=$(mvn help:evaluate --quiet --file=target/checkout/pom.xml -Dexpression=project.version -DforceStdout)" > maven.env + environment: + MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.woodpecker/maven/settings.xml + MAVEN_GPG_KEY: {from_secret: woodpecker_gpg_key} + GIT_SIGN_KEY: {from_secret: woodpecker_sign_key} + GIT_SIGN_PUB: {from_secret: woodpecker_sign_pub} + FORGEJO_USERNAME: {from_secret: woodpecker_username} + FORGEJO_PASSWORD: {from_secret: woodpecker_password} + SONATYPE_ORG_USERNAME: {from_secret: sonatype_org_username} + SONATYPE_ORG_PASSWORD: {from_secret: sonatype_org_password} + + image: + image: kokuwaio/buildctl + settings: + env-file: maven.env + name: + - docker.io/kokuwaio/keycloak-event-metrics:latest + - docker.io/kokuwaio/keycloak-event-metrics:$VERSION + - ghcr.io/kokuwaio/keycloak-event-metrics:latest + - ghcr.io/kokuwaio/keycloak-event-metrics:$VERSION + build-args: {MAVEN_MIRROR_CENTRAL: "${MAVEN_MIRROR_CENTRAL}"} + platform: [linux/amd64, linux/arm64] + auth: + "https://index.docker.io/v1/": + username: {from_secret: docker_io_username} + password: {from_secret: docker_io_password} + ghcr.io: + username: {from_secret: ghcr_io_username} + password: {from_secret: ghcr_io_password} + annotation: + org.opencontainers.image.title: Keycloak Metrics + org.opencontainers.image.description: Provides metrics for Keycloak user/admin events and user/client/session count. + org.opencontainers.image.url: $CI_REPO_URL + org.opencontainers.image.documentation: $CI_REPO_URL/README.md + org.opencontainers.image.source: $CI_REPO_CLONE_URL + org.opencontainers.image.revision: $CI_COMMIT_SHA + org.opencontainers.image.vendor: kokuwa.io + org.opencontainers.image.licenses: EUPL-1.2 + org.opencontainers.image.ref.name: kokuwaio/keycloak-event-metrics + org.opencontainers.image.version: $VERSION diff --git a/.woodpecker/verify.yaml b/.woodpecker/verify.yaml new file mode 100644 index 0000000..5d9002b --- /dev/null +++ b/.woodpecker/verify.yaml @@ -0,0 +1,24 @@ +when: + event: [manual, pull_request] + path: [.woodpecker/verify.yaml, pom.xml, src/**] + +services: + - name: dockerd + image: kokuwaio/dockerd + privileged: true + ports: [2375, 8080] + +steps: + + test: + image: maven:3.9.10-eclipse-temurin-17 + commands: mvn verify -P-deploy + environment: + MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.woodpecker/maven/settings.xml + + image: + image: kokuwaio/buildctl + settings: + platform: [linux/amd64, linux/arm64] + when: + instance: ci.kokuwa.io diff --git a/.woodpecker/versions.yaml b/.woodpecker/versions.yaml new file mode 100644 index 0000000..47a286e --- /dev/null +++ b/.woodpecker/versions.yaml @@ -0,0 +1,26 @@ +when: + event: [manual, pull_request] + path: [.woodpecker/versions.yaml, pom.xml, src/**] + +depends_on: [verify] +matrix: + KEYCLOAK_VERSION: + - 22.0.5 + - 23.0.7 + - 24.0.5 + - 25.0.6 + - 26.2.5 + +services: + - name: dockerd + image: kokuwaio/dockerd + privileged: true + ports: [2375, 8080] + +steps: + + test: + image: maven:3.9.10-eclipse-temurin-17 + commands: mvn verify -Dversion.org.keycloak.test="$KEYCLOAK_VERSION" -P-deploy,-check + environment: + MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress --settings=.woodpecker/maven/settings.xml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6d8ad09 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM maven:3.9.10-eclipse-temurin-17 AS build +SHELL ["/usr/bin/bash", "-e", "-u", "-c"] +WORKDIR /build +ARG MAVEN_ARGS="--batch-mode --color=always --no-transfer-progress" +ARG MAVEN_MIRROR_CENTRAL +RUN mkdir "$HOME/.m2" && printf "\n\ +\n\ + /tmp/mvn-repo\n\ + %scentral\n\ +" "${MAVEN_MIRROR_CENTRAL:-https://repo.maven.apache.org/maven2}" > "$HOME/.m2/settings.xml" +COPY . . +RUN --mount=type=cache,target=/tmp/mvn-repo mvn package -DskipTests -P=-dev + +FROM busybox:1.37.0-uclibc +COPY --from=build --chmod=444 /build/target/keycloak-event-metrics.jar /opt/keycloak/providers/keycloak-event-metrics.jar diff --git a/Dockerfile.dockerignore b/Dockerfile.dockerignore new file mode 100644 index 0000000..744a668 --- /dev/null +++ b/Dockerfile.dockerignore @@ -0,0 +1,5 @@ +* +.* + +!pom.xml +!src/main/** diff --git a/LICENSE b/LICENSE index 261eeb9..dacd3ae 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,288 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + EUROPEAN UNION PUBLIC LICENCE v. 1.2 + EUPL © the European Union 2007, 2016 - 1. Definitions. +This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined +below) which is provided under the terms of this Licence. Any use of the Work, +other than as authorised under this Licence is prohibited (to the extent such +use is covered by a right of the copyright holder of the Work). - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. +The Work is provided under the terms of this Licence when the Licensor (as +defined below) has placed the following notice immediately following the +copyright notice for the Work: - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. + Licensed under the EUPL - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. +or has expressed by any other means his willingness to license under the EUPL. - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. +1. Definitions - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. +In this Licence, the following terms have the following meaning: - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. +- ‘The Licence’: this Licence. - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). +- ‘The Original Work’: the work or software distributed or communicated by the + Licensor under this Licence, available as Source Code and also as Executable + Code as the case may be. - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. +- ‘Derivative Works’: the works or software that could be created by the + Licensee, based upon the Original Work or modifications thereof. This Licence + does not define the extent of modification or dependence on the Original Work + required in order to classify a work as a Derivative Work; this extent is + determined by copyright law applicable in the country mentioned in Article 15. - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." +- ‘The Work’: the Original Work or its Derivative Works. - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. +- ‘The Source Code’: the human-readable form of the Work which is the most + convenient for people to study and modify. - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. +- ‘The Executable Code’: any code which has generally been compiled and which is + meant to be interpreted by a computer as a program. - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. +- ‘The Licensor’: the natural or legal person that distributes or communicates + the Work under the Licence. - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: +- ‘Contributor(s)’: any natural or legal person who modifies the Work under the + Licence, or otherwise contributes to the creation of a Derivative Work. - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and +- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of + the Work under the terms of the Licence. - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and +- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending, + renting, distributing, communicating, transmitting, or otherwise making + available, online or offline, copies of the Work or providing access to its + essential functionalities at the disposal of any other natural or legal + person. - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and +2. Scope of the rights granted by the Licence - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. +The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +sublicensable licence to do the following, for the duration of copyright vested +in the Original Work: - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. +- use the Work in any circumstance and for all usage, +- reproduce the Work, +- modify the Work, and make Derivative Works based upon the Work, +- communicate to the public, including the right to make available or display + the Work or copies thereof to the public and perform publicly, as the case may + be, the Work, +- distribute the Work or copies thereof, +- lend and rent the Work or copies thereof, +- sublicense rights in the Work or copies thereof. - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. +Those rights can be exercised on any media, supports and formats, whether now +known or later invented, as far as the applicable law permits so. - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. +In the countries where moral rights apply, the Licensor waives his right to +exercise his moral right to the extent allowed by law in order to make effective +the licence of the economic rights here above listed. - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. +The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to +any patents held by the Licensor, to the extent necessary to make use of the +rights granted on the Work under this Licence. - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. +3. Communication of the Source Code - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. +The Licensor may provide the Work either in its Source Code form, or as +Executable Code. If the Work is provided as Executable Code, the Licensor +provides in addition a machine-readable copy of the Source Code of the Work +along with each copy of the Work that the Licensor distributes or indicates, in +a notice following the copyright notice attached to the Work, a repository where +the Source Code is easily and freely accessible for as long as the Licensor +continues to distribute or communicate the Work. - END OF TERMS AND CONDITIONS +4. Limitations on copyright - APPENDIX: How to apply the Apache License to your work. +Nothing in this Licence is intended to deprive the Licensee of the benefits from +any exception or limitation to the exclusive rights of the rights owners in the +Work, of the exhaustion of those rights or of other applicable limitations +thereto. - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. +5. Obligations of the Licensee - Copyright [yyyy] [name of copyright owner] +The grant of the rights mentioned above is subject to some restrictions and +obligations imposed on the Licensee. Those obligations are the following: - 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 +Attribution right: The Licensee shall keep intact all copyright, patent or +trademarks notices and all notices that refer to the Licence and to the +disclaimer of warranties. The Licensee must include a copy of such notices and a +copy of the Licence with every copy of the Work he/she distributes or +communicates. The Licensee must cause any Derivative Work to carry prominent +notices stating that the Work has been modified and the date of modification. - http://www.apache.org/licenses/LICENSE-2.0 +Copyleft clause: If the Licensee distributes or communicates copies of the +Original Works or Derivative Works, this Distribution or Communication will be +done under the terms of this Licence or of a later version of this Licence +unless the Original Work is expressly distributed only under this version of the +Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee +(becoming Licensor) cannot offer or impose any additional terms or conditions on +the Work or Derivative Work that alter or restrict the terms of the Licence. - 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. +Compatibility clause: If the Licensee Distributes or Communicates Derivative +Works or copies thereof based upon both the Work and another work licensed under +a Compatible Licence, this Distribution or Communication can be done under the +terms of this Compatible Licence. For the sake of this clause, ‘Compatible +Licence’ refers to the licences listed in the appendix attached to this Licence. +Should the Licensee's obligations under the Compatible Licence conflict with +his/her obligations under this Licence, the obligations of the Compatible +Licence shall prevail. + +Provision of Source Code: When distributing or communicating copies of the Work, +the Licensee will provide a machine-readable copy of the Source Code or indicate +a repository where this Source will be easily and freely available for as long +as the Licensee continues to distribute or communicate the Work. + +Legal Protection: This Licence does not grant permission to use the trade names, +trademarks, service marks, or names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the copyright notice. + +6. Chain of Authorship + +The original Licensor warrants that the copyright in the Original Work granted +hereunder is owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each Contributor warrants that the copyright in the modifications he/she brings +to the Work are owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each time You accept the Licence, the original Licensor and subsequent +Contributors grant You a licence to their contributions to the Work, under the +terms of this Licence. + +7. Disclaimer of Warranty + +The Work is a work in progress, which is continuously improved by numerous +Contributors. It is not a finished work and may therefore contain defects or +‘bugs’ inherent to this type of development. + +For the above reason, the Work is provided under the Licence on an ‘as is’ basis +and without warranties of any kind concerning the Work, including without +limitation merchantability, fitness for a particular purpose, absence of defects +or errors, accuracy, non-infringement of intellectual property rights other than +copyright as stated in Article 6 of this Licence. + +This disclaimer of warranty is an essential part of the Licence and a condition +for the grant of any rights to the Work. + +8. Disclaimer of Liability + +Except in the cases of wilful misconduct or damages directly caused to natural +persons, the Licensor will in no event be liable for any direct or indirect, +material or moral, damages of any kind, arising out of the Licence or of the use +of the Work, including without limitation, damages for loss of goodwill, work +stoppage, computer failure or malfunction, loss of data or any commercial +damage, even if the Licensor has been advised of the possibility of such damage. +However, the Licensor will be liable under statutory product liability laws as +far such laws apply to the Work. + +9. Additional agreements + +While distributing the Work, You may choose to conclude an additional agreement, +defining obligations or services consistent with this Licence. However, if +accepting obligations, You may act only on your own behalf and on your sole +responsibility, not on behalf of the original Licensor or any other Contributor, +and only if You agree to indemnify, defend, and hold each Contributor harmless +for any liability incurred by, or claims asserted against such Contributor by +the fact You have accepted any warranty or additional liability. + +10. Acceptance of the Licence + +The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ +placed under the bottom of a window displaying the text of this Licence or by +affirming consent in any other similar way, in accordance with the rules of +applicable law. Clicking on that icon indicates your clear and irrevocable +acceptance of this Licence and all of its terms and conditions. + +Similarly, you irrevocably accept this Licence and all of its terms and +conditions by exercising any rights granted to You by Article 2 of this Licence, +such as the use of the Work, the creation by You of a Derivative Work or the +Distribution or Communication by You of the Work or copies thereof. + +11. Information to the public + +In case of any Distribution or Communication of the Work by means of electronic +communication by You (for example, by offering to download the Work from a +remote location) the distribution channel or media (for example, a website) must +at least provide to the public the information requested by the applicable law +regarding the Licensor, the Licence and the way it may be accessible, concluded, +stored and reproduced by the Licensee. + +12. Termination of the Licence + +The Licence and the rights granted hereunder will terminate automatically upon +any breach by the Licensee of the terms of the Licence. + +Such a termination will not terminate the licences of any person who has +received the Work from the Licensee under the Licence, provided such persons +remain in full compliance with the Licence. + +13. Miscellaneous + +Without prejudice of Article 9 above, the Licence represents the complete +agreement between the Parties as to the Work. + +If any provision of the Licence is invalid or unenforceable under applicable +law, this will not affect the validity or enforceability of the Licence as a +whole. Such provision will be construed or reformed so as necessary to make it +valid and enforceable. + +The European Commission may publish other linguistic versions or new versions of +this Licence or updated versions of the Appendix, so far this is required and +reasonable, without reducing the scope of the rights granted by the Licence. New +versions of the Licence will be published with a unique version number. + +All linguistic versions of this Licence, approved by the European Commission, +have identical value. Parties can take advantage of the linguistic version of +their choice. + +14. Jurisdiction + +Without prejudice to specific agreement between parties, + +- any litigation resulting from the interpretation of this License, arising + between the European Union institutions, bodies, offices or agencies, as a + Licensor, and any Licensee, will be subject to the jurisdiction of the Court + of Justice of the European Union, as laid down in article 272 of the Treaty on + the Functioning of the European Union, + +- any litigation arising between other parties and resulting from the + interpretation of this License, will be subject to the exclusive jurisdiction + of the competent court where the Licensor resides or conducts its primary + business. + +15. Applicable Law + +Without prejudice to specific agreement between parties, + +- this Licence shall be governed by the law of the European Union Member State + where the Licensor has his seat, resides or has his registered office, + +- this licence shall be governed by Belgian law if the Licensor has no seat, + residence or registered office inside a European Union Member State. + +Appendix + +‘Compatible Licences’ according to Article 5 EUPL are: + +- GNU General Public License (GPL) v. 2, v. 3 +- GNU Affero General Public License (AGPL) v. 3 +- Open Software License (OSL) v. 2.1, v. 3.0 +- Eclipse Public License (EPL) v. 1.0 +- CeCILL v. 2.0, v. 2.1 +- Mozilla Public Licence (MPL) v. 2 +- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for + works other than software +- European Union Public Licence (EUPL) v. 1.1, v. 1.2 +- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong + Reciprocity (LiLiQ-R+). + +The European Commission may update this Appendix to later versions of the above +licences without producing a new version of the EUPL, as long as they provide +the rights granted in Article 2 of this Licence and protect the covered Source +Code from exclusive appropriation. + +All other changes or additions to this Appendix require the production of a new +EUPL version. diff --git a/README.md b/README.md index d57d9b6..cd59d4d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,15 @@ # Keycloak Metrics -Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [22-26](.github/workflows/pr.yaml#L48-L53). +Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [22-26](.woodpecker/verify.yaml#L7-L11). -[![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/kokuwaio/keycloak-event-metrics.svg?label=License)](http://www.apache.org/licenses/) [![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) -[![Build](https://img.shields.io/github/actions/workflow/status/kokuwaio/keycloak-event-metrics/build.yaml?label=Build)](https://github.com/kokuwaio/keycloak-event-metrics/actions/workflows/build.yaml) +[![pulls](https://img.shields.io/docker/pulls/kokuwaio/keycloak-event-metrics)](https://hub.docker.com/r/kokuwaio/keycloak-event-metrics) +[![size](https://img.shields.io/docker/image-size/kokuwaio/keycloak-event-metrics)](https://hub.docker.com/r/kokuwaio/keycloak-event-metrics) +[![dockerfile](https://img.shields.io/badge/source-Dockerfile%20-blue)](https://git.kokuwa.io/keycloak/keycloak-event-metrics/src/branch/main/Dockerfile) +[![license](https://img.shields.io/badge/License-EUPL%201.2-blue)](https://git.kokuwa.io/keycloak/keycloak-event-metrics/src/branch/main/LICENSE) +[![prs](https://img.shields.io/gitea/pull-requests/open/keycloak/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/keycloak/keycloak-event-metrics/pulls) +[![issues](https://img.shields.io/gitea/issues/open/keycloak/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/keycloak/keycloak-event-metrics/issues) +[![build](https://ci.kokuwa.io/api/badges/keycloak/keycloak-event-metrics/status.svg)](https://ci.kokuwa.io/repos/keycloak/keycloak-event-metrics/) ## Why? @@ -114,7 +119,7 @@ If scrapping takes less than `KC_METRICS_STATS_INFO_THRESHOLD` duration will be ### Grafana Dashboard -Can be found here: [kokuwaio/keycloak keycloak-metrics.json](https://github.com/kokuwaio/keycloak/blob/main/src/test/k3s/dev/grafana/files/dashboards/keycloak-metrics.json) +Can be found here: [keycloak-metrics.json](https://git.kokuwa.io/keycloak/keycloak/blob/main/src/test/k3s/dev/grafana/files/dashboards/keycloak-metrics.json) ### Testcontainers @@ -131,7 +136,7 @@ This images are based on busybox, so you can use cp to copy the jar into your ke ### Docker -Check: [kokuwaio/keycloak](https://github.com/kokuwaio/keycloak) +Check: [kowaio/keycloak](https://git.kokuwa.io/keycloak/keycloak) Dockerfile: @@ -145,7 +150,7 @@ FROM debian:stable-slim AS metrics RUN apt-get -qq update RUN apt-get -qq install --yes --no-install-recommends ca-certificates wget -ARG METRICS_VERSION=1.0.0 +ARG METRICS_VERSION=2.0.0 ARG METRICS_FILE=keycloak-event-metrics-${METRICS_VERSION}.jar ARG METRICS_URL=https://repo1.maven.org/maven2/io/kokuwa/keycloak/keycloak-event-metrics/${METRICS_VERSION} @@ -159,7 +164,7 @@ RUN mv ${METRICS_FILE} /opt/keycloak/providers ### build keycloak with metrics ### -FROM quay.io/keycloak/keycloak:25.0.1 +FROM quay.io/keycloak/keycloak:25.2.5 ENV KEYCLOAK_ADMIN=admin ENV KEYCLOAK_ADMIN_PASSWORD=password diff --git a/pom.xml b/pom.xml index 8e26d7f..4ed00e1 100644 --- a/pom.xml +++ b/pom.xml @@ -4,11 +4,11 @@ io.kokuwa.keycloak keycloak-event-metrics - 1.1.2-SNAPSHOT + 2.0.0-SNAPSHOT Keycloak Metrics Provides metrics for Keycloak user/admin events - https://github.com/kokuwaio/keycloak-event-metrics + https://git.kokuwa.io/keycloak/keycloak-event-metrics 2023 Kokuwa.io @@ -16,8 +16,8 @@ - Apache-2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt + EUPL-1.2 + https://eupl.eu/1.2/en repo @@ -33,27 +33,23 @@ - https://github.com/kokuwaio/keycloak-event-metrics - scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git - scm:git:https://github.com/kokuwaio/keycloak-event-metrics.git + https://git.kokuwa.io/keycloak/keycloak-event-metrics + scm:git:https://git.kokuwa.io/keycloak/keycloak-event-metrics.git + scm:git:https://git.kokuwa.io/keycloak/keycloak-event-metrics.git HEAD - github - https://github.com/kokuwaio/keycloak-event-metrics/issues + forgejo + https://git.kokuwa.io/keycloak/keycloak-event-metrics/issues - github - https://github.com/kokuwaio/keycloak-event-metrics/actions + woodpecker + https://ci.kokuwa.io/repos/keycloak/keycloak-event-metrics - - sonatype-nexus - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - sonatype-nexus - https://oss.sonatype.org/content/repositories/snapshots/ + sonatype.org + https://central.sonatype.com/repository/maven-snapshots/ @@ -83,28 +79,8 @@ - 3.4.1 - 3.14.0 - 3.1.4 - 3.2.7 - 3.1.4 - 3.4.2 - 3.11.2 - 3.1.1 - 3.3.1 - 3.21.0 - 3.3.1 - 3.5.3 - 1.4.0 - 2.18.0 - 1.7.0 - 2.26.0 - 1.12.0 - 0.46.0 - 26.2.5 ${version.org.keycloak} - 1.18.3 @@ -153,6 +129,15 @@ org.jboss.resteasy resteasy-multipart-provider + + + com.sun.istack + istack-commons-tools + + + com.sun.istack + istack-commons-runtime + @@ -219,6 +204,7 @@ + ${project.artifactId} ${project.basedir}/src/test/resources @@ -227,15 +213,10 @@ - - org.apache.maven.plugins - maven-clean-plugin - ${version.org.apache.maven.plugins.clean} - org.apache.maven.plugins maven-compiler-plugin - ${version.org.apache.maven.plugins.compiler} + 3.14.0 ${maven.compiler.compilerArgument} @@ -243,41 +224,41 @@ org.apache.maven.plugins maven-deploy-plugin - ${version.org.apache.maven.plugins.deploy} + 3.1.4 org.apache.maven.plugins maven-failsafe-plugin - ${version.org.apache.maven.plugins.surefire} + 3.5.3 org.apache.maven.plugins maven-gpg-plugin - ${version.org.apache.maven.plugins.gpg} + 3.2.7 org.apache.maven.plugins maven-install-plugin - ${version.org.apache.maven.plugins.install} + 3.1.4 org.apache.maven.plugins maven-jar-plugin - ${version.org.apache.maven.plugins.jar} + 3.4.2 org.apache.maven.plugins maven-javadoc-plugin - ${version.org.apache.maven.plugins.javadoc} + 3.11.2 org.apache.maven.plugins maven-release-plugin - ${version.org.apache.maven.plugins.release} + 3.1.1 - clean verify + test check - deploy + deploy -DskipITs deploy,release true @{prefix} prepare release @{releaseLabel} [CI SKIP] @@ -287,7 +268,7 @@ org.apache.maven.plugins maven-resources-plugin - ${version.org.apache.maven.plugins.resources} + 3.3.1 ${project.build.propertiesEncoding} @@ -295,43 +276,32 @@ org.apache.maven.plugins maven-site-plugin - ${version.org.apache.maven.plugins.site} + 3.21.0 org.apache.maven.plugins maven-source-plugin - ${version.org.apache.maven.plugins.source} + 3.3.1 org.apache.maven.plugins maven-surefire-plugin - ${version.org.apache.maven.plugins.surefire} + 3.5.3 org.codehaus.mojo tidy-maven-plugin - ${version.org.codehaus.mojo.tidy} + 1.4.0 - org.codehaus.mojo - versions-maven-plugin - ${version.org.codehaus.mojo.versions} - - false - - ^.*-(alpha|beta|M)-?[0-9]+$ - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - ${version.org.sonatype.plugins.nexus} + org.sonatype.central + central-publishing-maven-plugin + 0.8.0 net.revelc.code.formatter formatter-maven-plugin - ${version.net.revelc.code.formatter} + 2.26.0 ${formatter.configFile} @@ -339,12 +309,7 @@ net.revelc.code impsort-maven-plugin - ${version.net.revelc.code.impsort} - - - io.fabric8 - docker-maven-plugin - ${version.io.fabric8.docker} + 1.12.0 @@ -496,7 +461,7 @@ - jar-no-fork + jar @@ -507,109 +472,12 @@ - javadoc-no-fork + jar - - - io.fabric8 - docker-maven-plugin - - - build - install - - build - - - - push - deploy - - push - - - - - build - - - docker.io/kokuwaio/keycloak-event-metrics:${project.version} - - docker.io/library/busybox:1.37.0-uclibc@sha256:cc57e0ff4b6d3138931ff5c7180d18078813300e2508a25fb767a4d36df30d4d - - ${file.separator} - - - - ${project.build.directory}/${project.build.finalName}.jar - ${project.artifactId}.jar - 444 - - - - - - - ${project.name} - ${project.description} - ${project.url} - ${project.scm.url} - ${project.organization.name} - https://github.com/orgs/kokuwaio/people - ${project.licenses[0].name} - ${project.version} - docker.io/library/busybox:1.37.0-uclibc - sha256:cc57e0ff4b6d3138931ff5c7180d18078813300e2508a25fb767a4d36df30d4d - - - - - ghcr.io/kokuwaio/keycloak-event-metrics:${project.version} - - docker.io/library/busybox:1.37.0-uclibc@sha256:cc57e0ff4b6d3138931ff5c7180d18078813300e2508a25fb767a4d36df30d4d - - ${file.separator} - - - - ${project.build.directory}/${project.build.finalName}.jar - ${project.artifactId}.jar - 444 - - - - - - - ${project.name} - ${project.description} - ${project.url} - ${project.scm.url} - ${project.organization.name} - https://github.com/orgs/kokuwaio/people - ${project.licenses[0].name} - ${project.version} - docker.io/library/busybox:1.37.0-uclibc - sha256:cc57e0ff4b6d3138931ff5c7180d18078813300e2508a25fb767a4d36df30d4d - - - - - - - - - - - - release - - - org.apache.maven.plugins @@ -619,22 +487,31 @@ sign + + bc + - - - org.sonatype.plugins - nexus-staging-maven-plugin - true - - sonatype-nexus - https://oss.sonatype.org/ - true - - - + + + + + release + + + + org.sonatype.central + central-publishing-maven-plugin + true + + true + sonatype.org + true + published + + diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..dc88820 --- /dev/null +++ b/renovate.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["local>infrastructure/renovate-config", ":reviewer(stephan.schnabel)"], + "pinDigests": false +} diff --git a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java index 91f013f..aa179f7 100644 --- a/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java +++ b/src/test/java/io/kokuwa/keycloak/metrics/junit/KeycloakExtension.java @@ -15,6 +15,7 @@ import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.token.TokenService; +import org.testcontainers.containers.FixedHostPortGenericContainer; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.MountableFile; @@ -45,30 +46,33 @@ public class KeycloakExtension implements BeforeAllCallback, ParameterResolver { throw new Exception("Failed to read properties", e); } var version = properties.getProperty("version"); + var image = "quay.io/keycloak/keycloak:" + version; var jar = properties.getProperty("jar"); var timeout = properties.getProperty("timeout"); - // create and start container + // create and start container - use fixed port in ci - @SuppressWarnings("resource") - var container = new GenericContainer<>("quay.io/keycloak/keycloak:" + version) - .withEnv("KEYCLOAK_ADMIN", "admin") - .withEnv("KEYCLOAK_ADMIN_PASSWORD", "password") - .withEnv("KC_LOG_LEVEL", "io.kokuwa:trace") - // otherwise port 9000 will be used, with this config we can test different keycloak versions - .withEnv("KC_LEGACY_OBSERVABILITY_INTERFACE", "true") - .withEnv("KC_HEALTH_ENABLED", "true") - .withEnv("KC_METRICS_ENABLED", "true") - .withEnv("KC_METRICS_STATS_ENABLED", "true") - .withEnv("KC_METRICS_STATS_INTERVAL", "PT1s") - .withCopyFileToContainer(MountableFile.forHostPath(jar), "/opt/keycloak/providers/metrics.jar") - .withLogConsumer(out -> System.out.print(out.getUtf8String())) - .withExposedPorts(8080) - .withStartupTimeout(Duration.parse(timeout)) - .waitingFor(Wait.forHttp("/health").forPort(8080)) - .withCommand("start-dev"); + @SuppressWarnings({ "resource", "deprecation" }) + var container = (System.getenv("CI") == null + ? new GenericContainer<>(image).withExposedPorts(8080) + : new FixedHostPortGenericContainer<>(image).withFixedExposedPort(8080, 8080)); try { - container.start(); + container + .withEnv("KEYCLOAK_ADMIN", "admin") + .withEnv("KEYCLOAK_ADMIN_PASSWORD", "password") + .withEnv("KC_LOG_LEVEL", "io.kokuwa:trace") + // otherwise port 9000 will be used, with this config we can test different keycloak versions + .withEnv("KC_LEGACY_OBSERVABILITY_INTERFACE", "true") + .withEnv("KC_HEALTH_ENABLED", "true") + .withEnv("KC_METRICS_ENABLED", "true") + .withEnv("KC_METRICS_STATS_ENABLED", "true") + .withEnv("KC_METRICS_STATS_INTERVAL", "PT1s") + .withCopyFileToContainer(MountableFile.forHostPath(jar), "/opt/keycloak/providers/metrics.jar") + .withLogConsumer(out -> System.out.print(out.getUtf8String())) + .withStartupTimeout(Duration.parse(timeout)) + .waitingFor(Wait.forHttp("/health").forPort(8080).withStartupTimeout(Duration.ofMinutes(10))) + .withCommand("start-dev") + .start(); } catch (RuntimeException e) { throw new Exception("Failed to start keycloak", e); } From 10b4312fc50d7b2027095559952e0c2ea2522726 Mon Sep 17 00:00:00 2001 From: Woodpecker Date: Wed, 25 Jun 2025 14:15:36 +0000 Subject: [PATCH 86/93] [maven-release-plugin] prepare release 2.0.0 [CI SKIP] --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 4ed00e1..8802b9e 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.kokuwa.keycloak keycloak-event-metrics - 2.0.0-SNAPSHOT + 2.0.0 Keycloak Metrics Provides metrics for Keycloak user/admin events @@ -36,7 +36,7 @@ https://git.kokuwa.io/keycloak/keycloak-event-metrics scm:git:https://git.kokuwa.io/keycloak/keycloak-event-metrics.git scm:git:https://git.kokuwa.io/keycloak/keycloak-event-metrics.git - HEAD + 2.0.0 forgejo @@ -59,7 +59,7 @@ - 2025-04-28T12:25:49Z + 2025-06-25T14:15:09Z UTF-8 ISO-8859-1 From 964bc985186418c5efa98652d54576acc48680f4 Mon Sep 17 00:00:00 2001 From: Woodpecker Date: Wed, 25 Jun 2025 14:15:39 +0000 Subject: [PATCH 87/93] [maven-release-plugin] prepare for next development iteration --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 8802b9e..c610000 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.kokuwa.keycloak keycloak-event-metrics - 2.0.0 + 2.0.1-SNAPSHOT Keycloak Metrics Provides metrics for Keycloak user/admin events @@ -36,7 +36,7 @@ https://git.kokuwa.io/keycloak/keycloak-event-metrics scm:git:https://git.kokuwa.io/keycloak/keycloak-event-metrics.git scm:git:https://git.kokuwa.io/keycloak/keycloak-event-metrics.git - 2.0.0 + HEAD forgejo @@ -59,7 +59,7 @@ - 2025-06-25T14:15:09Z + 2025-06-25T14:15:39Z UTF-8 ISO-8859-1 From efb009aaef10866b5de1ae3e9f9be7ae900ec8aa Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Wed, 25 Jun 2025 19:44:59 +0200 Subject: [PATCH 88/93] Rename to `kokuwaio/keycloak-event-metrics` --- .woodpecker/deploy.yaml | 2 +- .woodpecker/dockerhub.yaml | 2 +- .woodpecker/release.yaml | 2 +- README.md | 10 +++++----- pom.xml | 1 - 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.woodpecker/deploy.yaml b/.woodpecker/deploy.yaml index 53976dc..a562c15 100644 --- a/.woodpecker/deploy.yaml +++ b/.woodpecker/deploy.yaml @@ -1,6 +1,6 @@ when: instance: ci.kokuwa.io - repo: keycloak/keycloak-event-metrics + repo: kokuwaio/keycloak-event-metrics event: [manual, push] branch: main path: [.woodpecker/deploy.yaml, Dockerfile, pom.xml, src/main/**] diff --git a/.woodpecker/dockerhub.yaml b/.woodpecker/dockerhub.yaml index a443560..df265b7 100644 --- a/.woodpecker/dockerhub.yaml +++ b/.woodpecker/dockerhub.yaml @@ -1,6 +1,6 @@ when: instance: ci.kokuwa.io - repo: keycloak/keycloak-event-metrics + repo: kokuwaio/keycloak-event-metrics event: [manual, push] branch: main path: [.woodpecker/dockerhub.yaml, README.md] diff --git a/.woodpecker/release.yaml b/.woodpecker/release.yaml index 8ec3522..5d560ab 100644 --- a/.woodpecker/release.yaml +++ b/.woodpecker/release.yaml @@ -1,6 +1,6 @@ when: instance: ci.kokuwa.io - repo: keycloak/keycloak-event-metrics + repo: kokuwaio/keycloak-event-metrics event: deployment branch: main diff --git a/README.md b/README.md index cd59d4d..e0802e1 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@ Provides metrics for Keycloak user/admin events and user/client/session count. T [![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) [![pulls](https://img.shields.io/docker/pulls/kokuwaio/keycloak-event-metrics)](https://hub.docker.com/r/kokuwaio/keycloak-event-metrics) [![size](https://img.shields.io/docker/image-size/kokuwaio/keycloak-event-metrics)](https://hub.docker.com/r/kokuwaio/keycloak-event-metrics) -[![dockerfile](https://img.shields.io/badge/source-Dockerfile%20-blue)](https://git.kokuwa.io/keycloak/keycloak-event-metrics/src/branch/main/Dockerfile) -[![license](https://img.shields.io/badge/License-EUPL%201.2-blue)](https://git.kokuwa.io/keycloak/keycloak-event-metrics/src/branch/main/LICENSE) -[![prs](https://img.shields.io/gitea/pull-requests/open/keycloak/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/keycloak/keycloak-event-metrics/pulls) -[![issues](https://img.shields.io/gitea/issues/open/keycloak/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/keycloak/keycloak-event-metrics/issues) -[![build](https://ci.kokuwa.io/api/badges/keycloak/keycloak-event-metrics/status.svg)](https://ci.kokuwa.io/repos/keycloak/keycloak-event-metrics/) +[![dockerfile](https://img.shields.io/badge/source-Dockerfile%20-blue)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/src/branch/main/Dockerfile) +[![license](https://img.shields.io/badge/License-EUPL%201.2-blue)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/src/branch/main/LICENSE) +[![prs](https://img.shields.io/gitea/pull-requests/open/kokuwaio/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/pulls) +[![issues](https://img.shields.io/gitea/issues/open/kokuwaio/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/issues) +[![build](https://ci.kokuwa.io/api/badges/kokuwaio/keycloak-event-metrics/status.svg)](https://ci.kokuwa.io/repos/kokuwaio/keycloak-event-metrics/) ## Why? diff --git a/pom.xml b/pom.xml index c610000..30c1b44 100644 --- a/pom.xml +++ b/pom.xml @@ -506,7 +506,6 @@ central-publishing-maven-plugin true - true sonatype.org true published From 4c5e97e0de37b13d20dc5121be259c0d744752a0 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Wed, 25 Jun 2025 20:40:06 +0200 Subject: [PATCH 89/93] Add Github README. --- .github/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/README.md diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 0000000..662ce3d --- /dev/null +++ b/.github/README.md @@ -0,0 +1,14 @@ +# Keycloak Metrics + +Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [22-26](.woodpecker/verify.yaml#L7-L11). + +[![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) +[![pulls](https://img.shields.io/docker/pulls/kokuwaio/keycloak-event-metrics)](https://hub.docker.com/r/kokuwaio/keycloak-event-metrics) +[![size](https://img.shields.io/docker/image-size/kokuwaio/keycloak-event-metrics)](https://hub.docker.com/r/kokuwaio/keycloak-event-metrics) +[![dockerfile](https://img.shields.io/badge/source-Dockerfile%20-blue)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/src/branch/main/Dockerfile) +[![license](https://img.shields.io/badge/License-EUPL%201.2-blue)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/src/branch/main/LICENSE) +[![prs](https://img.shields.io/gitea/pull-requests/open/kokuwaio/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/pulls) +[![issues](https://img.shields.io/gitea/issues/open/kokuwaio/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/issues) +[![build](https://ci.kokuwa.io/api/badges/kokuwaio/keycloak-event-metrics/status.svg)](https://ci.kokuwa.io/repos/kokuwaio/keycloak-event-metrics/) + +For more documention see: [git.kokuwa.io/kokuwaio/keycloak-event-metrics](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics) From ad4604e5a85f59618a2eba2e5d196ccf094c00f9 Mon Sep 17 00:00:00 2001 From: Renovate Date: Thu, 26 Jun 2025 03:03:26 +0000 Subject: [PATCH 90/93] chore(deps): update dependency net.revelc.code.formatter:formatter-maven-plugin from 2.26.0 to 2.27.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 30c1b44..96f8bce 100644 --- a/pom.xml +++ b/pom.xml @@ -301,7 +301,7 @@ net.revelc.code.formatter formatter-maven-plugin - 2.26.0 + 2.27.0 ${formatter.configFile} From 9277ad3afcf6f0e8830a736b3a82752f319adacf Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Thu, 26 Jun 2025 21:25:10 +0200 Subject: [PATCH 91/93] chore: fix repo urls in `pom.xml` --- pom.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 96f8bce..ea2dea8 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ Keycloak Metrics Provides metrics for Keycloak user/admin events - https://git.kokuwa.io/keycloak/keycloak-event-metrics + https://git.kokuwa.io/kokuwaio/keycloak-event-metrics 2023 Kokuwa.io @@ -33,18 +33,18 @@ - https://git.kokuwa.io/keycloak/keycloak-event-metrics - scm:git:https://git.kokuwa.io/keycloak/keycloak-event-metrics.git - scm:git:https://git.kokuwa.io/keycloak/keycloak-event-metrics.git + https://git.kokuwa.io/kokuwaio/keycloak-event-metrics + scm:git:https://git.kokuwa.io/kokuwaio/keycloak-event-metrics.git + scm:git:https://git.kokuwa.io/kokuwaio/keycloak-event-metrics.git HEAD forgejo - https://git.kokuwa.io/keycloak/keycloak-event-metrics/issues + https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/issues woodpecker - https://ci.kokuwa.io/repos/keycloak/keycloak-event-metrics + https://ci.kokuwa.io/repos/kokuwaio/keycloak-event-metrics @@ -454,7 +454,7 @@ - + org.apache.maven.plugins maven-source-plugin From cafd9647007e2f2caedd27d82f636f8cdc13feba Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Fri, 27 Jun 2025 11:38:37 +0200 Subject: [PATCH 92/93] chore: fix renovate preset location --- renovate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index dc88820..c59fb01 100644 --- a/renovate.json +++ b/renovate.json @@ -1,5 +1,5 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["local>infrastructure/renovate-config", ":reviewer(stephan.schnabel)"], + "extends": ["local>kokuwaio/renovate-config", ":reviewer(stephan.schnabel)"], "pinDigests": false } From beb356e75f76cb20def0e1744ba5f2065b2be03d Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Fri, 27 Jun 2025 21:01:24 +0200 Subject: [PATCH 93/93] chore: remove github actions --- .github/README.md | 6 +++--- .github/workflows/build.yaml | 42 ------------------------------------ .github/workflows/lint.yaml | 23 -------------------- .woodpecker/deploy.yaml | 13 ++++++++++- .woodpecker/dockerhub.yaml | 17 --------------- .yamllint.yaml | 4 ---- README.md | 6 +++--- 7 files changed, 18 insertions(+), 93 deletions(-) delete mode 100644 .github/workflows/build.yaml delete mode 100644 .github/workflows/lint.yaml delete mode 100644 .woodpecker/dockerhub.yaml diff --git a/.github/README.md b/.github/README.md index 662ce3d..b95b40f 100644 --- a/.github/README.md +++ b/.github/README.md @@ -2,13 +2,13 @@ Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [22-26](.woodpecker/verify.yaml#L7-L11). -[![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) +[![maven](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=maven)](https://central.sonatype.com/artifact/io.kokuwa.keycloak/keycloak-event-metrics) [![pulls](https://img.shields.io/docker/pulls/kokuwaio/keycloak-event-metrics)](https://hub.docker.com/r/kokuwaio/keycloak-event-metrics) [![size](https://img.shields.io/docker/image-size/kokuwaio/keycloak-event-metrics)](https://hub.docker.com/r/kokuwaio/keycloak-event-metrics) [![dockerfile](https://img.shields.io/badge/source-Dockerfile%20-blue)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/src/branch/main/Dockerfile) -[![license](https://img.shields.io/badge/License-EUPL%201.2-blue)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/src/branch/main/LICENSE) -[![prs](https://img.shields.io/gitea/pull-requests/open/kokuwaio/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/pulls) +[![license](https://img.shields.io/badge/license-EUPL%201.2-blue)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/src/branch/main/LICENSE) [![issues](https://img.shields.io/gitea/issues/open/kokuwaio/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/issues) +[![prs](https://img.shields.io/gitea/pull-requests/open/kokuwaio/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/pulls) [![build](https://ci.kokuwa.io/api/badges/kokuwaio/keycloak-event-metrics/status.svg)](https://ci.kokuwa.io/repos/kokuwaio/keycloak-event-metrics/) For more documention see: [git.kokuwa.io/kokuwaio/keycloak-event-metrics](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml deleted file mode 100644 index 5d30921..0000000 --- a/.github/workflows/build.yaml +++ /dev/null @@ -1,42 +0,0 @@ -name: Verify - -on: - - pull_request - - push: - branches: [main] - -env: - MAVEN_ARGS: --batch-mode --color=always --no-transfer-progress - -jobs: - - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@main - - uses: actions/setup-java@main - with: - distribution: temurin - java-version: 17 - cache: maven - - run: mvn verify - - versions: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - version: - - 22.0.5 - - 23.0.7 - - 24.0.5 - - 25.0.6 - - 26.2.5 - steps: - - uses: actions/checkout@main - - uses: actions/setup-java@main - with: - distribution: temurin - java-version: 17 - cache: maven - - run: mvn verify -Dversion.org.keycloak.test=${{ matrix.version }} diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml deleted file mode 100644 index af980fa..0000000 --- a/.github/workflows/lint.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: Lint - -on: push - -jobs: - - renovate: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@main - - uses: docker://kokuwaio/renovate-config-validator - - markdownlint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@main - - uses: docker://kokuwaio/markdownlint - - yamllint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@main - - uses: docker://kokuwaio/yamllint diff --git a/.woodpecker/deploy.yaml b/.woodpecker/deploy.yaml index a562c15..7916e19 100644 --- a/.woodpecker/deploy.yaml +++ b/.woodpecker/deploy.yaml @@ -3,7 +3,7 @@ when: repo: kokuwaio/keycloak-event-metrics event: [manual, push] branch: main - path: [.woodpecker/deploy.yaml, Dockerfile, pom.xml, src/main/**] + path: [.woodpecker/deploy.yaml, README.md, Dockerfile, pom.xml, src/main/**] services: - name: dockerd @@ -48,3 +48,14 @@ steps: org.opencontainers.image.licenses: EUPL-1.2 org.opencontainers.image.ref.name: kokuwaio/keycloak-event-metrics org.opencontainers.image.version: snapshot + + dockerhub: + image: kokuwaio/dockerhub-metadata + settings: + repository: kokuwaio/keycloak-event-metrics + description-short: Provides metrics for Keycloak user/admin events and user/client/session count. + categories: monitoring-and-observability + username: {from_secret: dockerhub_username} + password: {from_secret: dockerhub_password} + when: + path: [README.md] diff --git a/.woodpecker/dockerhub.yaml b/.woodpecker/dockerhub.yaml deleted file mode 100644 index df265b7..0000000 --- a/.woodpecker/dockerhub.yaml +++ /dev/null @@ -1,17 +0,0 @@ -when: - instance: ci.kokuwa.io - repo: kokuwaio/keycloak-event-metrics - event: [manual, push] - branch: main - path: [.woodpecker/dockerhub.yaml, README.md] - -steps: - - metadata: - image: kokuwaio/dockerhub-metadata - settings: - repository: kokuwaio/keycloak-event-metrics - description-short: Provides metrics for Keycloak user/admin events and user/client/session count. - categories: monitoring-and-observability - username: {from_secret: dockerhub_username} - password: {from_secret: dockerhub_password} diff --git a/.yamllint.yaml b/.yamllint.yaml index 8011808..21966f2 100644 --- a/.yamllint.yaml +++ b/.yamllint.yaml @@ -13,7 +13,3 @@ rules: quoted-strings: quote-type: double required: only-when-needed - - # allow everything on keys - truthy: - check-keys: false diff --git a/README.md b/README.md index e0802e1..b7d0bb0 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,13 @@ Provides metrics for Keycloak user/admin events and user/client/session count. Tested on Keycloak [22-26](.woodpecker/verify.yaml#L7-L11). -[![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=Maven%20Central)](https://central.sonatype.com/search?namespace=io.kokuwa.keycloak&q=keycloak-event-metrics) +[![maven](https://img.shields.io/maven-central/v/io.kokuwa.keycloak/keycloak-event-metrics.svg?label=maven)](https://central.sonatype.com/artifact/io.kokuwa.keycloak/keycloak-event-metrics) [![pulls](https://img.shields.io/docker/pulls/kokuwaio/keycloak-event-metrics)](https://hub.docker.com/r/kokuwaio/keycloak-event-metrics) [![size](https://img.shields.io/docker/image-size/kokuwaio/keycloak-event-metrics)](https://hub.docker.com/r/kokuwaio/keycloak-event-metrics) [![dockerfile](https://img.shields.io/badge/source-Dockerfile%20-blue)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/src/branch/main/Dockerfile) -[![license](https://img.shields.io/badge/License-EUPL%201.2-blue)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/src/branch/main/LICENSE) -[![prs](https://img.shields.io/gitea/pull-requests/open/kokuwaio/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/pulls) +[![license](https://img.shields.io/badge/license-EUPL%201.2-blue)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/src/branch/main/LICENSE) [![issues](https://img.shields.io/gitea/issues/open/kokuwaio/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/issues) +[![prs](https://img.shields.io/gitea/pull-requests/open/kokuwaio/keycloak-event-metrics?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/keycloak-event-metrics/pulls) [![build](https://ci.kokuwa.io/api/badges/kokuwaio/keycloak-event-metrics/status.svg)](https://ci.kokuwa.io/repos/kokuwaio/keycloak-event-metrics/) ## Why?