com.espertech.esper.epl.metric.MetricReportingServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.espertech.esper.epl.metric.MetricReportingServiceImpl.java

Source

/**************************************************************************************
 * Copyright (C) 2008 EsperTech, Inc. All rights reserved.                            *
 * http://esper.codehaus.org                                                          *
 * http://www.espertech.com                                                           *
 * ---------------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the GPL license       *
 * a copy of which has been included with this distribution in the license.txt file.  *
 **************************************************************************************/
package com.espertech.esper.epl.metric;

import com.espertech.esper.client.ConfigurationException;
import com.espertech.esper.client.ConfigurationMetricsReporting;
import com.espertech.esper.client.EPRuntime;
import com.espertech.esper.client.metric.MetricEvent;
import com.espertech.esper.core.service.EPServicesContext;
import com.espertech.esper.core.service.StatementLifecycleEvent;
import com.espertech.esper.core.service.StatementLifecycleObserver;
import com.espertech.esper.core.service.StatementResultListener;
import com.espertech.esper.util.MetricUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Metrics reporting.
 * <p>
 * Reports for all statements even if not in a statement group, i.e. statement in default group.
 */
public class MetricReportingServiceImpl
        implements MetricReportingServiceSPI, MetricEventRouter, StatementLifecycleObserver {
    private static final Log log = LogFactory.getLog(MetricReportingServiceImpl.class);

    private final ConfigurationMetricsReporting specification;
    private final String engineUri;

    private volatile MetricExecutionContext executionContext;

    private boolean isScheduled;
    private final MetricScheduleService schedule;
    private final StatementMetricRepository stmtMetricRepository;

    private MetricExecEngine metricExecEngine;
    private MetricExecStatement metricExecStmtGroupDefault;
    private Map<String, MetricExecStatement> statementGroupExecutions;

    private final Map<String, StatementMetricHandle> statementMetricHandles;
    private final MetricsExecutor metricsExecutor;

    private CopyOnWriteArraySet<StatementResultListener> statementOutputHooks;

    /**
     * Ctor.
     * @param specification configuration
     * @param engineUri engine URI
     */
    public MetricReportingServiceImpl(ConfigurationMetricsReporting specification, String engineUri) {
        if (specification.isEnableMetricsReporting()) {
            MetricUtil.initialize();
        }
        this.specification = specification;
        this.engineUri = engineUri;
        schedule = new MetricScheduleService();

        stmtMetricRepository = new StatementMetricRepository(engineUri, specification);
        statementGroupExecutions = new LinkedHashMap<String, MetricExecStatement>();
        statementMetricHandles = new HashMap<String, StatementMetricHandle>();
        statementOutputHooks = new CopyOnWriteArraySet<StatementResultListener>();

        if (specification.isThreading()) {
            metricsExecutor = new MetricsExecutorThreaded(engineUri);
        } else {
            metricsExecutor = new MetricsExecutorUnthreaded();
        }
    }

    public void addStatementResultListener(StatementResultListener listener) {
        statementOutputHooks.add(listener);
    }

    public void removeStatementResultListener(StatementResultListener listener) {
        statementOutputHooks.remove(listener);
    }

    public CopyOnWriteArraySet<StatementResultListener> getStatementOutputHooks() {
        return statementOutputHooks;
    }

    public void setContext(EPRuntime runtime, EPServicesContext servicesContext) {
        MetricExecutionContext metricsExecutionContext = new MetricExecutionContext(servicesContext, runtime,
                stmtMetricRepository);

        // create all engine and statement executions
        metricExecEngine = new MetricExecEngine(this, engineUri, schedule, specification.getEngineInterval());
        metricExecStmtGroupDefault = new MetricExecStatement(this, schedule, specification.getStatementInterval(),
                0);

        int countGroups = 1;
        for (Map.Entry<String, ConfigurationMetricsReporting.StmtGroupMetrics> entry : specification
                .getStatementGroups().entrySet()) {
            ConfigurationMetricsReporting.StmtGroupMetrics config = entry.getValue();
            MetricExecStatement metricsExecution = new MetricExecStatement(this, schedule, config.getInterval(),
                    countGroups);
            this.statementGroupExecutions.put(entry.getKey(), metricsExecution);
            countGroups++;
        }

        // last assign this volatile variable so the time event processing may schedule callbacks 
        executionContext = metricsExecutionContext;
    }

    public void processTimeEvent(long timeEventTime) {
        if (!MetricReportingPath.isMetricsEnabled) {
            return;
        }

        schedule.setTime(timeEventTime);
        if (!isScheduled) {
            if (executionContext != null) {
                scheduleExecutions();
                isScheduled = true;
            } else {
                return; // not initialized yet, race condition and must wait till initialized
            }
        }

        // fast evaluation against nearest scheduled time
        Long nearestTime = schedule.getNearestTime();
        if ((nearestTime == null) || (nearestTime > timeEventTime)) {
            return;
        }

        // get executions
        List<MetricExec> executions = new ArrayList<MetricExec>(2);
        schedule.evaluate(executions);
        if (executions.isEmpty()) {
            return;
        }

        // execute
        if (executionContext == null) {
            log.debug(".processTimeEvent No execution context");
            return;
        }

        for (MetricExec execution : executions) {
            metricsExecutor.execute(execution, executionContext);
        }
    }

    public void destroy() {
        schedule.clear();
        metricsExecutor.destroy();
    }

    public void route(MetricEvent metricEvent) {
        executionContext.getRuntime().sendEvent(metricEvent);
    }

    public void accountTime(StatementMetricHandle metricsHandle, long deltaCPU, long deltaWall,
            int numInputEvents) {
        stmtMetricRepository.accountTimes(metricsHandle, deltaCPU, deltaWall, numInputEvents);
    }

    public void accountOutput(StatementMetricHandle handle, int numIStream, int numRStream) {
        stmtMetricRepository.accountOutput(handle, numIStream, numRStream);
    }

    public StatementMetricHandle getStatementHandle(String statementId, String statementName) {
        if (!MetricReportingPath.isMetricsEnabled) {
            return null;
        }

        StatementMetricHandle handle = stmtMetricRepository.addStatement(statementName);
        statementMetricHandles.put(statementName, handle);
        return handle;
    }

    public void observe(StatementLifecycleEvent theEvent) {
        if (!MetricReportingPath.isMetricsEnabled) {
            return;
        }

        if (theEvent.getEventType() == StatementLifecycleEvent.LifecycleEventType.STATECHANGE) {
            if (theEvent.getStatement().isDestroyed()) {
                stmtMetricRepository.removeStatement(theEvent.getStatement().getName());
                statementMetricHandles.remove(theEvent.getStatement().getName());
            }
        }
    }

    public void setMetricsReportingInterval(String stmtGroupName, long newInterval) {
        if (stmtGroupName == null) {
            metricExecStmtGroupDefault.setInterval(newInterval);
            return;
        }

        MetricExecStatement exec = this.statementGroupExecutions.get(stmtGroupName);
        if (exec == null) {
            throw new IllegalArgumentException(
                    "Statement group by name '" + stmtGroupName + "' could not be found");
        }
        exec.setInterval(newInterval);
    }

    private boolean isConsiderSchedule(long value) {
        if ((value > 0) && (value < Long.MAX_VALUE)) {
            return true;
        }
        return false;
    }

    public void setMetricsReportingStmtDisabled(String statementName) throws ConfigurationException {
        StatementMetricHandle handle = statementMetricHandles.get(statementName);
        if (handle == null) {
            throw new ConfigurationException(
                    "Statement by name '" + statementName + "' not found in metrics collection");
        }
        handle.setEnabled(false);
    }

    public void setMetricsReportingStmtEnabled(String statementName) throws ConfigurationException {
        StatementMetricHandle handle = statementMetricHandles.get(statementName);
        if (handle == null) {
            throw new ConfigurationException(
                    "Statement by name '" + statementName + "' not found in metrics collection");
        }
        handle.setEnabled(true);
    }

    public void setMetricsReportingEnabled() {
        if (!specification.isEnableMetricsReporting()) {
            throw new ConfigurationException(
                    "Metrics reporting must be enabled through initialization-time configuration");
        }
        scheduleExecutions();
        MetricReportingPath.setMetricsEnabled(true);
    }

    public void setMetricsReportingDisabled() {
        schedule.clear();
        MetricReportingPath.setMetricsEnabled(false);
    }

    private void scheduleExecutions() {
        if (!specification.isEnableMetricsReporting()) {
            return;
        }

        if (isConsiderSchedule(metricExecEngine.getInterval())) {
            schedule.add(metricExecEngine.getInterval(), metricExecEngine);
        }

        // schedule each statement group, count the "default" group as the first group
        if (isConsiderSchedule(metricExecStmtGroupDefault.getInterval())) {
            schedule.add(metricExecStmtGroupDefault.getInterval(), metricExecStmtGroupDefault);
        }

        for (MetricExecStatement metricsExecution : statementGroupExecutions.values()) {
            if (isConsiderSchedule(metricsExecution.getInterval())) {
                schedule.add(metricsExecution.getInterval(), metricsExecution);
            }
        }
    }
}