com.ottogroup.bi.spqr.metrics.MetricsReporterFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.ottogroup.bi.spqr.metrics.MetricsReporterFactory.java

Source

/**
 * Copyright 2015 Otto (GmbH & Co KG)
 *
 * Licensed 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.ottogroup.bi.spqr.metrics;

import java.io.File;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;

import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.CsvReporter;
import com.codahale.metrics.MetricFilter;
import com.codahale.metrics.Reporter;
import com.codahale.metrics.graphite.Graphite;
import com.codahale.metrics.graphite.GraphiteReporter;
import com.ottogroup.bi.spqr.exception.RequiredInputMissingException;
import com.ottogroup.bi.spqr.metrics.kafka.KafkaReporter;
import com.ottogroup.bi.spqr.pipeline.metrics.MetricReporterType;
import com.ottogroup.bi.spqr.pipeline.metrics.MicroPipelineMetricsReporterConfiguration;

/**
 * Generates {@link Reporter} instances from provided settings and attaches them to a {@link MetricsHandler}
 * @author mnxfst
 * @since May 27, 2015
 */
public class MetricsReporterFactory {

    /**
     * Attaches a {@link GraphiteReporter} to provided {@link MetricsHandler}
     * @param metricsHandler
     * @param id
     * @param period
     * @param host
     * @param port
     * @throws RequiredInputMissingException
     */
    private static void attachGraphiteReporter(final MetricsHandler metricsHandler, final String id,
            final int period, final String host, final int port) throws RequiredInputMissingException {

        //////////////////////////////////////////////////////////////////////////
        // validate input
        if (StringUtils.isBlank(id))
            throw new RequiredInputMissingException("Missing required metric reporter id");
        if (metricsHandler == null)
            throw new RequiredInputMissingException("Missing required metrics handler");
        if (StringUtils.isBlank(host))
            throw new RequiredInputMissingException("Missing required graphite host");
        if (port < 0)
            throw new RequiredInputMissingException("Missing required graphite port");
        //////////////////////////////////////////////////////////////////////////

        final Graphite graphite = new Graphite(new InetSocketAddress(host, port));
        final GraphiteReporter reporter = GraphiteReporter.forRegistry(metricsHandler.getRegistry())
                .convertRatesTo(TimeUnit.SECONDS).convertDurationsTo(TimeUnit.MILLISECONDS).filter(MetricFilter.ALL)
                .build(graphite);
        reporter.start((period > 0 ? period : 1), TimeUnit.SECONDS);
        metricsHandler.addScheduledReporter(id, reporter);
    }

    /**
     * Attaches a {@link CsvReporter} to provided {@link MetricsHandler}
     * @param metricsHandler
     * @param id
     * @param period
     * @param outputFile
     * @throws RequiredInputMissingException
     */
    private static void attachCSVReporter(final MetricsHandler metricsHandler, final String id, final int period,
            final String outputFile) throws RequiredInputMissingException {

        //////////////////////////////////////////////////////////////////////////
        // validate input
        if (StringUtils.isBlank(id))
            throw new RequiredInputMissingException("Missing required metric reporter id");
        if (metricsHandler == null)
            throw new RequiredInputMissingException("Missing required metrics handler");
        if (StringUtils.isBlank(outputFile))
            throw new RequiredInputMissingException("Missing required output file for CSV metrics writer");
        File oFile = new File(outputFile);
        if (oFile.isDirectory())
            throw new RequiredInputMissingException("Output file points to directory");
        //////////////////////////////////////////////////////////////////////////

        final CsvReporter reporter = CsvReporter.forRegistry(metricsHandler.getRegistry()).formatFor(Locale.US)
                .convertRatesTo(TimeUnit.SECONDS).convertDurationsTo(TimeUnit.MILLISECONDS).build(oFile);
        reporter.start((period > 0 ? period : 1), TimeUnit.SECONDS);
        metricsHandler.addScheduledReporter(id, reporter);
    }

    /**
     * Attaches a {@link ConsoleReporter} to provided {@link MetricsHandler}
     * @param metricsHandler
     * @param id
     * @param period
     * @throws RequiredInputMissingException
     */
    private static void attachConsoleReporter(final MetricsHandler metricsHandler, final String id,
            final int period) throws RequiredInputMissingException {
        //////////////////////////////////////////////////////////////////////////
        // validate input
        if (StringUtils.isBlank(id))
            throw new RequiredInputMissingException("Missing required metric reporter id");
        if (metricsHandler == null)
            throw new RequiredInputMissingException("Missing required metrics handler");
        //////////////////////////////////////////////////////////////////////////

        final ConsoleReporter reporter = ConsoleReporter.forRegistry(metricsHandler.getRegistry())
                .convertDurationsTo(TimeUnit.SECONDS).convertRatesTo(TimeUnit.MILLISECONDS).formattedFor(Locale.US)
                .build();
        reporter.start((period > 0 ? period : 1), TimeUnit.SECONDS);
        metricsHandler.addScheduledReporter(id, reporter);
    }

