org.hyperic.hq.measurement.galerts.ResourceMetricTracker.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.measurement.galerts.ResourceMetricTracker.java

Source

/*
 * NOTE: This copyright does *not* cover user programs that use HQ
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 * "derived work".
 *
 * Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
 * This file is part of HQ.
 *
 * HQ is free software; you can redistribute it and/or modify
 * it under the terms version 2 of the GNU General Public License as
 * published by the Free Software Foundation. This program is distributed
 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 */

package org.hyperic.hq.measurement.galerts;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.product.MetricValue;

/**
 * Tracks chronologically the metrics for a given resource.
 */
class ResourceMetricTracker {

    private static final Log _log = LogFactory.getLog(ResourceMetricTracker.class);

    private final ComparisonOperator _comparator;

    private final Float _violatingMetricValue;

    private final boolean _isNotReportingOffending;

    private final LinkedList _chronOrderedValues;

    /**
     * Creates an instance.
     *
     * @param comparator The comparator used to check for violating the trigger 
     *                   condition.
     * @param violatingMetricValue The violating metric value.
     * @param isNotReportingOffending <code>true</code> if not reporting 
     *                                resources are considered offending; 
     *                                <code>false</code> otherwise.                         
     */
    public ResourceMetricTracker(ComparisonOperator comparator, Float violatingMetricValue,
            boolean isNotReportingOffending) {
        _comparator = comparator;
        _violatingMetricValue = violatingMetricValue;
        _isNotReportingOffending = isNotReportingOffending;
        _chronOrderedValues = new LinkedList();
    }

    /**
     * Track a new metric value.
     * 
     * @param value The metric value.                            
     */
    public void trackMetricValue(MetricValue value) {
        removeNewerTrackedMetrics(value);
        _chronOrderedValues.add(value);
    }

    /**
     * @return The current number of tracked metrics.
     */
    public int getNumberOfTrackedMetrics() {
        return _chronOrderedValues.size();
    }

    /**
     * Search for the first metric value violating the trigger condition in 
     * the given time window. Any metric value older than the window start 
     * time will be removed from tracking automatically.
     * 
     * @param startTime The start timestamp for the window (inclusive).
     * @param endTime The end timestamp for the window (inclusive).
     * @return The violating metric value or <code>null</code> if no metric 
     *         violated in the time window. {@link MetricValue#NONE} is returned 
     *         if not reporting resources are considered offending and there 
     *         is no metric value in the time window.
     */
    public MetricValue searchForViolatingMetricInWindow(long startTime, long endTime) {
        boolean debug = _log.isDebugEnabled();
        boolean hasReportedInWindow = false;

        for (Iterator iter = _chronOrderedValues.iterator(); iter.hasNext();) {
            MetricValue metric = (MetricValue) iter.next();

            long metricTimestamp = metric.getTimestamp();

            if (metricTimestamp < startTime) {
                if (debug) {
                    _log.debug("Aging out metrics older than the current " + "window start time: metric timestamp="
                            + metricTimestamp + ", start time=" + startTime);
                }

                iter.remove();
            } else if (metric.getTimestamp() <= endTime) {
                hasReportedInWindow = true;

                if (_comparator.isTrue(new Float(metric.getValue()), _violatingMetricValue)) {
                    return metric;
                }
            } // else The metric value is in the future - evaluate later          
        }

        if (_isNotReportingOffending && !hasReportedInWindow) {
            return MetricValue.NONE;
        } else {
            // no violating metrics were found in the window
            return null;
        }
    }

    /**
     * If there are any newer (or with the same timestamp) tracked metrics than 
     * this one that just came in, remove those newer tracked metrics. This 
     * accounts for the backfilled case where the backfilled metrics reported 
     * one value, but then the agent starts reporting again with the "real" 
     * values that should preempt the backfilled values.
     * 
     * @param value The metric value that just came in.
     */
    private void removeNewerTrackedMetrics(MetricValue value) {
        if (_chronOrderedValues.isEmpty()) {
            return;
        }

        if (value.getTimestamp() <= ((MetricValue) _chronOrderedValues.getLast()).getTimestamp()) {

            _log.debug("Removing tracked metrics newer than timestamp=" + value.getTimestamp());

            ListIterator iter = _chronOrderedValues.listIterator(_chronOrderedValues.size());

            while (iter.hasPrevious()) {
                MetricValue trackedValue = (MetricValue) iter.previous();

                if (trackedValue.getTimestamp() >= value.getTimestamp()) {
                    iter.remove();
                } else {
                    return;
                }
            }
        }
    }

}