All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.weld.probe.ProbeExtension Maven / Gradle / Ivy

There is a newer version: 3.0.0.Alpha1
Show newest version
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014, Red Hat, Inc., and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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.jboss.weld.probe;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.util.Collections;
import java.util.Set;
import java.util.regex.Pattern;

import javax.decorator.Decorator;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.UnproxyableResolutionException;
import javax.enterprise.inject.Vetoed;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.AfterTypeDiscovery;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.AnnotatedMember;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeanAttributes;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.BeforeShutdown;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ObserverMethod;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.ProcessBean;
import javax.enterprise.inject.spi.ProcessBeanAttributes;
import javax.enterprise.inject.spi.ProcessInjectionPoint;
import javax.enterprise.inject.spi.ProcessInjectionTarget;
import javax.enterprise.inject.spi.ProcessObserverMethod;
import javax.enterprise.inject.spi.ProcessProducer;
import javax.enterprise.inject.spi.ProcessProducerField;
import javax.enterprise.inject.spi.ProcessProducerMethod;
import javax.interceptor.Interceptor;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;

import org.jboss.weld.bean.builtin.BeanManagerProxy;
import org.jboss.weld.bootstrap.api.Environment;
import org.jboss.weld.bootstrap.events.AbstractContainerEvent;
import org.jboss.weld.bootstrap.events.ProcessAnnotatedTypeEventResolvable;
import org.jboss.weld.bootstrap.events.ProcessAnnotatedTypeImpl;
import org.jboss.weld.bootstrap.events.RequiredAnnotationDiscovery;
import org.jboss.weld.config.ConfigurationKey;
import org.jboss.weld.config.WeldConfiguration;
import org.jboss.weld.event.ResolvedObservers;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.manager.api.WeldManager;
import org.jboss.weld.probe.BootstrapStats.EventType;
import org.jboss.weld.util.BiConsumer;
import org.jboss.weld.util.Proxies;
import org.jboss.weld.util.annotated.VetoedSuppressedAnnotatedType;
import org.jboss.weld.util.bean.ForwardingBeanAttributes;
import org.jboss.weld.util.collections.ImmutableSet;
import org.jboss.weld.util.reflection.Formats;
import org.jboss.weld.util.reflection.Reflections;

