java-源码-工具包-Metrics

一. 成员

ScheduledReporter成员

    private final MetricRegistry registry;
    private final ScheduledExecutorService executor;
    private final MetricFilter filter;
    private final double durationFactor;
    private final String durationUnit;
    private final double rateFactor;
    private final String rateUnit;

ConsoleReporter成员

    private static final int CONSOLE_WIDTH = 80;
    private final PrintStream output;
    private final Locale locale;
    private final Clock clock;
    private final DateFormat dateFormat;		//java自带的类

二. MetricRegistry

创建MetricRegistry的实例,默认构造方法创建,内部含有metrics是一个ConcurrentHashMap

private final ConcurrentMap<String, Metric> metrics

其value是一个Metric,是一个空接口,这个空接口是什么作用呢,从类图可以看到继承关系

MetricRegistry---->MertricSet->Metric

MetricRegistry自身也是一个Mertric接口的实现,所有的数据类型都是Metric

内部包含一些getXX方法,比如:

   public SortedMap<String, Gauge> getGauges() {
        return getGauges(MetricFilter.ALL);
   }
   public SortedMap<String, Gauge> getGauges(MetricFilter filter) {
        return getMetrics(Gauge.class, filter);
   }
   ...

无参getGauges方法中,调用了MetricFilter接口如下,All是一个始终返回true的滤波器

public interface MetricFilter {
    MetricFilter ALL = new MetricFilter() {
        @Override
        public boolean matches(String name, Metric metric) {
            return true;
        }
    };

    boolean matches(String name, Metric metric);
}

调用有参方法

    public SortedMap<String, Gauge> getGauges(MetricFilter filter) {
        return getMetrics(Gauge.class, filter);
    }

getMertrics如下

    private <T extends Metric> SortedMap<String, T> getMetrics(Class<T> klass, MetricFilter filter) {
        final TreeMap<String, T> timers = new TreeMap<String, T>();
        for (Map.Entry<String, Metric> entry : metrics.entrySet()) {
            if (klass.isInstance(entry.getValue()) && filter.matches(entry.getKey(),
                                                                     entry.getValue())) {
                timers.put(entry.getKey(), (T) entry.getValue());
            }
        }
        return Collections.unmodifiableSortedMap(timers);
    }

返回一个不可变的TreeMap,这里显然是空的

三. ConsoleReporter

ConsoleReporter创建时调用构造器方法,把metrics传入,然后设置了一些默认参数

private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();

构造器默认参数

    this.registry = registry;
    this.output = System.out;		//输出流可以配置
    this.locale = Locale.getDefault();
    this.clock = Clock.defaultClock();
    this.timeZone = TimeZone.getDefault();
    this.rateUnit = TimeUnit.SECONDS;
    this.durationUnit = TimeUnit.MILLISECONDS;
    this.filter = MetricFilter.ALL;

构造器调用build创建ConsoleReporter

    private ConsoleReporter(MetricRegistry registry,
                            PrintStream output,
                            Locale locale,
                            Clock clock,
                            TimeZone timeZone,
                            TimeUnit rateUnit,
                            TimeUnit durationUnit,
                            MetricFilter filter) {
        super(registry, "console-reporter", filter, rateUnit, durationUnit);
        this.output = output;
        this.locale = locale;
        this.clock = clock;
        this.dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT,
                                                         DateFormat.MEDIUM,
                                                         locale);
        dateFormat.setTimeZone(timeZone);
    }

ScheduledReporter构造时调用的默认参数

    protected ScheduledReporter(MetricRegistry registry,
                                String name,
                                MetricFilter filter,
                                TimeUnit rateUnit,
                                TimeUnit durationUnit) {
        this.registry = registry;
        this.filter = filter;
        this.executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory(name));
        this.rateFactor = rateUnit.toSeconds(1);
        this.rateUnit = calculateRateUnit(rateUnit);
        this.durationFactor = 1.0 / durationUnit.toNanos(1);
        this.durationUnit = durationUnit.toString().toLowerCase(Locale.US);
    }

start方法

reporter.start(3, TimeUnit.SECONDS);

以固定频率即3s执行,report任务

    public void start(long period, TimeUnit unit) {
        executor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                report();
            }
        }, period, period, unit);
    }

空参report如下

    public void report() {
        report(registry.getGauges(filter),
               registry.getCounters(filter),
               registry.getHistograms(filter),
               registry.getMeters(filter),
               registry.getTimers(filter));
    }

这里调用的是带参report是抽象方法,实现在ConsoleReporter中

    public void report(SortedMap<String, Gauge> gauges,
                       SortedMap<String, Counter> counters,
                       SortedMap<String, Histogram> histograms,
                       SortedMap<String, Meter> meters,
                       SortedMap<String, Timer> timers) {
        final String dateTime = dateFormat.format(new Date(clock.getTime()));
        printWithBanner(dateTime, '=');
        output.println();

        if (!gauges.isEmpty()) {
            printWithBanner("-- Gauges", '-');
            for (Map.Entry<String, Gauge> entry : gauges.entrySet()) {
                output.println(entry.getKey());
                printGauge(entry);
            }
            output.println();
        }

        if (!counters.isEmpty()) {
            printWithBanner("-- Counters", '-');
            for (Map.Entry<String, Counter> entry : counters.entrySet()) {
                output.println(entry.getKey());
                printCounter(entry);
            }
            output.println();
        }

        if (!histograms.isEmpty()) {
            printWithBanner("-- Histograms", '-');
            for (Map.Entry<String, Histogram> entry : histograms.entrySet()) {
                output.println(entry.getKey());
                printHistogram(entry.getValue());
            }
            output.println();
        }

        if (!meters.isEmpty()) {
            printWithBanner("-- Meters", '-');
            for (Map.Entry<String, Meter> entry : meters.entrySet()) {
                output.println(entry.getKey());
                printMeter(entry.getValue());
            }
            output.println();
        }

        if (!timers.isEmpty()) {
            printWithBanner("-- Timers", '-');
            for (Map.Entry<String, Timer> entry : timers.entrySet()) {
                output.println(entry.getKey());
                printTimer(entry.getValue());
            }
            output.println();
        }

        output.println();
        output.flush();
    }

默认的report方法就是输出所有容器的内容

四. 构造类型

Gauge接口,有一个getValue方法

	public interface Gauge<T> extends Metric {
	    T getValue();
	}

我们的调用实现这个方法

   Gauge<Integer> gauge = new Gauge<Integer>() {
        @Override
        public Integer getValue() {
            return queue.size();
        }
   };

调用register注册进MetricRegistry容器中

metrics.register(MetricRegistry.name(MetricsTest.class, "pending-job", "size"), gauge);

名字以.分隔的形式,这里是MetricsTest.pending-job.size
该方法源码如下

    public <T extends Metric> T register(String name, T metric) throws IllegalArgumentException {
        if (metric instanceof MetricSet) {
            registerAll(name, (MetricSet) metric);
        } else {
            final Metric existing = metrics.putIfAbsent(name, metric);
            if (existing == null) {
                onMetricAdded(name, metric);
            } else {
                throw new IllegalArgumentException("A metric named " + name + " already exists");
            }
        }
        return metric;
    }

把key value加入到metrics中,然后退出

posted @ 2016-09-19 16:33  zhangshihai1232  阅读(354)  评论(0)    收藏  举报