    /**
     * Attaches a {@link KafkaReporter} to provided {@link MetricsHandler}
     * @param metricsHandler
     * @param id
     * @param period
     * @param zookeeperConnect
     * @param brokerList
     * @param clientId
     * @param topicId
     * @throws RequiredInputMissingException
     */
    private static void attachKafkaReporter(final MetricsHandler metricsHandler, final String id, final int period,
            final String zookeeperConnect, final String brokerList, final String clientId, final String topicId)
            throws RequiredInputMissingException {

        //////////////////////////////////////////////////////////////////////////
        // validate input
        if (StringUtils.isBlank(id))
            throw new RequiredInputMissingException("Missing required metric reporter id");
        if (metricsHandler == null)
            throw new RequiredInputMissingException("Missing required metrics handler");
        if (StringUtils.isBlank(zookeeperConnect))
            throw new RequiredInputMissingException("Missing required zookeeper connect");
        if (StringUtils.isBlank(brokerList))
            throw new RequiredInputMissingException("Missing required broker list");
        if (StringUtils.isBlank(clientId))
            throw new RequiredInputMissingException("Missing required client identifier");
        if (StringUtils.isBlank(topicId))
            throw new RequiredInputMissingException("Missing required topic identifier");
        //////////////////////////////////////////////////////////////////////////

        final KafkaReporter reporter = KafkaReporter.forRegistry(metricsHandler.getRegistry())
                .brokerList("localhost:9092").clientId(clientId).convertRatesTo(TimeUnit.SECONDS)
                .convertDurationsTo(TimeUnit.MICROSECONDS).topic(topicId).zookeeperConnect(zookeeperConnect)
                .build();
        reporter.start((period > 0 ? period : 1), TimeUnit.SECONDS);
        metricsHandler.addScheduledReporter(id, reporter);
    }

    /**
     * Attaches a new reporter of specified {@link MetricReporterType type} to contained {@link MetricsHandler#getRegistry() registry}
     * @param metricsHandler
     * @param reporterConfig
     * @throws RequiredInputMissingException
     */
    public static void attachReporters(final MetricsHandler metricsHandler,
            final List<MicroPipelineMetricsReporterConfiguration> reporterConfig)
            throws RequiredInputMissingException {

        if (reporterConfig == null || reporterConfig.isEmpty())
            return;

        ///////////////////////////////////////////////////////////////////
        // validate input
        if (metricsHandler == null)
            throw new RequiredInputMissingException("Missing required metrics handler");
        ///////////////////////////////////////////////////////////////////

        for (final MicroPipelineMetricsReporterConfiguration rc : reporterConfig) {

            if (rc.getType() == null)
                throw new RequiredInputMissingException(
                        "Missing required type for metrics reporter configuration [id=" + rc.getId() + "]");

            switch (rc.getType()) {
            case CONSOLE: {
                MetricsReporterFactory.attachConsoleReporter(metricsHandler, rc.getId(), rc.getPeriod());
                break;
            }
            case CSV: {

                if (rc.getSettings() == null || rc.getSettings().isEmpty())
                    throw new RequiredInputMissingException(
                            "Missing required settings for metrics reporter configuration [id=" + rc.getId() + "]");

                MetricsReporterFactory.attachCSVReporter(metricsHandler, rc.getId(), rc.getPeriod(),
                        rc.getSettings().get(MicroPipelineMetricsReporterConfiguration.SETTING_CSV_OUTPUT_FILE));
                break;
            }
            case GRAPHITE: {

                if (rc.getSettings() == null || rc.getSettings().isEmpty())
                    throw new RequiredInputMissingException(
                            "Missing required settings for metrics reporter configuration [id=" + rc.getId() + "]");

                String p = rc.getSettings().get(MicroPipelineMetricsReporterConfiguration.SETTING_GRAPHITE_PORT);
                int port = -1;
                try {
                    port = Integer.parseInt(StringUtils.trim(p));
                } catch (Exception e) {
                    throw new RequiredInputMissingException("Invalid input found for graphite port [id="
                            + rc.getId() + "]. Error: " + e.getMessage());
                }

                MetricsReporterFactory.attachGraphiteReporter(metricsHandler, rc.getId(), rc.getPeriod(),
                        rc.getSettings().get(MicroPipelineMetricsReporterConfiguration.SETTING_GRAPHITE_HOST),
                        port);

                break;
            }
            case KAFKA: {

                MetricsReporterFactory.attachKafkaReporter(metricsHandler, rc.getId(), rc.getPeriod(),
                        rc.getSettings()
                                .get(MicroPipelineMetricsReporterConfiguration.SETTING_KAFKA_ZOOKEEPER_CONNECT),
                        rc.getSettings().get(MicroPipelineMetricsReporterConfiguration.SETTING_KAFKA_BROKER_LIST),
                        rc.getSettings().get(MicroPipelineMetricsReporterConfiguration.SETTING_KAFKA_CLIENT_ID),
                        rc.getSettings().get(MicroPipelineMetricsReporterConfiguration.SETTING_KAFKA_TOPIC_ID));
                break;
            }
            default: {
                throw new RequiredInputMissingException("Unknown metrics reporter type: " + rc.getType());
            }
            }
        }
    }
}