blob: dfd4e1d775ae3def1b3ceb0b7dc777aeac6edc66 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.geronimo.microprofile.opentracing.microprofile.cdi;
import java.lang.reflect.Type;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.WithAnnotations;
import javax.enterprise.inject.spi.configurator.AnnotatedTypeConfigurator;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.Path;
import org.apache.geronimo.microprofile.opentracing.common.config.GeronimoOpenTracingConfig;
import org.apache.geronimo.microprofile.opentracing.common.impl.IdGenerator;
import org.apache.geronimo.microprofile.opentracing.common.microprofile.client.OpenTracingClientRequestFilter;
import org.apache.geronimo.microprofile.opentracing.common.microprofile.client.OpenTracingClientResponseFilter;
import org.apache.geronimo.microprofile.opentracing.common.microprofile.thread.OpenTracingExecutorService;
import org.apache.geronimo.microprofile.opentracing.microprofile.zipkin.CdiZipkinConverter;
import org.apache.geronimo.microprofile.opentracing.microprofile.zipkin.CdiZipkinLogger;
import org.eclipse.microprofile.opentracing.Traced;
import io.opentracing.ScopeManager;
public class OpenTracingExtension implements Extension {
private GeronimoOpenTracingConfig config;
private boolean useZipkin;
private boolean useZipkinLogger;
void onStart(@Observes final BeforeBeanDiscovery beforeBeanDiscovery) {
config = GeronimoOpenTracingConfig.create();
useZipkin = Boolean.parseBoolean(config.read("span.converter.zipkin.active", "true"));
useZipkinLogger = useZipkin && Boolean.parseBoolean(config.read("span.converter.zipkin.logger.active", "true"));
}
void vetoDefaultConfigIfScanned(@Observes final ProcessAnnotatedType<GeronimoOpenTracingConfig> config) {
if (config.getAnnotatedType().getJavaClass().getName()
.equals("org.apache.geronimo.microprofile.opentracing.common.config.DefaultOpenTracingConfig")) {
config.veto();
}
}
void vetoDefaultScopeManagerIfScanned(@Observes final ProcessAnnotatedType<ScopeManager> manager) {
if (manager.getAnnotatedType().getJavaClass().getName()
.equals("org.apache.geronimo.microprofile.opentracing.common.impl.ScopeManagerImpl")) {
manager.veto();
}
}
void vetoDefaultIdGeneratorIfScanned(@Observes final ProcessAnnotatedType<IdGenerator> generator) {
if (generator.getAnnotatedType().getJavaClass().getName()
.equals("org.apache.geronimo.microprofile.opentracing.common.impl.IdGenerator")) {
generator.veto();
}
}
void vetoClientRequestTracingIfScanned(@Observes final ProcessAnnotatedType<OpenTracingClientRequestFilter> clientFilter) {
if (clientFilter.getAnnotatedType().getJavaClass().getName()
.equals("org.apache.geronimo.microprofile.opentracing.common.microprofile.client.OpenTracingClientRequestFilter")) {
clientFilter.veto();
}
}
void vetoClientResponseTracingIfScanned(@Observes final ProcessAnnotatedType<OpenTracingClientResponseFilter> clientFilter) {
if (clientFilter.getAnnotatedType().getJavaClass().getName()
.equals("org.apache.geronimo.microprofile.opentracing.common.microprofile.client.OpenTracingClientResponseFilter")) {
clientFilter.veto();
}
}
void zipkinConverterToggle(@Observes final ProcessAnnotatedType<CdiZipkinConverter> onZipkinConverter) {
if (!useZipkin) {
onZipkinConverter.veto();
}
}
void zipkinLoggerToggle(@Observes final ProcessAnnotatedType<CdiZipkinLogger> onZipkinLogger) {
if (!useZipkinLogger) {
onZipkinLogger.veto();
}
}
<T> void removeTracedFromJaxRsEndpoints(@Observes @WithAnnotations(Traced.class) final ProcessAnnotatedType<T> pat) {
if (isJaxRs(pat.getAnnotatedType())) { // we have filters with more accurate timing
final AnnotatedTypeConfigurator<T> configurator = pat.configureAnnotatedType();
configurator.remove(it -> it.annotationType() == Traced.class);
configurator.methods().stream().filter(m -> isJaxRs(m.getAnnotated()))
.forEach(m -> m.remove(it -> it.annotationType() == Traced.class));
}
}
<T> void instrumentExecutorServices(@Observes final ProcessAnnotatedType<T> pat) {
final Set<Type> typeClosure = pat.getAnnotatedType().getTypeClosure();
if (typeClosure.contains(ExecutorService.class) && !typeClosure.contains(OpenTracingExecutorService.class)) {
pat.configureAnnotatedType().add(TracedExecutorService.Literal.INSTANCE);
}
}
void addConfigAsBean(@Observes final AfterBeanDiscovery afterBeanDiscovery) {
afterBeanDiscovery.addBean().id(OpenTracingExtension.class.getName() + "#" + GeronimoOpenTracingConfig.class.getName())
.beanClass(GeronimoOpenTracingConfig.class).types(GeronimoOpenTracingConfig.class, Object.class)
.qualifiers(Default.Literal.INSTANCE, Any.Literal.INSTANCE).scope(ApplicationScoped.class)
.createWith(ctx -> config);
}
private <T> boolean isJaxRs(final AnnotatedType<T> annotatedType) {
return annotatedType.getAnnotations().stream().anyMatch(it -> it.annotationType() == Path.class)
|| annotatedType.getMethods().stream().anyMatch(this::isJaxRs);
}
private <T> boolean isJaxRs(final AnnotatedMethod<? super T> m) {
return m.getAnnotations().stream().anyMatch(it -> it.annotationType().isAnnotationPresent(HttpMethod.class));
}
}