mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 23:12:06 -03:30
Add a span per rest resource, thereby showing subresources (#35420)
* Add a span per rest resource, thereby showing subresources Closes #35419 Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
parent
8cad78b1df
commit
909db9e65e
@ -80,6 +80,7 @@ import org.keycloak.config.HttpOptions;
|
||||
import org.keycloak.config.ManagementOptions;
|
||||
import org.keycloak.config.MetricsOptions;
|
||||
import org.keycloak.config.SecurityOptions;
|
||||
import org.keycloak.config.TracingOptions;
|
||||
import org.keycloak.connections.jpa.DefaultJpaConnectionProviderFactory;
|
||||
import org.keycloak.connections.jpa.JpaConnectionProvider;
|
||||
import org.keycloak.connections.jpa.JpaConnectionSpi;
|
||||
@ -104,6 +105,7 @@ import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource;
|
||||
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper;
|
||||
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
|
||||
import org.keycloak.quarkus.runtime.integration.resteasy.KeycloakHandlerChainCustomizer;
|
||||
import org.keycloak.quarkus.runtime.integration.resteasy.KeycloakTracingCustomizer;
|
||||
import org.keycloak.quarkus.runtime.services.health.KeycloakReadyHealthCheck;
|
||||
import org.keycloak.quarkus.runtime.storage.database.jpa.NamedJpaConnectionProviderFactory;
|
||||
import org.keycloak.quarkus.runtime.themes.FlatClasspathThemeResourceProviderFactory;
|
||||
@ -636,13 +638,19 @@ class KeycloakProcessor {
|
||||
LoadBalancerResource.class.getName())), false));
|
||||
}
|
||||
|
||||
KeycloakHandlerChainCustomizer chainCustomizer = new KeycloakHandlerChainCustomizer();
|
||||
ArrayList<HandlerChainCustomizer> chainCustomizers = new ArrayList<>();
|
||||
|
||||
chainCustomizers.add(new KeycloakHandlerChainCustomizer());
|
||||
|
||||
if (Configuration.isTrue(TracingOptions.TRACING_ENABLED)) {
|
||||
chainCustomizers.add(new KeycloakTracingCustomizer());
|
||||
}
|
||||
|
||||
scanner.produce(new MethodScannerBuildItem(new MethodScanner() {
|
||||
@Override
|
||||
public List<HandlerChainCustomizer> scan(MethodInfo method, ClassInfo actualEndpointClass,
|
||||
Map<String, Object> methodContext) {
|
||||
return List.of(chainCustomizer);
|
||||
return chainCustomizers;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.keycloak.quarkus.runtime.integration.resteasy;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
import io.opentelemetry.api.trace.SpanBuilder;
|
||||
import io.opentelemetry.api.trace.Tracer;
|
||||
import io.opentelemetry.context.Context;
|
||||
import jakarta.enterprise.inject.spi.CDI;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jboss.resteasy.reactive.common.model.ResourceClass;
|
||||
import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext;
|
||||
import org.jboss.resteasy.reactive.server.model.HandlerChainCustomizer;
|
||||
import org.jboss.resteasy.reactive.server.model.ServerResourceMethod;
|
||||
import org.jboss.resteasy.reactive.server.spi.ServerRestHandler;
|
||||
import org.keycloak.common.Version;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class KeycloakTracingCustomizer implements HandlerChainCustomizer {
|
||||
|
||||
private static class StartHandler implements ServerRestHandler {
|
||||
private final String className;
|
||||
private final String methodName;
|
||||
private final String spanName;
|
||||
|
||||
public StartHandler(String className, String methodName) {
|
||||
this.className = className;
|
||||
this.methodName = methodName;
|
||||
this.spanName = StringUtils.substringAfterLast(className, ".") + "." + methodName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(ResteasyReactiveRequestContext requestContext) {
|
||||
if (requestContext.getProperty("span") != null) {
|
||||
return;
|
||||
}
|
||||
OpenTelemetry openTelemetry = CDI.current().select(OpenTelemetry.class).get();
|
||||
Tracer myTracer = openTelemetry.getTracer(this.getClass().getName(), Version.VERSION);
|
||||
SpanBuilder spanBuilder = myTracer.spanBuilder(spanName);
|
||||
spanBuilder.setParent(Context.current().with(Span.current()));
|
||||
spanBuilder.setAttribute("code.function", methodName);
|
||||
spanBuilder.setAttribute("code.namespace", className);
|
||||
Span span = spanBuilder.startSpan();
|
||||
requestContext.setProperty("span", span);
|
||||
}
|
||||
}
|
||||
|
||||
private static class EndHandler implements ServerRestHandler {
|
||||
@Override
|
||||
public void handle(ResteasyReactiveRequestContext requestContext) {
|
||||
Span span = (Span) requestContext.getProperty("span");
|
||||
if (span != null) {
|
||||
span.end();
|
||||
}
|
||||
requestContext.removeProperty("span");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServerRestHandler> handlers(Phase phase, ResourceClass resourceClass,
|
||||
ServerResourceMethod resourceMethod) {
|
||||
List<ServerRestHandler> handlers = new ArrayList<>();
|
||||
|
||||
switch (phase) {
|
||||
case BEFORE_METHOD_INVOKE:
|
||||
handlers.add(new StartHandler(resourceClass.getClassName(), resourceMethod.getName()));
|
||||
break;
|
||||
case AFTER_METHOD_INVOKE:
|
||||
handlers.add(new EndHandler());
|
||||
break;
|
||||
}
|
||||
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user