Java tutorial
/* * Copyright (c) 2005-2008, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * 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 * * 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.wso2.carbon.mediation.statistics.monitor; import org.apache.axiom.om.OMAttribute; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.impl.builder.StAXOMBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.synapse.aspects.ComponentType; import org.apache.synapse.commons.jmx.MBeanRegistrar; import org.wso2.carbon.mediation.statistics.MediationStatisticsObserver; import org.wso2.carbon.mediation.statistics.MediationStatisticsSnapshot; import org.wso2.carbon.mediation.statistics.MessageTraceLog; import org.wso2.carbon.mediation.statistics.StatisticsRecord; import org.wso2.carbon.utils.CarbonUtils; import javax.xml.namespace.QName; import java.io.File; import java.io.InputStream; import java.io.FileInputStream; import java.util.Map; import java.util.HashMap; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import java.util.concurrent.locks.ReentrantLock; /** * This class gets stats updates from the mediation stats component. All update events are stored * for a period of 1 minute. A Timer task runs with an interval of 1 minute and it exposes all * stored stats in the MBeans. So the MBeans will we updated once a minute with the stats related * to the passed minute. */ public class EsbStatisticsConsumer implements MediationStatisticsObserver { private static final Log log = LogFactory.getLog(EsbStatisticsConsumer.class); private static final String SEQUENCE_MONITOR = "Sequence-Monitor"; private static final String ENDPOINT_MONITOR = "Endpoint-Monitor"; private static final String ENDPOINT_OPERATION_MONITOR = "Endpoint-Operation-Monitor"; private static final String MEMORY_MONITOR = "Memory-Monitor"; private static final String ESB_MONITOR = "ESB-Monitor"; private static final String MEMORY_ID = "system-memory"; private static final String ESB_ID = "entire-esb"; private static final String STAT_PROP_XML = "stat-properties.xml"; private static final float MEGA = 1024 * 1024; private Map<String, SequenceStatView> sequenceViewMap; private Map<String, EndpointStatView> endpointViewMap; private Map<String, EndpointOperationStatView> endpointOperationViewMap; private MemoryStatView memoryView; private EsbStatView esbView; private Map<String, String> registeredMbeanIds; private Map<String, String> endpointThresholds; private volatile List<StatisticsRecord> lastMinRecords; private ReentrantLock lock = new ReentrantLock(); public EsbStatisticsConsumer() { sequenceViewMap = new HashMap<String, SequenceStatView>(); endpointViewMap = new HashMap<String, EndpointStatView>(); endpointOperationViewMap = new HashMap<String, EndpointOperationStatView>(); registeredMbeanIds = new HashMap<String, String>(); endpointThresholds = new HashMap<String, String>(); lastMinRecords = new ArrayList<StatisticsRecord>(); readStatProperties(); // We start the scheduler here. it will call the exposeData method after each 1 min new StatScheduler(this).schedule(); } public void destroy() { if (log.isDebugEnabled()) { log.debug("Destroying all the MBeans in the custom statistics consumer"); } for (String key : registeredMbeanIds.keySet()) { MBeanRegistrar.getInstance().unRegisterMBean(key, registeredMbeanIds.get(key)); } } public void updateStatistics(MediationStatisticsSnapshot mediationStatisticsSnapshot) { // storing the received update. lock the lastMinRecords until this is done. lock.lock(); StatisticsRecord record = mediationStatisticsSnapshot.getUpdate(); try { lastMinRecords.add(new StatisticsRecord(record)); } finally { lock.unlock(); } } public void notifyTraceLogs(MessageTraceLog[] messageTraceLogs) { } /** * Mediation stats component calls this method time to time. We store received updates for * a period of one minute until the Time task processes them. * * @param updateRecord - update * @param entitySnap - * @param categorySnapshot - */ public void updateStatistics(StatisticsRecord updateRecord, StatisticsRecord entitySnap, StatisticsRecord categorySnapshot) { // storing the received update. lock the lastMinRecords until this is done. lock.lock(); try { lastMinRecords.add(new StatisticsRecord(updateRecord)); } finally { lock.unlock(); } } /** * This method will be repeatedly called by the timer task with an interval of 1 min. Here, we * clear all currently existing data on MBeans first. Then expose the data stored during past * 1 min through the MBeans. */ public void exposeData() { // We are going to use the stored data in the lastMinRecords. We have to lock the // lastMinRecords list until data are used and the list is cleaned up.. lock.lock(); try { // Fill MBeans with new data for (StatisticsRecord record : lastMinRecords) { exposeDataOnMBeans(record); } // Clean the update records collected duing last minute lastMinRecords.clear(); } finally { lock.unlock(); } // Check whether the endpoints are active or not using the requests received.. EndpointStatView endpointView; long threshold; for (String key : endpointViewMap.keySet()) { endpointView = endpointViewMap.get(key); if (endpointThresholds.get(key) != null) { threshold = Long.parseLong(endpointThresholds.get(key)); if (endpointView.getTransactionsIn() < threshold) { endpointView.setActive(false); } else { endpointView.setActive(true); } } } } /** * This method fills the MBeans with the given update record * * @param updateRecord - update record */ private void exposeDataOnMBeans(StatisticsRecord updateRecord) { // We only consider the In flow stats.. ComponentType type = updateRecord.getType(); if (type == ComponentType.SEQUENCE) { SequenceStatView view; if (!sequenceViewMap.containsKey(updateRecord.getResourceId())) { view = new SequenceStatView(); MBeanRegistrar.getInstance().registerMBean(view, SEQUENCE_MONITOR, (updateRecord.getResourceId())); registeredMbeanIds.put(SEQUENCE_MONITOR, (updateRecord.getResourceId())); sequenceViewMap.put(updateRecord.getResourceId(), view); } else { view = sequenceViewMap.get(updateRecord.getResourceId()); } updateCommonView(view, updateRecord); } if (updateRecord.isInStatistic()) { if (type == ComponentType.ENDPOINT) { // Handling total endpoint related stats EndpointStatView endpointView; String endpointName = getEndpointName(updateRecord.getResourceId()); if (!endpointViewMap.containsKey(endpointName)) { endpointView = new EndpointStatView(); MBeanRegistrar.getInstance().registerMBean(endpointView, ENDPOINT_MONITOR, endpointName); registeredMbeanIds.put(ENDPOINT_MONITOR, endpointName); endpointViewMap.put(endpointName, endpointView); } else { endpointView = endpointViewMap.get(endpointName); } updateEndpointView(endpointView, updateRecord); // Handling individual operation stats of the endpoint EndpointOperationStatView endpointOpView; if (!endpointOperationViewMap.containsKey(updateRecord.getResourceId())) { endpointOpView = new EndpointOperationStatView(); MBeanRegistrar.getInstance().registerMBean(endpointOpView, ENDPOINT_OPERATION_MONITOR, updateRecord.getResourceId()); registeredMbeanIds.put(ENDPOINT_OPERATION_MONITOR, updateRecord.getResourceId()); endpointOperationViewMap.put(updateRecord.getResourceId(), endpointOpView); } else { endpointOpView = endpointOperationViewMap.get(updateRecord.getResourceId()); } updateEndpointOperationView(endpointOpView, updateRecord); // We update the ESB monitor here (stats for all endpoints) if (esbView == null) { esbView = new EsbStatView(); MBeanRegistrar.getInstance().registerMBean(esbView, ESB_MONITOR, ESB_ID); registeredMbeanIds.put(ESB_MONITOR, ESB_ID); } updateEsbView(esbView, updateRecord); } } // We update the memory monitor here if (memoryView == null) { memoryView = new MemoryStatView(); MBeanRegistrar.getInstance().registerMBean(memoryView, MEMORY_MONITOR, MEMORY_ID); registeredMbeanIds.put(MEMORY_MONITOR, MEMORY_ID); } updateMemoryView(memoryView); } private void updateCommonView(SequenceStatView view, StatisticsRecord update) { long updatedTotalCount = view.getTransactionsIn() + update.getTotalCount(); long updateFaultCount = view.getNumberOfErrorsIn() + update.getFaultCount(); if (updatedTotalCount > 0) { view.setAvgTimeInLastMin( (view.getAvgTimeIn() * view.getTransactionsIn() + update.getAvgTime() * update.getTotalCount()) / updatedTotalCount); view.setAvgMediationTimeInLastMin(-1); view.setAvgMediationTimeInLastMin(-1); view.setErrorPercentageInLastMin((updateFaultCount / updatedTotalCount) * 100); } view.setNumberOfErrorsInLastMin(updateFaultCount); view.setTransactionsInLastMin(updatedTotalCount); } private void updateEndpointView(EndpointStatView view, StatisticsRecord update) { view.setTransactionsInLastMin(view.getTransactionsIn() + update.getTotalCount()); } private void updateEndpointOperationView(EndpointOperationStatView view, StatisticsRecord update) { long updatedTotalCount = view.getTransactionsIn() + update.getTotalCount(); double totalTime = view.getAverageTransactionDurationIn() * view.getTransactionsIn() + update.getAvgTime() * update.getTotalCount(); if (updatedTotalCount > 0 && totalTime > 0) { view.setAvgTransactionDurationInLastMin(totalTime / updatedTotalCount); } view.setTransactionsInLastMin(updatedTotalCount); } private void updateEsbView(EsbStatView view, StatisticsRecord update) { long totalTransactions = view.getTransactionsIn() + update.getTotalCount(); long totalErrors = view.getErrorsIn() + update.getFaultCount(); view.setTransactionsInLastMin(totalTransactions); view.setErrorsInLastMin(totalErrors); if (totalTransactions > 0) { view.setErrorPercentageInLastMin(totalErrors * 100 / totalTransactions); } } private void updateMemoryView(MemoryStatView view) { Runtime runtime = Runtime.getRuntime(); view.setTotalMemory(runtime.totalMemory() / MEGA); view.setFreeMemory(runtime.freeMemory() / MEGA); view.setUsedMemory((runtime.totalMemory() - runtime.freeMemory()) / MEGA); view.setMaxMemory(runtime.maxMemory() / MEGA); } /** * Reads the stat-properties.xml file from the conf folder and loads the properties * related to statistics */ private void readStatProperties() { String statPropPath = CarbonUtils.getCarbonHome() + "/conf/" + STAT_PROP_XML; File f = new File(statPropPath); if (!f.exists()) { log.error(STAT_PROP_XML + " file not found at : " + statPropPath); return; } InputStream xmlInputStream; try { xmlInputStream = new FileInputStream(f); OMElement documentElement = new StAXOMBuilder(xmlInputStream).getDocumentElement(); OMElement endpointPropElement = documentElement.getFirstChildWithName(new QName("endpointProperties")); Iterator itr = endpointPropElement.getChildrenWithLocalName("endpoint"); String name, threshold = null; while (itr.hasNext()) { OMElement endpoint = (OMElement) itr.next(); name = readAttribute(endpoint, "name"); OMElement thresholdEle = endpoint.getFirstChildWithName(new QName("threshold")); if (thresholdEle != null) { threshold = thresholdEle.getText(); } if (name != null && threshold != null) { endpointThresholds.put(name, threshold); } } } catch (Exception e) { log.error("Error while parsing file : " + STAT_PROP_XML, e); } } private String readAttribute(OMElement element, String attName) { if (element == null) { return null; } OMAttribute temp = element.getAttribute(new QName(attName)); if (temp != null) { return temp.getAttributeValue(); } return null; } private String getEndpointName(String resId) { String[] temp = resId.split("__"); return temp[0]; } }