Optimize meter generation

Closes #35834

Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
Signed-off-by: Alexander Schwartz <alexander.schwartz@gmx.net>
Co-authored-by: Pedro Ruivo <pruivo@users.noreply.github.com>
This commit is contained in:
Alexander Schwartz 2024-12-12 18:00:41 +01:00 committed by GitHub
parent f12fe052a6
commit c8078fa2af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 19 deletions

View File

@ -18,10 +18,8 @@
package org.keycloak.quarkus.runtime.services.metrics.events;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import io.micrometer.core.instrument.binder.BaseUnits;
import org.jboss.logging.Logger;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
@ -32,7 +30,9 @@ import org.keycloak.events.EventType;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.models.KeycloakSession;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
public class MicrometerUserEventMetricsEventListenerProvider implements EventListenerProvider {
@ -44,10 +44,6 @@ public class MicrometerUserEventMetricsEventListenerProvider implements EventLis
private static final String CLIENT_ID_TAG = "client.id";
private static final String ERROR_TAG = "error";
private static final String EVENT_TAG = "event";
private static final String DESCRIPTION_OF_EVENT_METER = "Keycloak user events";
// Micrometer naming convention that separates lowercase words with a . (dot) character.
private static final String KEYCLOAK_METER_NAME_PREFIX = "keycloak.";
private static final String USER_EVENTS_METER_NAME = KEYCLOAK_METER_NAME_PREFIX + "user";
private final boolean withIdp;
private final boolean withRealm;
@ -56,12 +52,14 @@ public class MicrometerUserEventMetricsEventListenerProvider implements EventLis
private final EventListenerTransaction tx =
new EventListenerTransaction(null, this::countEvent);
private final Meter.MeterProvider<Counter> meterProvider;
public MicrometerUserEventMetricsEventListenerProvider(KeycloakSession session, boolean withIdp, boolean withRealm, boolean withClientId, HashSet<String> events) {
public MicrometerUserEventMetricsEventListenerProvider(KeycloakSession session, boolean withIdp, boolean withRealm, boolean withClientId, HashSet<String> events, Meter.MeterProvider<Counter> meterProvider) {
this.withIdp = withIdp;
this.withRealm = withRealm;
this.withClientId = withClientId;
this.events = events;
this.meterProvider = meterProvider;
session.getTransactionManager().enlistAfterCompletion(tx);
}
@ -79,26 +77,24 @@ public class MicrometerUserEventMetricsEventListenerProvider implements EventLis
return;
}
Counter.Builder counterBuilder = Counter.builder(USER_EVENTS_METER_NAME)
.description(DESCRIPTION_OF_EVENT_METER)
.tags(Tags.of(Tag.of(EVENT_TAG, eventTag),
Tag.of(ERROR_TAG, getError(event))))
.baseUnit(BaseUnits.EVENTS);
List<Tag> tags = new ArrayList<>(5);
tags.add(Tag.of(EVENT_TAG, eventTag));
tags.add(Tag.of(ERROR_TAG, getError(event)));
if (withRealm) {
counterBuilder.tag(REALM_TAG, nullToEmpty(event.getRealmName()));
tags.add(Tag.of(REALM_TAG, nullToEmpty(event.getRealmName())));
}
if (withIdp) {
counterBuilder.tag(IDP_TAG, getIdentityProvider(event));
tags.add(Tag.of(IDP_TAG, getIdentityProvider(event)));
}
if (withClientId) {
counterBuilder.tag(CLIENT_ID_TAG, getClientId(event));
tags.add(Tag.of(CLIENT_ID_TAG, getClientId(event)));
}
counterBuilder.register(Metrics.globalRegistry)
.increment();
meterProvider.withTags(tags).increment();
}
@Override

View File

@ -17,6 +17,10 @@
package org.keycloak.quarkus.runtime.services.metrics.events;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.binder.BaseUnits;
import org.bouncycastle.util.Strings;
import org.keycloak.Config;
import org.keycloak.events.EventListenerProvider;
@ -32,18 +36,27 @@ public class MicrometerUserEventMetricsEventListenerProviderFactory implements E
private static final String ID = "micrometer-user-event-metrics";
private static final String TAGS_OPTION = "tags";
private static final String EVENTS_OPTION = "events";
private static final String DESCRIPTION_OF_EVENT_METER = "Keycloak user events";
// Micrometer naming convention that separates lowercase words with a . (dot) character.
private static final String KEYCLOAK_METER_NAME_PREFIX = "keycloak.";
private static final String USER_EVENTS_METER_NAME = KEYCLOAK_METER_NAME_PREFIX + "user";
private boolean withIdp, withRealm, withClientId;
private HashSet<String> events;
private Meter.MeterProvider<Counter> meterProvider;
@Override
public EventListenerProvider create(KeycloakSession session) {
return new MicrometerUserEventMetricsEventListenerProvider(session, withIdp, withRealm, withClientId, events);
return new MicrometerUserEventMetricsEventListenerProvider(session, withIdp, withRealm, withClientId, events, meterProvider);
}
@Override
public void init(Config.Scope config) {
meterProvider = Counter.builder(USER_EVENTS_METER_NAME)
.description(DESCRIPTION_OF_EVENT_METER)
.baseUnit(BaseUnits.EVENTS).withRegistry(Metrics.globalRegistry);
String tagsConfig = config.get(TAGS_OPTION);
if (tagsConfig != null) {
for (String s : Strings.split(tagsConfig, ',')) {