com.github.lpezet.antiope.metrics.aws.MachineMetricFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.github.lpezet.antiope.metrics.aws.MachineMetricFactory.java

Source

/*
 * Copyright 2010-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 com.github.lpezet.antiope.metrics.aws;

import static com.github.lpezet.antiope.metrics.aws.MachineMetric.DaemonThreadCount;
import static com.github.lpezet.antiope.metrics.aws.MachineMetric.DeadLockThreadCount;
import static com.github.lpezet.antiope.metrics.aws.MachineMetric.FreeMemory;
import static com.github.lpezet.antiope.metrics.aws.MachineMetric.OpenFileDescriptorCount;
import static com.github.lpezet.antiope.metrics.aws.MachineMetric.PeakThreadCount;
import static com.github.lpezet.antiope.metrics.aws.MachineMetric.SpareFileDescriptorCount;
import static com.github.lpezet.antiope.metrics.aws.MachineMetric.SpareMemory;
import static com.github.lpezet.antiope.metrics.aws.MachineMetric.ThreadCount;
import static com.github.lpezet.antiope.metrics.aws.MachineMetric.TotalMemory;
import static com.github.lpezet.antiope.metrics.aws.MachineMetric.TotalStartedThreadCount;
import static com.github.lpezet.antiope.metrics.aws.MachineMetric.UsedMemory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.LogFactory;

import com.amazonaws.jmx.spi.JmxInfoProvider;
import com.amazonaws.services.cloudwatch.model.Dimension;
import com.amazonaws.services.cloudwatch.model.MetricDatum;
import com.amazonaws.services.cloudwatch.model.StandardUnit;
import com.github.lpezet.antiope.metrics.MetricType;

class MachineMetricFactory {
    private static final List<MachineMetric> MEMORY_METRICS = Arrays.asList(TotalMemory, FreeMemory, UsedMemory,
            SpareMemory);
    private static final List<MachineMetric> THREAD_METRICS = Arrays.asList(ThreadCount, DeadLockThreadCount,
            DaemonThreadCount, PeakThreadCount, TotalStartedThreadCount);
    private static final List<MachineMetric> FD_METRICS = Arrays.asList(OpenFileDescriptorCount,
            SpareFileDescriptorCount);
    private final JmxInfoProvider mJmxInfoProvider = JmxInfoProvider.Factory.getJmxInfoProvider();

    private Config mConfig;

    public MachineMetricFactory(Config pConfig) {
        mConfig = pConfig;
    }

    /**
     * Add the given list of metrics and corresponding values specified in
     * "metricValues" to the given list of metric datum.
     * 
     * @param pList
     *            list of metric data
     * @param pMetricValues
     *            list of metrics and their corresponding values
     */
    private void addMetrics(List<MetricDatum> pList, MetricValues pMetricValues, StandardUnit pUnit) {
        List<MachineMetric> oMachineMetrics = pMetricValues.getMetrics();
        List<Long> oValues = pMetricValues.getValues();
        for (int i = 0; i < oMachineMetrics.size(); i++) {
            MachineMetric oMetric = oMachineMetrics.get(i);
            long val = oValues.get(i).longValue();
            // skip zero values in some cases
            if (val != 0 || oMetric.includeZeroValue()) {
                MetricDatum oDatum = new MetricDatum().withMetricName(oMetric.getMetricName())
                        .withDimensions(
                                new Dimension().withName(oMetric.getDimensionName()).withValue(oMetric.name()))
                        .withUnit(pUnit).withValue((double) val);
                pList.add(oDatum);
            }
        }
    }

    /**
     * Returns the set of custom machine metrics specified in the SDK metrics
     * registry; or an empty set if there is none. Note any machine metrics
     * found in the registry must have been custom specified, as the default
     * behavior is to include all machine metrics when enabled.
     * 
     * @return a non-null set of machine metrics. An empty set means no custom
     *         machine metrics have been specified.
     */
    private Set<MachineMetric> customMachineMetrics() {
        Set<MachineMetric> oCustomized = new HashSet<MachineMetric>();
        for (MetricType m : mConfig.getMetricsConfig().getPredefinedMetrics()) {
            if (m instanceof MachineMetric)
                oCustomized.add((MachineMetric) m);
        }
        return oCustomized;
    }

    /**
     * Returns a subset of the given list of metrics in "defaults" and the
     * corresponding value of each returned metric in the subset. Note if the
     * custom set is empty, the full set of default machine metrics and values
     * will be returned. (In particular, as in set theory, a set is a subset of
     * itself.)
     * 
     * @param pCustomSet
     *            custom machine metrics specified in the SDK metrics registry
     * @param pDefaults
     *            the given default list of metrics
     * @param pValues
     *            corresponding values of each metric in "defaults"
     */
    private MetricValues metricValues(Set<MachineMetric> pCustomSet, List<MachineMetric> pDefaults,
            List<Long> pValues) {
        List<MachineMetric> oActualMetrics = pDefaults;
        List<Long> oActualValues = pValues;
        if (pCustomSet.size() > 0) {
            // custom set of machine metrics specified
            oActualMetrics = new ArrayList<MachineMetric>();
            oActualValues = new ArrayList<Long>();
            for (int i = 0; i < pDefaults.size(); i++) {
                MachineMetric mm = pDefaults.get(i);
                if (pCustomSet.contains(mm)) {
                    oActualMetrics.add(mm);
                    oActualValues.add(pValues.get(i));
                }
            }
        }
        return new MetricValues(oActualMetrics, oActualValues);
    }

    List<MetricDatum> generateMetrics() {
        if (mConfig.getMetricsConfig().isMachineMetricExcluded())
            return Collections.emptyList();
        Set<MachineMetric> oCustomSet = customMachineMetrics();
        List<MetricDatum> oTargetList = new ArrayList<MetricDatum>(MachineMetric.values().length);
        // Memory usage
        addMemoryMetrics(oTargetList, oCustomSet);
        // Thread related counts
        try {
            addThreadMetrics(oTargetList, oCustomSet);
        } catch (Throwable t) {
            LogFactory.getLog(getClass()).debug("Ignoring thread metrics", t);
        }
        // File descriptor usage
        try {
            addFileDescriptorMetrics(oTargetList, oCustomSet);
        } catch (Throwable t) {
            LogFactory.getLog(getClass()).debug("Ignoring file descriptor metrics", t);
        }
        return oTargetList;
    }

    private void addMemoryMetrics(List<MetricDatum> pTargetList, Set<MachineMetric> pCustomSet) {
        Runtime rt = Runtime.getRuntime();
        long oTotalMem = rt.totalMemory();
        long oFreeMem = rt.freeMemory();
        long oUsedMem = oTotalMem - oFreeMem;
        long oSpareMem = rt.maxMemory() - oUsedMem;
        List<Long> oValues = Arrays.asList(oTotalMem, oFreeMem, oUsedMem, oSpareMem);
        MetricValues oMetricValues = memoryMetricValues(pCustomSet, oValues);
        addMetrics(pTargetList, oMetricValues, StandardUnit.Bytes);
    }

    private void addFileDescriptorMetrics(List<MetricDatum> pTargetList, Set<MachineMetric> pCustomSet) {
        JmxInfoProvider oProvider = JmxInfoProvider.Factory.getJmxInfoProvider();
        long[] oFdInfo = oProvider.getFileDecriptorInfo();

        if (oFdInfo != null) {
            long oOpenFdCount = oFdInfo[0];
            long oMaxFdCount = oFdInfo[1];
            List<Long> oValues = Arrays.asList(oOpenFdCount, oMaxFdCount - oOpenFdCount);
            MetricValues oMetricValues = fdMetricValues(pCustomSet, oValues);
            addMetrics(pTargetList, oMetricValues, StandardUnit.Count);
        }
    }

    private void addThreadMetrics(List<MetricDatum> pTargetList, Set<MachineMetric> pCustomSet) {
        long oThreadCount = mJmxInfoProvider.getThreadCount();
        long[] oIds = mJmxInfoProvider.findDeadlockedThreads();
        long oDeadLockThreadCount = oIds == null ? 0 : oIds.length;
        long oDaemonThreadCount = mJmxInfoProvider.getDaemonThreadCount();
        long oPeakThreadCount = mJmxInfoProvider.getPeakThreadCount();
        long oTotalStartedThreadCount = mJmxInfoProvider.getTotalStartedThreadCount();
        List<Long> oValues = Arrays.asList(oThreadCount, oDeadLockThreadCount, oDaemonThreadCount, oPeakThreadCount,
                oTotalStartedThreadCount);
        MetricValues oMetricValues = threadMetricValues(pCustomSet, oValues);
        addMetrics(pTargetList, oMetricValues, StandardUnit.Count);
    }

    /**
     * Returns the set of memory metrics and the corresponding values based on
     * the default and the customized set of metrics, if any.
     * 
     * @param pCustomSet
     *            a non-null customized set of metrics
     * @param pValues
     *            a non-null list of values corresponding to the list of default
     *            memory metrics
     */
    private MetricValues memoryMetricValues(Set<MachineMetric> pCustomSet, List<Long> pValues) {
        return metricValues(pCustomSet, MachineMetricFactory.MEMORY_METRICS, pValues);
    }

    /**
     * Returns the set of file-descriptor metrics and the corresponding values based on
     * the default and the customized set of metrics, if any.
     * 
     * @param pCustomSet
     *            a non-null customized set of metrics
     * @param pValues
     *            a non-null list of values corresponding to the list of default
     *            file-descriptor metrics
     */
    private MetricValues fdMetricValues(Set<MachineMetric> pCustomSet, List<Long> pValues) {
        return metricValues(pCustomSet, MachineMetricFactory.FD_METRICS, pValues);
    }

    /**
     * Returns the set of thread metrics and the corresponding values based on
     * the default and the customized set of metrics, if any.
     * 
     * @param pCustomSet
     *            a non-null customized set of metrics
     * @param pValues
     *            a non-null list of values corresponding to the list of default
     *            thread metrics
     */
    private MetricValues threadMetricValues(Set<MachineMetric> pCustomSet, List<Long> pValues) {
        return metricValues(pCustomSet, MachineMetricFactory.THREAD_METRICS, pValues);
    }

    // Used to get around the limitation of Java returning at most a single value
    private static class MetricValues {
        private final List<MachineMetric> mMetrics;
        private final List<Long> mValues;

        MetricValues(List<MachineMetric> pMetrics, List<Long> pValues) {
            this.mMetrics = pMetrics;
            this.mValues = pValues;
        }

        List<MachineMetric> getMetrics() {
            return mMetrics;
        }

        List<Long> getValues() {
            return mValues;
        }
    }
}