added a few gauges updated on a timer
This commit is contained in:
parent
ca966a4c6b
commit
d88e22d899
3 changed files with 83 additions and 4 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*~
|
||||||
|
target/
|
16
docker-compose.yml
Normal file
16
docker-compose.yml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
keycloak:
|
||||||
|
image: quay.io/keycloak/keycloak:21.0.2
|
||||||
|
environment:
|
||||||
|
KEYCLOAK_ADMIN: admin
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD: admin
|
||||||
|
KC_HTTP_RELATIVE_PATH: /auth
|
||||||
|
KC_HEALTH_ENABLED: true
|
||||||
|
KC_METRICS_ENABLED: true
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
||||||
|
volumes:
|
||||||
|
- ./target/keycloak-event-metrics-0.2.1-SNAPSHOT.jar:/opt/keycloak/providers/keycloak-event-metrics.jar
|
||||||
|
command: [ "start-dev" ]
|
|
@ -1,15 +1,18 @@
|
||||||
package io.kokuwa.keycloak.metrics;
|
package io.kokuwa.keycloak.metrics;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import io.micrometer.core.instrument.ImmutableTag;
|
||||||
|
import io.micrometer.core.instrument.MeterRegistry;
|
||||||
|
import io.micrometer.core.instrument.Tag;
|
||||||
import javax.enterprise.inject.spi.CDI;
|
import javax.enterprise.inject.spi.CDI;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config.Scope;
|
import org.keycloak.Config.Scope;
|
||||||
import org.keycloak.events.EventListenerProvider;
|
import org.keycloak.events.EventListenerProvider;
|
||||||
import org.keycloak.events.EventListenerProviderFactory;
|
import org.keycloak.events.EventListenerProviderFactory;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import io.micrometer.core.instrument.MeterRegistry;
|
import org.keycloak.timer.TimerProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for {@link MicrometerEventListener}, uses {@link MeterRegistry} from CDI.
|
* Factory for {@link MicrometerEventListener}, uses {@link MeterRegistry} from CDI.
|
||||||
|
@ -18,13 +21,15 @@ import io.micrometer.core.instrument.MeterRegistry;
|
||||||
*/
|
*/
|
||||||
public class MicrometerEventListenerFactory implements EventListenerProviderFactory {
|
public class MicrometerEventListenerFactory implements EventListenerProviderFactory {
|
||||||
|
|
||||||
|
private static final String PROVIDER_ID = "metrics-listener";
|
||||||
|
private static final int INTERVAL = 60 * 1000; //1 MINUTE
|
||||||
private static final Logger log = Logger.getLogger(MicrometerEventListener.class);
|
private static final Logger log = Logger.getLogger(MicrometerEventListener.class);
|
||||||
private MeterRegistry registry;
|
private MeterRegistry registry;
|
||||||
private boolean replace;
|
private boolean replace;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return "metrics-listener";
|
return PROVIDER_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -36,6 +41,17 @@ public class MicrometerEventListenerFactory implements EventListenerProviderFact
|
||||||
@Override
|
@Override
|
||||||
public void postInit(KeycloakSessionFactory factory) {
|
public void postInit(KeycloakSessionFactory factory) {
|
||||||
registry = CDI.current().select(MeterRegistry.class).get();
|
registry = CDI.current().select(MeterRegistry.class).get();
|
||||||
|
|
||||||
|
KeycloakModelUtils.runJobInTransaction(factory, s1 -> {
|
||||||
|
TimerProvider timer = s1.getProvider(TimerProvider.class);
|
||||||
|
log.info("Registering gauge update job TimerProvider");
|
||||||
|
timer.schedule(() -> {
|
||||||
|
KeycloakModelUtils.runJobInTransaction(s1.getKeycloakSessionFactory(), s2 -> {
|
||||||
|
log.info("Updating gauges");
|
||||||
|
updateGauges(s2);
|
||||||
|
});
|
||||||
|
}, INTERVAL, PROVIDER_ID);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -45,4 +61,49 @@ public class MicrometerEventListenerFactory implements EventListenerProviderFact
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {}
|
public void close() {}
|
||||||
|
|
||||||
|
|
||||||
|
private Iterable<Tag> tags(String... tags) {
|
||||||
|
if (tags.length % 2 != 0) throw new IllegalStateException("Tag name value pairs must be even");
|
||||||
|
ImmutableList.Builder<Tag> builder = new ImmutableList.Builder<Tag>();
|
||||||
|
for (int i = 0;i < tags.length;i+=2) {
|
||||||
|
builder.add(new ImmutableTag(tags[i], tags[i+1]));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateGauges(KeycloakSession session) {
|
||||||
|
session.realms().getRealmsStream().forEach(realm -> {
|
||||||
|
// keycloak_users = total number of users
|
||||||
|
registry.gauge("keycloak_users",
|
||||||
|
tags("realm", replace ? realm.getName() : realm.getId()),
|
||||||
|
session.users().getUsersCount(realm));
|
||||||
|
|
||||||
|
// keycloak_clients = total number of clients
|
||||||
|
registry.gauge("keycloak_clients",
|
||||||
|
tags("realm", replace ? realm.getName() : realm.getId()),
|
||||||
|
realm.getClientsCount());
|
||||||
|
|
||||||
|
// sessions - by client
|
||||||
|
|
||||||
|
realm.getClientsStream().forEach(client -> {
|
||||||
|
// keycloak_active_user_sessions
|
||||||
|
registry.gauge("keycloak_active_user_sessions",
|
||||||
|
tags("realm", replace ? realm.getName() : realm.getId(),
|
||||||
|
"client", replace ? client.getClientId() : client.getId()),
|
||||||
|
session.sessions().getActiveUserSessions(realm, client));
|
||||||
|
// keycloak_active_client_sessions
|
||||||
|
registry.gauge("keycloak_active_client_sessions",
|
||||||
|
tags("realm", replace ? realm.getName() : realm.getId(),
|
||||||
|
"client", replace ? client.getClientId() : client.getId()),
|
||||||
|
session.sessions().getActiveClientSessionStats(realm,false).get(client.getId()));
|
||||||
|
|
||||||
|
// keycloak_offline_sessions
|
||||||
|
registry.gauge("keycloak_offline_sessions",
|
||||||
|
tags("realm", replace ? realm.getName() : realm.getId(),
|
||||||
|
"client", replace ? client.getClientId() : client.getId()),
|
||||||
|
session.sessions().getOfflineSessionsCount(realm, client));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue