added DATA_COUNT and DATA_COUNT_INTERVAL params. extracted into separate config.

This commit is contained in:
Garth 2023-04-07 10:42:01 +02:00
parent d88e22d899
commit 3b148f90f7
3 changed files with 104 additions and 50 deletions

View file

@ -0,0 +1,52 @@
package io.kokuwa.keycloak.metrics;
public class MicrometerEventConfig {
private static final String KEY_EVENT_REPLACE_IDS = "KC_METRICS_EVENT_REPLACE_IDS";
private static final String KEY_DATA_COUNT = "KC_METRICS_DATA_COUNT";
private static final String KEY_DATA_COUNT_INTERVAL = "KC_METRICS_DATA_COUNT_INTERVAL";
private static final long DEFAULT_DATA_COUNT_INTERVAL = 60;
private final boolean replaceIds;
private final boolean dataCount;
private final long dataCountInterval;
public static MicrometerEventConfig getConfig() {
long interval = DEFAULT_DATA_COUNT_INTERVAL;
try {
interval = Long.parseLong(System.getenv(KEY_DATA_COUNT_INTERVAL));
} catch (Exception ignore) {}
return new MicrometerEventConfig("true".equals(System.getenv(KEY_EVENT_REPLACE_IDS)),
"true".equals(System.getenv(KEY_DATA_COUNT)),
interval);
}
private MicrometerEventConfig(boolean replaceIds, boolean dataCount, long dataCountInterval) {
this.replaceIds = replaceIds;
this.dataCount = dataCount;
this.dataCountInterval = dataCountInterval;
}
public boolean replaceIds() {
return replaceIds;
}
public boolean dataCount() {
return dataCount;
}
public long dataCountInterval() {
return dataCountInterval;
}
@Override
public String toString() {
StringBuilder o = new StringBuilder();
o.append("replaceIds: ").append(replaceIds).append(", ");
o.append("dataCount: ").append(dataCount).append(", ");
o.append("dataCountInterval: ").append(dataCountInterval);
return o.toString();
}
}

View file

@ -18,20 +18,20 @@ public class MicrometerEventListener implements EventListenerProvider, AutoClose
private static final Logger log = Logger.getLogger(MicrometerEventListener.class); private static final Logger log = Logger.getLogger(MicrometerEventListener.class);
private final MeterRegistry registry; private final MeterRegistry registry;
private final KeycloakSession session; private final KeycloakSession session;
private final boolean replace; private final MicrometerEventConfig config;
public MicrometerEventListener(MeterRegistry registry, KeycloakSession session, boolean replaceId) { public MicrometerEventListener(MeterRegistry registry, KeycloakSession session, MicrometerEventConfig config) {
this.registry = registry; this.registry = registry;
this.session = session; this.session = session;
this.replace = replaceId; this.config = config;
} }
@Override @Override
public void onEvent(Event event) { public void onEvent(Event event) {
registry.counter("keycloak_event_user", registry.counter("keycloak_event_user",
"realm", toBlank(replace ? getRealmName(event.getRealmId()) : event.getRealmId()), "realm", toBlank(config.replaceIds() ? getRealmName(event.getRealmId()) : event.getRealmId()),
"type", toBlank(event.getType()), "type", toBlank(event.getType()),
"client", toBlank(replace ? getClientId(event.getClientId()) : event.getClientId()), "client", toBlank(config.replaceIds() ? getClientId(event.getClientId()) : event.getClientId()),
"error", toBlank(event.getError())) "error", toBlank(event.getError()))
.increment(); .increment();
} }
@ -39,7 +39,7 @@ public class MicrometerEventListener implements EventListenerProvider, AutoClose
@Override @Override
public void onEvent(AdminEvent event, boolean includeRepresentation) { public void onEvent(AdminEvent event, boolean includeRepresentation) {
registry.counter("keycloak_event_admin", registry.counter("keycloak_event_admin",
"realm", toBlank(replace ? getRealmName(event.getRealmId()) : event.getRealmId()), "realm", toBlank(config.replaceIds() ? getRealmName(event.getRealmId()) : event.getRealmId()),
"resource", toBlank(event.getResourceType()), "resource", toBlank(event.getResourceType()),
"operation", toBlank(event.getOperationType()), "operation", toBlank(event.getOperationType()),
"error", toBlank(event.getError())) "error", toBlank(event.getError()))

View file

@ -23,9 +23,10 @@ public class MicrometerEventListenerFactory implements EventListenerProviderFact
private static final String PROVIDER_ID = "metrics-listener"; private static final String PROVIDER_ID = "metrics-listener";
private static final int INTERVAL = 60 * 1000; //1 MINUTE 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 MicrometerEventConfig config;
@Override @Override
public String getId() { public String getId() {
@ -33,15 +34,16 @@ public class MicrometerEventListenerFactory implements EventListenerProviderFact
} }
@Override @Override
public void init(Scope config) { public void init(Scope scopeConfig) {
replace = "true".equals(System.getenv("KC_METRICS_EVENT_REPLACE_IDS")); config = MicrometerEventConfig.getConfig();
log.info(replace ? "Configured with model names." : "Configured with model ids."); log.infof("Configuration: %s", config);
} }
@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();
if (config.dataCount()) {
KeycloakModelUtils.runJobInTransaction(factory, s1 -> { KeycloakModelUtils.runJobInTransaction(factory, s1 -> {
TimerProvider timer = s1.getProvider(TimerProvider.class); TimerProvider timer = s1.getProvider(TimerProvider.class);
log.info("Registering gauge update job TimerProvider"); log.info("Registering gauge update job TimerProvider");
@ -50,19 +52,19 @@ public class MicrometerEventListenerFactory implements EventListenerProviderFact
log.info("Updating gauges"); log.info("Updating gauges");
updateGauges(s2); updateGauges(s2);
}); });
}, INTERVAL, PROVIDER_ID); }, config.dataCountInterval(), PROVIDER_ID);
}); });
} }
}
@Override @Override
public EventListenerProvider create(KeycloakSession session) { public EventListenerProvider create(KeycloakSession session) {
return new MicrometerEventListener(registry, session, replace); return new MicrometerEventListener(registry, session, config);
} }
@Override @Override
public void close() {} public void close() {}
private Iterable<Tag> tags(String... tags) { private Iterable<Tag> tags(String... tags) {
if (tags.length % 2 != 0) throw new IllegalStateException("Tag name value pairs must be even"); if (tags.length % 2 != 0) throw new IllegalStateException("Tag name value pairs must be even");
ImmutableList.Builder<Tag> builder = new ImmutableList.Builder<Tag>(); ImmutableList.Builder<Tag> builder = new ImmutableList.Builder<Tag>();
@ -76,12 +78,12 @@ public class MicrometerEventListenerFactory implements EventListenerProviderFact
session.realms().getRealmsStream().forEach(realm -> { session.realms().getRealmsStream().forEach(realm -> {
// keycloak_users = total number of users // keycloak_users = total number of users
registry.gauge("keycloak_users", registry.gauge("keycloak_users",
tags("realm", replace ? realm.getName() : realm.getId()), tags("realm", config.replaceIds() ? realm.getName() : realm.getId()),
session.users().getUsersCount(realm)); session.users().getUsersCount(realm));
// keycloak_clients = total number of clients // keycloak_clients = total number of clients
registry.gauge("keycloak_clients", registry.gauge("keycloak_clients",
tags("realm", replace ? realm.getName() : realm.getId()), tags("realm", config.replaceIds() ? realm.getName() : realm.getId()),
realm.getClientsCount()); realm.getClientsCount());
// sessions - by client // sessions - by client
@ -89,19 +91,19 @@ public class MicrometerEventListenerFactory implements EventListenerProviderFact
realm.getClientsStream().forEach(client -> { realm.getClientsStream().forEach(client -> {
// keycloak_active_user_sessions // keycloak_active_user_sessions
registry.gauge("keycloak_active_user_sessions", registry.gauge("keycloak_active_user_sessions",
tags("realm", replace ? realm.getName() : realm.getId(), tags("realm", config.replaceIds() ? realm.getName() : realm.getId(),
"client", replace ? client.getClientId() : client.getId()), "client", config.replaceIds() ? client.getClientId() : client.getId()),
session.sessions().getActiveUserSessions(realm, client)); session.sessions().getActiveUserSessions(realm, client));
// keycloak_active_client_sessions // keycloak_active_client_sessions
registry.gauge("keycloak_active_client_sessions", registry.gauge("keycloak_active_client_sessions",
tags("realm", replace ? realm.getName() : realm.getId(), tags("realm", config.replaceIds() ? realm.getName() : realm.getId(),
"client", replace ? client.getClientId() : client.getId()), "client", config.replaceIds() ? client.getClientId() : client.getId()),
session.sessions().getActiveClientSessionStats(realm,false).get(client.getId())); session.sessions().getActiveClientSessionStats(realm,false).get(client.getId()));
// keycloak_offline_sessions // keycloak_offline_sessions
registry.gauge("keycloak_offline_sessions", registry.gauge("keycloak_offline_sessions",
tags("realm", replace ? realm.getName() : realm.getId(), tags("realm", config.replaceIds() ? realm.getName() : realm.getId(),
"client", replace ? client.getClientId() : client.getId()), "client", config.replaceIds() ? client.getClientId() : client.getId()),
session.sessions().getOfflineSessionsCount(realm, client)); session.sessions().getOfflineSessionsCount(realm, client));
}); });
}); });