package rocks.inspectit.agent.java.spring; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import org.springframework.core.io.ClassPathResource; import com.google.common.util.concurrent.ThreadFactoryBuilder; import rocks.inspectit.agent.java.IThreadTransformHelper; import rocks.inspectit.agent.java.config.IConfigurationStorage; import rocks.inspectit.agent.java.connection.impl.AgentAwareClient; import rocks.inspectit.agent.java.sdk.opentracing.Reporter; import rocks.inspectit.agent.java.sdk.opentracing.internal.impl.TracerImpl; import rocks.inspectit.agent.java.sdk.opentracing.util.SystemTimer; import rocks.inspectit.agent.java.util.AgentAwareThread; import rocks.inspectit.shared.all.instrumentation.config.impl.AbstractSensorTypeConfig; import rocks.inspectit.shared.all.instrumentation.config.impl.JmxSensorTypeConfig; import rocks.inspectit.shared.all.instrumentation.config.impl.StrategyConfig; import rocks.inspectit.shared.all.kryonet.Client; import rocks.inspectit.shared.all.kryonet.ExtendedSerializationImpl; import rocks.inspectit.shared.all.kryonet.IExtendedSerialization; /** * Post process configuration storage to define buffer and sending strategy beans. * * @author Ivan Senic * */ @Configuration @ComponentScan("rocks.inspectit") public class SpringConfiguration implements BeanDefinitionRegistryPostProcessor { /** * Registry to add bean definitions to. */ private BeanDefinitionRegistry registry; /** * Bean factory to force initialization of manually defined beans. */ private ConfigurableListableBeanFactory beanFactory; /** * {@inheritDoc} */ @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } /** * {@inheritDoc} */ @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { this.registry = registry; } /** * Returns {@link PropertyPlaceholderConfigurer} for the Agent. * * @return Returns {@link PropertyPlaceholderConfigurer} for the Agent. */ @Bean public static PropertyPlaceholderConfigurer properties() { PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); ClassPathResource[] resources = new ClassPathResource[] { new ClassPathResource("/config/bytebufferpool.properties") }; ppc.setLocations(resources); ppc.setIgnoreUnresolvablePlaceholders(true); return ppc; } /** * @param threadTransformHelper * {@link IThreadTransformHelper} * @return Returns socketReadExecutorService */ @Bean(name = "socketReadExecutorService") @Scope(BeanDefinition.SCOPE_SINGLETON) @Autowired public ExecutorService getSocketReadExecutorService(final IThreadTransformHelper threadTransformHelper) { ThreadFactory inspectitThreadFactory = new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new AgentAwareThread(r, threadTransformHelper); } }; ThreadFactory threadFactory = new ThreadFactoryBuilder().setThreadFactory(inspectitThreadFactory).setNameFormat("inspectit-socket-read-executor-service-thread-%d").setDaemon(true).build(); return Executors.newFixedThreadPool(1, threadFactory); } /** * @param threadTransformHelper * {@link IThreadTransformHelper} * @return Returns coreServiceExecutorService */ @Bean(name = "coreServiceExecutorService") @Scope(BeanDefinition.SCOPE_SINGLETON) @Autowired public ScheduledExecutorService getCoreServiceExecutorService(final IThreadTransformHelper threadTransformHelper) { ThreadFactory inspectitThreadFactory = new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new AgentAwareThread(r, threadTransformHelper); } }; ThreadFactory threadFactory = new ThreadFactoryBuilder().setThreadFactory(inspectitThreadFactory).setNameFormat("inspectit-core-service-executor-service-thread-%d").setDaemon(true).build(); return Executors.newScheduledThreadPool(3, threadFactory); } /** * Creates the client bean. * * @param prototypesProvider * {@link PrototypesProvider} (autowired) * @param threadTransformHelper * {@link IThreadTransformHelper} (autowired) * @return Created bean */ @Bean(name = "kryonet-client") @Scope(BeanDefinition.SCOPE_SINGLETON) @Autowired public Client getClient(PrototypesProvider prototypesProvider, IThreadTransformHelper threadTransformHelper) { IExtendedSerialization serialization = new ExtendedSerializationImpl(prototypesProvider); return new AgentAwareClient(serialization, prototypesProvider, threadTransformHelper); } /** * Creates the {@link TracerImpl}. * * @param reporter * Reporter to use. Autowired. * @return Created bean */ @Bean @Scope(BeanDefinition.SCOPE_SINGLETON) @Autowired public TracerImpl getTracer(Reporter reporter) { TracerImpl tracer = new TracerImpl(new SystemTimer(), reporter, true); return tracer; } /** * Registers components needed by the configuration to the Spring container. * * @param configurationStorage * {@link IConfigurationStorage} with the settings. * @throws Exception * If exception occurs during the registration. */ public void registerComponents(IConfigurationStorage configurationStorage) throws Exception { // buffer strategy String className = configurationStorage.getBufferStrategyConfig().getClazzName(); String beanName = "bufferStrategy[" + className + "]"; registerBeanDefinitionAndInitialize(beanName, className); // sending strategies StrategyConfig sendingStrategyConfig = configurationStorage.getSendingStrategyConfig(); className = sendingStrategyConfig.getClazzName(); beanName = "sendingStrategy[" + className + "]"; registerBeanDefinitionAndInitialize(beanName, className); // platform sensor types for (AbstractSensorTypeConfig platformSensorTypeConfig : configurationStorage.getPlatformSensorTypes()) { className = platformSensorTypeConfig.getClassName(); beanName = "platformSensorType[" + className + "]"; registerBeanDefinitionAndInitialize(beanName, className); } // jmx sensor types for (JmxSensorTypeConfig jmxSensorTypeConfig : configurationStorage.getJmxSensorTypes()) { className = jmxSensorTypeConfig.getClassName(); beanName = "jmxSensorType[" + className + "]"; registerBeanDefinitionAndInitialize(beanName, className); } // method sensor types for (AbstractSensorTypeConfig methodSensorTypeConfig : configurationStorage.getMethodSensorTypes()) { className = methodSensorTypeConfig.getClassName(); beanName = "methodSensorType[" + className + "]"; registerBeanDefinitionAndInitialize(beanName, className); } } /** * Creates bean definition for the given class name, registers the definition in the registry * and immediately invokes the initialization of the bean. * <p> * <i>This is the only way to initialize the bean definitions that no other component has * dependency to, since we add the definitions in the moment when the lookup has been finished * and bean creation has started.</i> * * @param beanName * Name of the bean to register. * @param className * Class name of the bean. * @throws ClassNotFoundException * If class can not be founded. */ private void registerBeanDefinitionAndInitialize(String beanName, String className) throws ClassNotFoundException { Class<?> clazz = Class.forName(className); GenericBeanDefinition definition = new GenericBeanDefinition(); definition.setBeanClass(clazz); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); definition.setAutowireCandidate(true); registry.registerBeanDefinition(beanName, definition); beanFactory.getBean(beanName, clazz); } }