com.cloudera.csd.tools.codahale.CodahaleMetricAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.cloudera.csd.tools.codahale.CodahaleMetricAdapter.java

Source

// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, 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 com.cloudera.csd.tools.codahale;

import com.cloudera.csd.descriptors.MetricDescriptor;
import com.cloudera.csd.tools.JsonUtil;
import com.cloudera.csd.tools.JsonUtil.JsonRuntimeException;
import com.cloudera.csd.tools.MetricDescriptorImpl;
import com.cloudera.csd.tools.MetricDescriptorImpl.Builder;
import com.cloudera.csd.tools.MetricFixtureAdapter;
import com.cloudera.csd.tools.codahale.CodahaleMetricDefinitionFixture.CodahaleMetric;
import com.cloudera.csd.tools.codahale.CodahaleMetricTypes.HistogramMetricType;
import com.cloudera.csd.tools.codahale.CodahaleMetricTypes.MeterMetricType;
import com.cloudera.csd.tools.codahale.CodahaleMetricTypes.TimerMetricType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.io.File;
import java.io.FileInputStream;
import java.util.Collection;
import java.util.List;

import javax.annotation.Nullable;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A codahale (aka yammer) metric fixture adapter. It takes as input a list of
 * codahale metrics and convert them to one or more Cloudera Manager metrics.
 * The fixture file should be a json formatted file (see Fixture class below).
 */
public class CodahaleMetricAdapter implements MetricFixtureAdapter {

    private static final Logger LOG = LoggerFactory.getLogger(CodahaleMetricAdapter.class);

    private CodahaleMetricDefinitionFixture fixture;
    private CodahaleMetricConventions conventions;

    @Override
    public void init(String fixtureFile, @Nullable String conventionsFile) throws Exception {
        Preconditions.checkNotNull(fixtureFile);

        FileInputStream in = null;
        try {
            in = FileUtils.openInputStream(new File(fixtureFile));
            fixture = JsonUtil.valueFromStream(CodahaleMetricDefinitionFixture.class, in);
        } catch (JsonRuntimeException ex) {
            LOG.error("Could not parse file at: " + fixtureFile, ex);
            throw ex;
        } finally {
            IOUtils.closeQuietly(in);
            in = null;
        }

        if (conventionsFile == null) {
            conventions = createDefaultConventions();
        } else {
            try {
                in = FileUtils.openInputStream(new File(conventionsFile));
                conventions = JsonUtil.valueFromStream(CodahaleMetricConventions.class, in);
            } catch (JsonRuntimeException ex) {
                LOG.error("Could not parse file at: " + conventionsFile, ex);
                throw ex;
            } finally {
                IOUtils.closeQuietly(in);
            }
        }
    }

    public String getServiceName() {
        Preconditions.checkNotNull(fixture);
        return fixture.getServiceName();
    }

    @Override
    public List<MetricDescriptor> getServiceMetrics() {
        Preconditions.checkState(null != fixture);
        List<MetricDescriptor> ret = Lists.newArrayList();
        for (CodahaleMetric metric : fixture.getServiceMetrics()) {
            ret.addAll(generateMetricDescriptorsForMetric(metric));
        }
        return ret;
    }

    private Collection<? extends MetricDescriptor> generateMetricDescriptorsForMetric(CodahaleMetric metric) {
        Preconditions.checkNotNull(metric);
        switch (metric.getType()) {
        case GAUGE:
            Preconditions.checkArgument(null == metric.getDenominatorForRateMetrics(),
                    "The denominator for rate metrics is only used for timers.");
            return ImmutableList.of(new MetricDescriptorImpl.Builder()
                    .setName(fixture.getServiceName(), metric.getName()).setLabel(metric.getLabel())
                    .setDescription(metric.getDescription()).setNumeratorUnit(metric.getNumeratorUnit())
                    .setDenominatorUnit(metric.getDenominatorUnit()).setIsCounter(false)
                    .setContext(conventions.makeGaugeContext(metric.getContext())).build());
        case COUNTER:
            Preconditions.checkArgument(null == metric.getDenominatorForRateMetrics(),
                    "The denominator for rate metrics is only used for timers.");
            Preconditions.checkArgument(null == metric.getDenominatorUnit(),
                    "Counters should not have denominators.");
            return ImmutableList.of(new MetricDescriptorImpl.Builder()
                    .setName(fixture.getServiceName(), metric.getName()).setLabel(metric.getLabel())
                    .setDescription(metric.getDescription()).setNumeratorUnit(metric.getNumeratorUnit())
                    .setIsCounter(true).setContext(conventions.makeCounterContext(metric.getContext())).build());
        case HISTOGRAM: {
            Preconditions.checkArgument(null == metric.getDenominatorForRateMetrics(),
                    "The denominator for rate metrics is only used for timers.");
            ImmutableList.Builder<MetricDescriptorImpl> b = ImmutableList.builder();
            for (HistogramMetricType type : HistogramMetricType.values()) {
                String metricName = type.makeMetricName(metric.getName());
                MetricDescriptorImpl.Builder metricBuilder = new MetricDescriptorImpl.Builder()
                        .setName(fixture.getServiceName(), metricName)
                        .setLabel(type.makeMetricLabel(metric.getLabel()))
                        .setDescription(type.makeMetricDescription(metric.getDescription()))
                        .setIsCounter(type.isCounter());
                determineUnitForHistogramType(type.isCounter(), metric, metricBuilder);
                metricBuilder.setContext(conventions.makeHistogramContext(metric.getContext(), type));
                b.add(metricBuilder.build());
            }
            return b.build();
        }
        case TIMER: {
            ImmutableList.Builder<MetricDescriptorImpl> b = ImmutableList.builder();
            for (TimerMetricType type : TimerMetricType.values()) {
                String metricName = type.makeMetricName(metric.getName());
                MetricDescriptorImpl.Builder metricBuilder = new MetricDescriptorImpl.Builder()
                        .setName(fixture.getServiceName(), metricName)
                        .setLabel(type.makeMetricLabel(metric.getLabel()))
                        .setDescription(type.makeMetricDescription(metric.getDescription()))
                        .setIsCounter(type.isCounter());
                determineUnitForTimerType(type, metric, metricBuilder);
                metricBuilder.setContext(conventions.makeTimerContext(metric.getContext(), type));
                b.add(metricBuilder.build());
            }
            return b.build();
        }
        case METER: {
            Preconditions.checkArgument(null == metric.getDenominatorForRateMetrics(),
                    "The denominator for rate metrics is only used for timers.");
            ImmutableList.Builder<MetricDescriptorImpl> b = ImmutableList.builder();
            for (MeterMetricType type : MeterMetricType.values()) {
                String metricName = type.makeMetricName(metric.getName());
                MetricDescriptorImpl.Builder metricBuilder = new MetricDescriptorImpl.Builder()
                        .setName(fixture.getServiceName(), metricName)
                        .setLabel(type.makeMetricLabel(metric.getLabel()))
                        .setDescription(type.makeMetricDescription(metric.getDescription()))
                        .setIsCounter(type.isCounter());
                determineUnitForMeterType(type, metric, metricBuilder);
                metricBuilder.setContext(conventions.makeMeterContext(metric.getContext(), type));
                b.add(metricBuilder.build());
            }
            return b.build();
        }
        default:
            throw new UnsupportedOperationException("Unknown codahale type: " + metric.getMetricType());
        }
    }