/**
 * This extension adds {@link AnnotatedType}s needed for monitoring. Furthermore, {@link BeanAttributes} of all suitable beans are modified so that a stereotype
 * with applied interceptor binding is declared. Finally, an initialization of the {@link Probe} component (mapping data) is triggered.
 *
 * 

* An integrator is required to register this extension for every application which should be a subject of inspection. *

* * @author Martin Kouba */ @Vetoed public class ProbeExtension implements Extension { private final Probe probe; private volatile JsonDataProvider jsonDataProvider; private volatile Pattern invocationMonitorExcludePattern; private volatile boolean eventMonitorContainerLifecycleEvents; public ProbeExtension() { this.probe = new Probe(); } public void beforeBeanDiscovery(@Observes BeforeBeanDiscovery event, BeanManager beanManager) { ProbeLogger.LOG.developmentModeEnabled(); final BeanManagerImpl manager = BeanManagerProxy.unwrap(beanManager); manager.addValidationFailureCallback(new BiConsumer() { @Override public void accept(Exception exception, Environment environment) { // Note that eventual problems are ignored during callback invocation probe.init(manager); Reports.generateValidationReport(probe, exception, environment, manager); } }); event.addAnnotatedType(VetoedSuppressedAnnotatedType.from(Monitored.class, beanManager), Monitored.class.getName()); event.addAnnotatedType(VetoedSuppressedAnnotatedType.from(MonitoredComponent.class, beanManager), MonitoredComponent.class.getName()); event.addAnnotatedType(VetoedSuppressedAnnotatedType.from(InvocationMonitor.class, beanManager), InvocationMonitor.class.getName()); WeldConfiguration configuration = manager.getServices().get(WeldConfiguration.class); String exclude = configuration.getStringProperty(ConfigurationKey.PROBE_INVOCATION_MONITOR_EXCLUDE_TYPE); this.invocationMonitorExcludePattern = exclude.isEmpty() ? null : Pattern.compile(exclude); this.jsonDataProvider = new DefaultJsonDataProvider(probe, manager); this.eventMonitorContainerLifecycleEvents = configuration.getBooleanProperty(ConfigurationKey.PROBE_EVENT_MONITOR_CONTAINER_LIFECYCLE_EVENTS); addContainerLifecycleEvent(event, null, beanManager); } public void processBeanAttributes(@Observes ProcessBeanAttributes event, BeanManager beanManager) { probe.getBootstrapStats().increment(EventType.PBA); final BeanAttributes beanAttributes = event.getBeanAttributes(); final WeldManager weldManager = (WeldManager) beanManager; if (isMonitored(event.getAnnotated(), beanAttributes, weldManager)) { event.setBeanAttributes(new ForwardingBeanAttributes() { @Override public Set> getStereotypes() { return ImmutableSet.> builder().addAll(attributes().getStereotypes()).add(MonitoredComponent.class).build(); } @Override protected BeanAttributes attributes() { return beanAttributes; } @Override public String toString() { return beanAttributes.toString(); } }); ProbeLogger.LOG.monitoringStereotypeAdded(event.getAnnotated()); } if (eventMonitorContainerLifecycleEvents) { addContainerLifecycleEvent(event, "Types: [" + Formats.formatTypes(event.getBeanAttributes().getTypes()) + "], qualifiers: [" + Formats.formatAnnotations(event.getBeanAttributes().getQualifiers()) + "]", beanManager); } } public void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager beanManager) { BeanManagerImpl weldManager = BeanManagerProxy.unwrap(beanManager); String exclude = weldManager.getServices().get(WeldConfiguration.class).getStringProperty(ConfigurationKey.PROBE_EVENT_MONITOR_EXCLUDE_TYPE); event.addObserverMethod(new ProbeObserver(weldManager, exclude.isEmpty() ? null : Pattern.compile(exclude), probe)); addContainerLifecycleEvent(event, null, beanManager); } public void afterDeploymentValidation(@Observes AfterDeploymentValidation event, BeanManager beanManager) { BeanManagerImpl manager = BeanManagerProxy.unwrap(beanManager); probe.init(manager); if (isJMXSupportEnabled(manager)) { try { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); mbs.registerMBean(new ProbeDynamicMBean(jsonDataProvider, JsonDataProvider.class), constructProbeJsonDataMBeanName(manager, probe)); } catch (MalformedObjectNameException | InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) { event.addDeploymentProblem(ProbeLogger.LOG.unableToRegisterMBean(JsonDataProvider.class, manager.getContextId(), e)); } } addContainerLifecycleEvent(event, null, beanManager); exportDataIfNeeded(manager); } public void beforeShutdown(@Observes BeforeShutdown event, BeanManager beanManager) { BeanManagerImpl manager = BeanManagerProxy.unwrap(beanManager); if (isJMXSupportEnabled(manager)) { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try { ObjectName name = constructProbeJsonDataMBeanName(manager, probe); if (mbs.isRegistered(name)) { mbs.unregisterMBean(name); } } catch (MalformedObjectNameException | MBeanRegistrationException | InstanceNotFoundException e) { throw ProbeLogger.LOG.unableToUnregisterMBean(JsonDataProvider.class, manager.getContextId(), e); } } } public void processAnnotatedTypes(@Observes ProcessAnnotatedType event, BeanManager beanManager) { probe.getBootstrapStats().increment(EventType.PAT); addContainerLifecycleEvent(event, null, beanManager); } public void processInjectionPoints(@Observes ProcessInjectionPoint event, BeanManager beanManager) { probe.getBootstrapStats().increment(EventType.PIP); if (eventMonitorContainerLifecycleEvents) { addContainerLifecycleEvent(event, formatMember(event.getInjectionPoint().getMember()), beanManager); } } public void processInjectionTargets(@Observes ProcessInjectionTarget event, BeanManager beanManager) { probe.getBootstrapStats().increment(EventType.PIT); if (eventMonitorContainerLifecycleEvents) { addContainerLifecycleEvent(event, Formats.formatType(event.getAnnotatedType().getBaseType(), false), beanManager); } } public void afterTypeDiscovery(@Observes AfterTypeDiscovery event, BeanManager beanManager) { addContainerLifecycleEvent(event, null, beanManager); } public void processObserverMethods(@Observes ProcessObserverMethod event, BeanManager beanManager) { probe.getBootstrapStats().increment(EventType.POM); if (eventMonitorContainerLifecycleEvents) { addContainerLifecycleEvent(event, event.getAnnotatedMethod() != null ? formatMember(event.getAnnotatedMethod().getJavaMember()) : event.getObserverMethod().toString(), beanManager); } } public void processProducers(@Observes ProcessProducer event, BeanManager beanManager) { probe.getBootstrapStats().increment(EventType.PP); if (eventMonitorContainerLifecycleEvents) { addContainerLifecycleEvent(event, formatMember(event.getAnnotatedMember().getJavaMember()), beanManager); } } public void processBeans(@Observes ProcessBean event, BeanManager beanManager) { probe.getBootstrapStats().increment(EventType.PB); if (eventMonitorContainerLifecycleEvents) { Object info; if (event instanceof ProcessProducerMethod) { info = formatMember(((ProcessProducerMethod) event).getAnnotatedProducerMethod().getJavaMember()); } else if (event instanceof ProcessProducerField) { info = formatMember(((ProcessProducerField) event).getAnnotatedProducerField().getJavaMember()); } else { info = Formats.formatType(event.getBean().getBeanClass(), false); } addContainerLifecycleEvent(event, info, beanManager); } } Probe getProbe() { return probe; } JsonDataProvider getJsonDataProvider() { return jsonDataProvider; } private boolean isJMXSupportEnabled(BeanManagerImpl manager) { return manager.getServices().get(WeldConfiguration.class).getBooleanProperty(ConfigurationKey.PROBE_JMX_SUPPORT); } private ObjectName constructProbeJsonDataMBeanName(BeanManagerImpl manager, Probe probe) throws MalformedObjectNameException { return new ObjectName( Probe.class.getPackage().getName() + ":type=JsonData,context=" + ObjectName.quote(manager.getContextId() + "_" + probe.getInitTs())); } private boolean isMonitored(Annotated annotated, BeanAttributes beanAttributes, WeldManager weldManager) { if (annotated.isAnnotationPresent(Interceptor.class) || annotated.isAnnotationPresent(Decorator.class)) { // Omit interceptors and decorators return false; } final Type type; if (annotated instanceof AnnotatedMember) { // AnnotatedField or AnnotatedMethod type = ((AnnotatedMember) annotated).getDeclaringType().getBaseType(); } else { type = annotated.getBaseType(); } UnproxyableResolutionException unproxyableException = Proxies.getUnproxyableTypeException(type, weldManager.getServices()); if (unproxyableException != null) { // A bean with an interceptor must be a proxyable ProbeLogger.LOG.invocationMonitorNotAssociatedNonProxyableType(type); ProbeLogger.LOG.catchingTrace(unproxyableException); return false; } if (type instanceof Class) { final Class clazz = (Class) type; if (invocationMonitorExcludePattern != null && invocationMonitorExcludePattern.matcher(clazz.getName()).matches()) { ProbeLogger.LOG.invocationMonitorNotAssociatedExcluded(clazz.getName()); return false; } } return true; } private void addContainerLifecycleEvent(T event, Object info, BeanManagerImpl beanManagerImpl) { ResolvedObservers resolvedObservers = null; Type eventType = null; if (event instanceof AbstractContainerEvent) { AbstractContainerEvent containerEvent = (AbstractContainerEvent) event; eventType = containerEvent.getEventType(); resolvedObservers = beanManagerImpl.getGlobalLenientObserverNotifier().resolveObserverMethods(eventType); } else if (event instanceof ProcessAnnotatedTypeImpl) { ProcessAnnotatedTypeImpl processAnnotatedTypeEvent = (ProcessAnnotatedTypeImpl) event; eventType = ProcessAnnotatedType.class; info = Formats.formatType(processAnnotatedTypeEvent.getOriginalAnnotatedType().getBaseType(), false); resolvedObservers = beanManagerImpl.getGlobalLenientObserverNotifier().resolveObserverMethods( ProcessAnnotatedTypeEventResolvable.of(processAnnotatedTypeEvent, beanManagerImpl.getServices().get(RequiredAnnotationDiscovery.class))); } if (resolvedObservers != null && eventType != null) { Iterable> observerMethods = Reflections.cast(resolvedObservers.getAllObservers()); probe.addEvent(new EventInfo(eventType, Collections. emptySet(), info, null, observerMethods, true, System.currentTimeMillis(), false)); } } private void addContainerLifecycleEvent(T event, Object payloadInfo, BeanManager beanManager) { if (eventMonitorContainerLifecycleEvents) { addContainerLifecycleEvent(event, payloadInfo, BeanManagerProxy.unwrap(beanManager)); } } private String formatMember(Member member) { StringBuilder format = new StringBuilder(); format.append(member.getDeclaringClass().getName()); format.append("."); format.append(member.getName()); if (member instanceof Method) { format.append("()"); } return format.toString(); } private void exportDataIfNeeded(BeanManagerImpl manager) { String export = manager.getServices().get(WeldConfiguration.class).getStringProperty(ConfigurationKey.PROBE_EXPORT_DATA_AFTER_DEPLOYMENT); if (!export.isEmpty()) { File exportPath = new File(export); if (!exportPath.canWrite()) { ProbeLogger.LOG.invalidExportPath(exportPath); return; } try { Files.write(new File(exportPath, "weld-probe-export.zip").toPath(), Exports.exportJsonData(jsonDataProvider)); } catch (IOException e) { ProbeLogger.LOG.unableToExportData(exportPath, e.getCause() != null ? e.getCause() : e); ProbeLogger.LOG.catchingTrace(e); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy