org.wso2.carbon.mediation.statistics.monitor.EsbStatisticsConsumer.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.mediation.statistics.monitor.EsbStatisticsConsumer.java

Source

/*
 *  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];
    }

}