    private void determineUnitForMeterType(MeterMetricType type, CodahaleMetric metric, Builder metricBuilder) {
        Preconditions.checkNotNull(metric);
        Preconditions.checkNotNull(type);
        Preconditions.checkNotNull(metricBuilder);

        metricBuilder.setNumeratorUnit(metric.getNumeratorUnit());
        if (type.isRate()) {
            Preconditions.checkNotNull(metric.getDenominatorUnit());
            metricBuilder.setDenominatorUnit(metric.getDenominatorUnit());
        }
    }

    private void determineUnitForTimerType(TimerMetricType type, CodahaleMetric metric, Builder metricBuilder) {
        Preconditions.checkNotNull(metric);
        Preconditions.checkNotNull(type);
        Preconditions.checkNotNull(metricBuilder);

        if (type.isCounter()) {
            Preconditions.checkNotNull(metric.getNumeratorForCounterMetric(),
                    "A numerator unit for the counter metric of the timer must be " + " provided");
            metricBuilder.setNumeratorUnit(metric.getNumeratorForCounterMetric());
        } else if (type.isRate()) {
            Preconditions.checkNotNull(metric.getNumeratorForCounterMetric(),
                    "A denominator unit for the rate metrics of the timer must be " + "provided");
            Preconditions.checkNotNull(metric.getDenominatorForRateMetrics());
            metricBuilder.setDenominatorUnit(metric.getDenominatorForRateMetrics())
                    .setNumeratorUnit(metric.getNumeratorForCounterMetric());
        } else {
            metricBuilder.setDenominatorUnit(metric.getDenominatorUnit())
                    .setNumeratorUnit(metric.getNumeratorUnit());
        }
    }

    private void determineUnitForHistogramType(boolean isCounter, CodahaleMetric metric, Builder metricBuilder) {
        Preconditions.checkNotNull(metric);
        if (isCounter) {
            Preconditions.checkNotNull(metric.getNumeratorForCounterMetric(),
                    "A numerator unit for the counter metric of the histogram must be " + "provided");
            metricBuilder.setNumeratorUnit(metric.getNumeratorForCounterMetric());
        } else {
            metricBuilder.setDenominatorUnit(metric.getDenominatorUnit())
                    .setNumeratorUnit(metric.getNumeratorUnit());
        }
    }

    public Collection<String> getRoleNames() {
        Preconditions.checkNotNull(fixture);
        return fixture.getRolesMetrics().keySet();
    }

    @Override
    public List<MetricDescriptor> getRoleMetrics(String roleName) {
        Preconditions.checkNotNull(fixture);

        if (null == fixture.getRolesMetrics().get(roleName)) {
            return null;
        }

        List<MetricDescriptor> ret = Lists.newArrayList();
        for (CodahaleMetric metric : fixture.getRolesMetrics().get(roleName)) {
            ret.addAll(generateMetricDescriptorsForMetric(metric));
        }
        return ret;
    }

    public Collection<String> getEntityNames() {
        Preconditions.checkNotNull(fixture);
        return fixture.getAdditionalServiceEntityTypesMetrics().keySet();
    }

    @Override
    public List<MetricDescriptor> getEntityMetrics(String entityName) {
        Preconditions.checkNotNull(fixture);

        if (null == fixture.getAdditionalServiceEntityTypesMetrics().get(entityName)) {
            // Not all entities need to have metrics.
            return null;
        }

        List<MetricDescriptor> ret = Lists.newArrayList();
        for (CodahaleMetric metric : fixture.getAdditionalServiceEntityTypesMetrics().get(entityName)) {
            ret.addAll(generateMetricDescriptorsForMetric(metric));
        }
        return ret;
    }

    /**
     * The default metric conventions do nothing.
     * @return
     */
    private CodahaleMetricConventions createDefaultConventions() {
        CodahaleMetricConventions conventions = new CodahaleMetricConventions();
        conventions.meterContextSuffixes = Maps.newHashMap();
        conventions.timerContextSuffixes = Maps.newHashMap();
        conventions.histogramContextSuffixes = Maps.newHashMap();
        return conventions;
    }
}