org.apache.tajo.util.metrics.reporter.TajoMetricsScheduledReporter.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.tajo.util.metrics.reporter.TajoMetricsScheduledReporter.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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 org.apache.tajo.util.metrics.reporter;

import com.codahale.metrics.MetricFilter;
import com.codahale.metrics.MetricRegistry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tajo.util.metrics.GroupNameMetricsFilter;
import org.apache.tajo.util.metrics.MetricsFilterList;
import org.apache.tajo.util.metrics.RegexpMetricsFilter;

import java.io.Closeable;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class TajoMetricsScheduledReporter extends TajoMetricsReporter implements Closeable {
    private static final Log LOG = LogFactory.getLog(TajoMetricsScheduledReporter.class);

    public static final String PERIOD_KEY = "period";

    protected MetricRegistry registry;
    protected ScheduledExecutorService executor;
    protected MetricFilter filter;
    protected double durationFactor;
    protected String durationUnit;
    protected double rateFactor;
    protected String rateUnit;
    protected Map<String, String> metricsProperties;
    protected String metricsName;
    protected String metricsPropertyKey;
    protected String hostAndPort;
    protected long period;

    protected abstract String getReporterName();

    protected abstract void afterInit();

    private static class NamedThreadFactory implements ThreadFactory {
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        private NamedThreadFactory(String name) {
            final SecurityManager s = System.getSecurityManager();
            this.group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            this.namePrefix = "metrics-" + name + "-thread-";
        }

        @Override
        public Thread newThread(Runnable r) {
            final Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
            t.setDaemon(true);
            if (t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }
            return t;
        }
    }

    public long getPeriod() {
        return period;
    }

    public void init(MetricRegistry registry, String metricsName, String hostAndPort,
            Map<String, String> metricsProperties) {
        this.registry = registry;
        this.metricsName = metricsName;
        this.executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory(metricsName));
        this.rateFactor = TimeUnit.SECONDS.toSeconds(1);
        this.rateUnit = calculateRateUnit(TimeUnit.MILLISECONDS);
        this.durationFactor = 1.0 / TimeUnit.MILLISECONDS.toNanos(1);
        this.durationUnit = TimeUnit.MILLISECONDS.toString().toLowerCase(Locale.US);
        this.metricsProperties = metricsProperties;
        this.metricsPropertyKey = metricsName + "." + getReporterName() + ".";
        this.hostAndPort = hostAndPort;

        MetricsFilterList filterList = new MetricsFilterList();
        filterList.addMetricFilter(new GroupNameMetricsFilter(metricsName));

        String regexpFilterKey = metricsPropertyKey + "regexp.";
        Set<String> regexpExpressions = new HashSet<>();

        for (Map.Entry<String, String> entry : metricsProperties.entrySet()) {
            String key = entry.getKey();
            if (key.indexOf(regexpFilterKey) == 0) {
                regexpExpressions.add(entry.getValue());
            }
        }

        if (!regexpExpressions.isEmpty()) {
            filterList.addMetricFilter(new RegexpMetricsFilter(regexpExpressions));
        }
        this.filter = filterList;

        this.period = 60;
        if (metricsProperties.get(metricsPropertyKey + PERIOD_KEY) != null) {
            this.period = Integer.parseInt(metricsProperties.get(metricsPropertyKey + PERIOD_KEY));
        }
        afterInit();
    }

    public void start() {
        start(period, TimeUnit.SECONDS);
    }

    /**
     * Starts the reporter polling at the given period.
     *
     * @param period the amount of time between polls
     * @param unit   the unit for {@code period}
     */
    public void start(long period, TimeUnit unit) {
        this.period = period;
        executor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    report();
                } catch (Exception e) {
                    LOG.warn("Metric report error:" + e.getMessage(), e);
                }
            }
        }, period, period, unit);
    }

    /**
     * Stops the reporter and shuts down its thread of execution.
     */
    public void stop() {
        executor.shutdown();
        try {
            executor.awaitTermination(1, TimeUnit.SECONDS);
        } catch (InterruptedException ignored) {
            // do nothing
        }
    }

    /**
     * Stops the reporter and shuts down its thread of execution.
     */
    @Override
    public void close() {
        stop();
    }

    /**
     * Report the current values of all metrics in the registry.
     */
    public void report() {
        report(registry.getGauges(filter), registry.getCounters(filter), registry.getHistograms(filter),
                registry.getMeters(filter), registry.getTimers(filter));
    }

    protected String getRateUnit() {
        return rateUnit;
    }

    protected String getDurationUnit() {
        return durationUnit;
    }

    protected double convertDuration(double duration) {
        return duration * durationFactor;
    }

    protected double convertRate(double rate) {
        return rate * rateFactor;
    }

    private String calculateRateUnit(TimeUnit unit) {
        final String s = unit.toString().toLowerCase(Locale.US);
        return s.substring(0, s.length() - 1);
    }
}