package rocks.inspectit.server.processor.impl; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; import javax.annotation.Resource; import javax.persistence.EntityManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import rocks.inspectit.server.ci.event.BusinessContextDefinitionUpdateEvent; import rocks.inspectit.server.dao.InvocationDataDao; import rocks.inspectit.server.processor.AbstractCmrDataProcessor; import rocks.inspectit.shared.all.cmr.service.ICachedDataService; import rocks.inspectit.shared.all.communication.DefaultData; import rocks.inspectit.shared.all.communication.data.InvocationSequenceData; import rocks.inspectit.shared.all.communication.data.cmr.ApplicationData; import rocks.inspectit.shared.all.communication.data.cmr.BusinessTransactionData; import rocks.inspectit.shared.cs.ci.business.impl.ApplicationDefinition; import rocks.inspectit.shared.cs.ci.business.impl.BusinessTransactionDefinition; import rocks.inspectit.shared.cs.ci.business.impl.IMatchingRuleProvider; import rocks.inspectit.shared.cs.cmr.service.IBusinessContextRegistryService; import rocks.inspectit.shared.cs.cmr.service.IConfigurationInterfaceService; import rocks.inspectit.shared.cs.cmr.service.cache.CachedDataService; /** * This processor enriches {@link InvocationSequenceData} instances (i.e. roots of invocation * sequences) with business context information (i.e. corresponding application and business * transaction). * * @author Alexander Wert * */ public class BusinessContextRecognitionProcessor extends AbstractCmrDataProcessor implements ApplicationListener<BusinessContextDefinitionUpdateEvent> { /** * {@link CachedDataService} instance used to access method information (e.g. method names, * parameters, etc.). */ @Autowired private ICachedDataService cachedDataService; /** * {@link IBusinessContextRegistryService} instance. */ @Autowired private IBusinessContextRegistryService businessContextRegistryService; /** * {@link IConfigurationInterfaceService} instance. */ @Autowired private IConfigurationInterfaceService configurationInterfaceService; /** * The invocation DAO used for updating {@link InvocationSequenceData} objects in the buffer. */ @Autowired private InvocationDataDao invocationDataDao; /** * {@link ExecutorService} for updating business context assignments. */ @Autowired @Resource(name = "scheduledExecutorService") ScheduledExecutorService executorService; /** * {@inheritDoc} */ @Override protected void processData(DefaultData defaultData, EntityManager entityManager) { InvocationSequenceData invocSequence = (InvocationSequenceData) defaultData; assignBusinessContext(invocSequence); } /** * Assigns the business context to the passed {@link InvocationSequenceData} instance. * * @param invocSequence * {@link InvocationSequenceData} instance to assign the business context for. */ private void assignBusinessContext(InvocationSequenceData invocSequence) { List<ApplicationDefinition> applicationDefinitions = configurationInterfaceService.getApplicationDefinitions(); ApplicationDefinition appDefinition = identify(invocSequence, applicationDefinitions); if (null == appDefinition) { appDefinition = ApplicationDefinition.DEFAULT_APPLICATION_DEFINITION; } ApplicationData application = businessContextRegistryService.registerApplication(appDefinition); invocSequence.setApplicationId(application.getId()); BusinessTransactionDefinition businessTxDefinition = identify(invocSequence, appDefinition.getBusinessTransactionDefinitions()); String businessTxName = businessTxDefinition.determineBusinessTransactionName(invocSequence, cachedDataService); BusinessTransactionData businessTransaction = businessContextRegistryService.registerBusinessTransaction(application, businessTxDefinition, businessTxName); invocSequence.setBusinessTransactionId(businessTransaction.getId()); } /** * Identifies a matching rule provider. * * @param invocSequence * {@link InvocationSequenceData} instance providing the evaluation context. * @param ruleProviders * list of provider candidates. * @param <E> * the type of the {@link IMatchingRuleProvider} instance. * @return one selected rule provider if any matches, otherwise null. */ private <E extends IMatchingRuleProvider> E identify(InvocationSequenceData invocSequence, List<E> ruleProviders) { for (E ruleProvider : ruleProviders) { boolean ruleMatches = ruleProvider.getMatchingRuleExpression().evaluate(invocSequence, cachedDataService); if (ruleMatches) { return ruleProvider; } } return null; } /** * {@inheritDoc} */ @Override public void onApplicationEvent(BusinessContextDefinitionUpdateEvent event) { executorService.execute(new Runnable() { @Override public void run() { // update business context for invocation sequences that are in the buffer List<InvocationSequenceData> invocations = invocationDataDao.getInvocationSequenceDetail(0, 0, -1, null, null, null); for (InvocationSequenceData invocation : invocations) { assignBusinessContext(invocation); } } }); } /** * {@inheritDoc} */ @Override public boolean canBeProcessed(DefaultData defaultData) { return defaultData instanceof InvocationSequenceData; } }