Java tutorial
/** * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * <p/> * WSO2 Inc. 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 * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * 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.synapse.aspects.flow.statistics.log; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.synapse.aspects.ComponentType; import org.apache.synapse.aspects.flow.statistics.data.aggregate.StatisticsEntry; import org.apache.synapse.aspects.flow.statistics.data.raw.BasicStatisticDataUnit; import org.apache.synapse.aspects.flow.statistics.data.raw.CallbackDataUnit; import org.apache.synapse.aspects.flow.statistics.data.raw.StatisticDataUnit; import org.apache.synapse.aspects.flow.statistics.util.StatisticCleaningThread; import org.apache.synapse.aspects.flow.statistics.util.StatisticsConstants; import org.apache.synapse.config.SynapsePropertiesLoader; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; /** * This class is to process the events and build runtime-statistics map for each message flow */ public class StatisticEventProcessor { private static final Log log = LogFactory.getLog(StatisticEventProcessor.class); /** * Map to hold statistic of current message flows in esb. */ private static Map<String, StatisticsEntry> runtimeStatistics = new HashMap<>(); public static void initializeCleaningThread() { //Thread to consume queue and update data structures for publishing ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setName("Mediation Statistic Stale Entry Cleaning Task"); return t; } }); Long eventCleanTime = Long.parseLong( SynapsePropertiesLoader.getPropertyValue(StatisticsConstants.FLOW_STATISTICS_EVENT_CLEAN_TIME, StatisticsConstants.FLOW_STATISTICS_DEFAULT_EVENT_CLEAN_INTERVAL)); StatisticCleaningThread statisticCleaningThread = new StatisticCleaningThread(runtimeStatistics); executor.scheduleAtFixedRate(statisticCleaningThread, 0, eventCleanTime, TimeUnit.MILLISECONDS); } /** * Opens statistic log for the reporting component. * * @param statisticDataUnit raw statistic data object. */ public static void openStatisticEntry(StatisticDataUnit statisticDataUnit) { if (runtimeStatistics.containsKey(statisticDataUnit.getStatisticId())) { if (log.isDebugEnabled()) { log.debug("Reported open statistics for component: " + statisticDataUnit.getComponentName() + " for " + "message flow :" + statisticDataUnit.getStatisticId()); } runtimeStatistics.get(statisticDataUnit.getStatisticId()).createLog(statisticDataUnit); } else if (!(statisticDataUnit.getComponentType() == ComponentType.MEDIATOR || statisticDataUnit.getComponentType() == ComponentType.RESOURCE)) { //Mediators and resources can't start statistic collection for a flow. if (statisticDataUnit.isIndividualStatisticCollected() && statisticDataUnit.getCurrentIndex() == 0) { StatisticsEntry statisticsEntry = new StatisticsEntry(statisticDataUnit); runtimeStatistics.put(statisticDataUnit.getStatisticId(), statisticsEntry); if (log.isDebugEnabled()) { log.debug("Creating New Entry in Running Statistics: Current size :" + runtimeStatistics.size() + "|Statistic Id : " + statisticDataUnit.getStatisticId()); } } else if (statisticDataUnit.getCurrentIndex() > 0 && !statisticDataUnit.isIndividualStatisticCollected()) { if (log.isDebugEnabled()) { log.debug("Component: " + statisticDataUnit.getComponentName() + " is in a middle of the statistics " + "collection. But collection cannot be found and it seems to be broken. |Statistic Id : " + statisticDataUnit.getStatisticId()); } } else { log.error( "Component: " + statisticDataUnit.getComponentName() + " is tried to open statistics, but " + "its individual collection was not enabled. |Statistic Id : " + statisticDataUnit.getStatisticId()); } } else { log.error("Component: " + statisticDataUnit.getComponentName() + " is tried to open statistics, but " + "its not a statistic entry component. |Statistic Id : " + statisticDataUnit.getStatisticId()); } } /** * Closes statistic collection log after finishing statistic collection for that component. * * @param dataUnit raw data unit containing id relevant for closing * @param mode Mode of closing GRACEFULLY_CLOSE, ATTEMPT_TO_CLOSE or FORCEFULLY_CLOSE */ public static void closeStatisticEntry(BasicStatisticDataUnit dataUnit, int mode) { if (log.isDebugEnabled()) { log.debug("Closing statistic event received for " + dataUnit.getStatisticId()); } if (runtimeStatistics.containsKey(dataUnit.getStatisticId())) { StatisticsEntry statisticsEntry = runtimeStatistics.get(dataUnit.getStatisticId()); if (StatisticsConstants.GRACEFULLY_CLOSE == mode) { /** * Ends statistics collection log for the reported statistics component. */ if (log.isDebugEnabled()) { log.debug("Closing statistic event received for component :" + ((StatisticDataUnit) dataUnit).getComponentName() + " for the message flow : " + dataUnit.getStatisticId()); } boolean finished = statisticsEntry.closeLog((StatisticDataUnit) dataUnit); if (finished) { endMessageFlow(dataUnit, statisticsEntry, false); } } else if (StatisticsConstants.ATTEMPT_TO_CLOSE == mode) { /** * Check whether Statistics entry present for the message flow and if there is an entry try * to finish ending statistics collection for that entry. */ if (log.isDebugEnabled()) { log.debug("Trying to close statistic for " + dataUnit.getStatisticId()); } endMessageFlow(dataUnit, statisticsEntry, false); } else if (StatisticsConstants.FORCEFULLY_CLOSE == mode) { /** * Close the statistic log after finishing the message flow forcefully. When we try to use this method to end * statistic collection for a message flow it will not consider any thing and close all the remaining logs and * will send the completed statistic entry for collection. */ if (log.isDebugEnabled()) { log.debug("Forcefully close statistic event received for " + dataUnit.getStatisticId()); } endMessageFlow(dataUnit, statisticsEntry, true); } else { log.error("Invalid mode for closing statistic entry |Statistic Id : " + dataUnit.getStatisticId()); } } else { if (log.isDebugEnabled()) { log.debug(StatisticsConstants.STATISTIC_NOT_FOUND_ERROR + dataUnit.getStatisticId()); } } } /** * End the statistics collection for the message flow. If entry is successfully completed ending * its statistics collection statistics store is updated with new statistics data. Then entry * is removed from the running statistic map. * * @param dataUnit Statistics raw data object. * @param statisticsEntry Statistic entry for the message flow. * @param closeForceFully Whether to close statistics forcefully. */ private synchronized static void endMessageFlow(BasicStatisticDataUnit dataUnit, StatisticsEntry statisticsEntry, boolean closeForceFully) { if (log.isDebugEnabled()) { log.debug("Checking whether message flow is ended for " + dataUnit.getStatisticId()); } boolean isMessageFlowEnded = statisticsEntry.endAll(dataUnit, closeForceFully); if (isMessageFlowEnded) { if (log.isDebugEnabled()) { log.debug("Statistic collection is ended for the message flow with statistic " + "trace Id :" + dataUnit.getStatisticId()); } dataUnit.getSynapseEnvironment().getCompletedStatisticStore() .putCompletedStatisticEntry(statisticsEntry.getMessageFlowLogs()); runtimeStatistics.remove(dataUnit.getStatisticId()); } } /** * Opens Flow Continuable mediators after callback is received for continuation call to the backend. * * @param basicStatisticDataUnit data unit which holds raw data */ public static void openParents(BasicStatisticDataUnit basicStatisticDataUnit) { if (log.isDebugEnabled()) { log.debug("Open parent event is reported for " + basicStatisticDataUnit.getStatisticId()); } if (runtimeStatistics.containsKey(basicStatisticDataUnit.getStatisticId())) { runtimeStatistics.get(basicStatisticDataUnit.getStatisticId()) .openFlowContinuableMediators(basicStatisticDataUnit); } else if (log.isDebugEnabled()) { log.debug(StatisticsConstants.STATISTIC_NOT_FOUND_ERROR + basicStatisticDataUnit.getStatisticId()); } } /** * Registers callback information for the message flow on the corresponding StatisticsEntry. * * @param callbackDataUnit raw statistic data unit */ public static void addCallbacks(CallbackDataUnit callbackDataUnit) { if (log.isDebugEnabled()) { log.debug("Callback registering event is reported for " + callbackDataUnit.getStatisticId()); } if (runtimeStatistics.containsKey(callbackDataUnit.getStatisticId())) { runtimeStatistics.get(callbackDataUnit.getStatisticId()).addCallback(callbackDataUnit); } else if (log.isDebugEnabled()) { log.debug(StatisticsConstants.STATISTIC_NOT_FOUND_ERROR + callbackDataUnit.getStatisticId()); } } /** * Removes specified callback info from StatisticsEntry for the message flow after all the processing for that * callback is ended. * * @param callbackDataUnit raw statistic data unit */ public static void removeCallback(CallbackDataUnit callbackDataUnit) { if (log.isDebugEnabled()) { log.debug("Callback remove event is reported for " + callbackDataUnit.getStatisticId()); } if (runtimeStatistics.containsKey(callbackDataUnit.getStatisticId())) { runtimeStatistics.get(callbackDataUnit.getStatisticId()).removeCallback(callbackDataUnit); } else if (log.isDebugEnabled()) { log.debug(StatisticsConstants.STATISTIC_NOT_FOUND_ERROR + callbackDataUnit.getStatisticId()); } } /** * Updates end time of the statistics logs in the StatisticsEntry after corresponding callback is removed from * SynapseCallbackReceiver. * * @param callbackDataUnit raw statistic data unit */ public static void updateForReceivedCallback(CallbackDataUnit callbackDataUnit) { if (log.isDebugEnabled()) { log.debug("Callback received event is reported for " + callbackDataUnit.getStatisticId()); } if (runtimeStatistics.containsKey(callbackDataUnit.getStatisticId())) { runtimeStatistics.get(callbackDataUnit.getStatisticId()).updateCallbackReceived(callbackDataUnit); } else if (log.isDebugEnabled()) { log.debug(StatisticsConstants.STATISTIC_NOT_FOUND_ERROR + callbackDataUnit.getStatisticId()); } } /** * Report to the StatisticsEntry that message flow encountered a Fault During Mediation. * * @param basicStatisticDataUnit raw statistic unit carrying statistic data */ public static void reportFault(BasicStatisticDataUnit basicStatisticDataUnit) { if (log.isDebugEnabled()) { log.debug("Fault Occurring is reported for " + basicStatisticDataUnit.getStatisticId()); } if (runtimeStatistics.containsKey(basicStatisticDataUnit.getStatisticId())) { runtimeStatistics.get(basicStatisticDataUnit.getStatisticId()).reportFault(basicStatisticDataUnit); } else if (log.isDebugEnabled()) { log.debug(StatisticsConstants.STATISTIC_NOT_FOUND_ERROR + basicStatisticDataUnit.getStatisticId()); } } /** * Report to the StatisticsEntry that message flow encountered Asynchronous flow. * * @param basicStatisticDataUnit raw statistic unit carrying statistic data */ public static void reportAsynchronousExecution(BasicStatisticDataUnit basicStatisticDataUnit) { if (log.isDebugEnabled()) { log.debug("Asynchronous execution reported for " + basicStatisticDataUnit.getStatisticId()); } if (runtimeStatistics.containsKey(basicStatisticDataUnit.getStatisticId())) { runtimeStatistics.get(basicStatisticDataUnit.getStatisticId()) .addAsynchronousFlow(basicStatisticDataUnit); } else if (log.isDebugEnabled()) { log.debug(StatisticsConstants.STATISTIC_NOT_FOUND_ERROR + basicStatisticDataUnit.getStatisticId()); } } }