1. 程式人生 > >Java 程式碼執行洞察庫 Metrics

Java 程式碼執行洞察庫 Metrics

Metrics是一個java庫,能夠為你提供無與倫比的程式碼執行洞察功能。
它是由yammer開發的,用於檢測jvm上後端服務的執行狀況。Metrics提供了一個強大的工具集,用於度量你的生產環境上關鍵元件的行為。

Metrics提供了一組通用的模組庫用於支援比如Guice,Jetty,Log4j,Apache HttpClient,EhCache,Logback,Spring等,也提供對比如Ganglia和Graphite等後端的報告。

專案官網:http://metrics.dropwizard.io/

Metrics 主要有五大基本元件

1:Counter

  記錄執行次數

2:Gauge

  獲取某個值

3:Meter

  用來計算事件的速率

4:Histogram

  可以為資料流提供統計資料。 除了最大值,最小值,平均值外,它還可以測量 中值(median),百分比比如XX%這樣的Quantile資料 

5:Timer

  用來測量一段程式碼被呼叫的速率和用時。等於Meter+Hitogram,既算TPS,也算執行時間。

下面是程式碼例子

首先加入依賴

<dependency>
	<groupId>io.dropwizard.metrics</groupId>
	<artifactId>metrics-core</artifactId>
	<version>3.1.2</version>
</dependency>

com.codahale.metrics.MetricRegistry  是Metrics的核心,這裡先用一個常量儲存
package com.lala.core;

import com.codahale.metrics.MetricRegistry;

public class MetricConstant 
{
	public static MetricRegistry REGISTER = new MetricRegistry();
}

上面也是說到了Metrics支援很多輸出,jmx, log4j , jetty, httpclient等等。我這裡就直接輸出到控制檯
package com.lala.core;

import java.util.concurrent.TimeUnit;
import com.codahale.metrics.ConsoleReporter;
/**
 * 控制檯列印輸出
 */
public class MyConsoleReport 
{
	public static void startReport()
	{
		final ConsoleReporter reporter = ConsoleReporter.forRegistry(MetricConstant.REGISTER)
                .convertRatesTo(TimeUnit.SECONDS)
                .convertDurationsTo(TimeUnit.SECONDS)
                .build();
		//一秒鐘執行一次
		reporter.start(1, TimeUnit.SECONDS);
	}
}

首先,來一個基本的公共類
package com.lala.core;

import java.util.concurrent.TimeUnit;
import com.codahale.metrics.MetricRegistry;

public class Base 
{
	protected static MetricRegistry metric = MetricConstant.REGISTER;
	protected static void secondSleep(long value)
	{
		try
		{
			TimeUnit.SECONDS.sleep(value);
		} catch (InterruptedException e)
		{
			e.printStackTrace();
		}
	}
	protected static void milliSecondSleep(long value)
	{
		try
		{
			TimeUnit.MILLISECONDS.sleep(value);
		} catch (InterruptedException e)
		{
			e.printStackTrace();
		}
	}
}

接下來,就演示這五大元件的基本用法

一:Counter

package com.lala.demo;

import java.util.Random;

import com.codahale.metrics.Counter;
import com.lala.core.Base;
import com.lala.core.MyConsoleReport;

/**
 * 記錄執行次數
 */
public class CounterTest extends Base
{
	final static Counter exec = metric.counter("com.pp.counter.invoke");
	public static void main(String[] args)
	{
		MyConsoleReport.startReport();
		new Thread(()->{
			for(int i=1;i<=3;i++)
			{
				exec.inc();
				milliSecondSleep(new Random().nextInt(500)*2);
			}
		}).start();
		secondSleep(3);
	}
}

輸出如下:

15-11-22 20:38:29 ==============================================================


-- Counters --------------------------------------------------------------------
com.pp.counter.invoke
             count = 3

二:Gauge

package com.lala.demo;

import com.codahale.metrics.Gauge;
import com.lala.core.Base;
import com.lala.core.MyConsoleReport;
/**
 * 獲取某個值
 */
public class GaugeTest extends Base
{
	public static void main(String[] args)
	{
		MyConsoleReport.startReport();
		metric.register("com.pp.gauge.freeMemory", new Gauge<Long>(){
			public Long getValue() {
				//這裡是獲取當前JVM可用記憶體
				return Runtime.getRuntime().freeMemory();
			}
		});
		secondSleep(2);
	}
}

輸出如下:

15-11-22 20:39:44 ==============================================================


-- Gauges ----------------------------------------------------------------------
com.pp.gauge.freeMemory
             value = 118203344

三:Meter

package com.lala.demo;

import java.util.Random;
import com.codahale.metrics.Meter;
import com.lala.core.Base;
import com.lala.core.MyConsoleReport;
/**
 * Meter用來計算事件的速率
 */
public class MeterTest extends Base
{
	static final Meter requests = metric.meter("com.pp.meter.invoke");
	public static void main(String[] args)
	{
		MyConsoleReport.startReport();
		new Thread(()->{
			for(int i=1;i<=2;i++)
			{
				requests.mark();
				milliSecondSleep(new Random().nextInt(500)*2);
			}
		}).start();
		secondSleep(2);
	}
}

輸出如下:

15-11-22 20:40:57 ==============================================================


-- Meters ----------------------------------------------------------------------
com.pp.meter.invoke
             count = 2
         mean rate = 0.97 events/second
     1-minute rate = 0.00 events/second
     5-minute rate = 0.00 events/second
    15-minute rate = 0.00 events/second

四:Histogram

package com.lala.demo;

import java.util.Arrays;
import java.util.List;
import java.util.Random;
import com.codahale.metrics.Histogram;
import com.lala.core.Base;
import com.lala.core.MyConsoleReport;
/**
 * Histogram可以為資料流提供統計資料。 除了最大值,最小值,平均值外,它還可以測量 中值(median),
 * 百分比比如XX%這樣的Quantile資料 
 */
public class HistogramTest extends Base
{
	static final Histogram his = metric.histogram("com.pp.histogram.score");
	static List<Integer> scores = Arrays.asList(60, 75, 80, 62, 90, 42, 33, 95, 61, 73);
	public static void main(String[] args) 
	{
		MyConsoleReport.startReport();
		new Thread(()->{
			scores.forEach( (score) -> {
				his.update(score);
				milliSecondSleep(new Random().nextInt(500)*2);
			});
		}).start();
		secondSleep(10);
	}
}

輸出如下:

15-11-22 20:42:14 ==============================================================


-- Histograms ------------------------------------------------------------------
com.pp.histogram.score
             count = 10
               min = 33
               max = 95
              mean = 67.11
            stddev = 18.70
            median = 73.00
              75% <= 80.00
              95% <= 95.00
              98% <= 95.00
              99% <= 95.00
            99.9% <= 95.00

五:Timer

package com.lala.demo;

import com.codahale.metrics.Timer;
import com.lala.core.Base;
import com.lala.core.MyConsoleReport;
/**
 * Timer用來測量一段程式碼被呼叫的速率和用時。
 * 等於Meter+Hitogram,既算TPS,也算執行時間。
 */
public class TimerTest extends Base 
{
	static final Timer timer = metric.timer("com.pp.timer.invoke");
	static void inovke(long time)
	{
		final Timer.Context context = timer.time();
		try
		{
			secondSleep(time);
		}finally
		{
			context.stop();
		}
	}
	public static void main(String[] args) 
	{
		MyConsoleReport.startReport();
		inovke(1);
		inovke(2);
		inovke(2);
		inovke(8);
		secondSleep(1);
	}
}
輸出如下:

15-11-22 20:43:34 ==============================================================


-- Timers ----------------------------------------------------------------------
com.pp.timer.invoke
             count = 4
         mean rate = 0.28 calls/second
     1-minute rate = 0.38 calls/second
     5-minute rate = 0.40 calls/second
    15-minute rate = 0.40 calls/second
               min = 1.01 seconds
               max = 8.00 seconds
              mean = 3.44 seconds
            stddev = 2.86 seconds
            median = 2.00 seconds
              75% <= 8.00 seconds
              95% <= 8.00 seconds
              98% <= 8.00 seconds
              99% <= 8.00 seconds
            99.9% <= 8.00 seconds

注意:這裡的輸出,和上一個元件輸出有些類似,但是不一樣的

這裡統計的是執行時間,什麼最大執行時間,最小執行時間,平均執行時間等。上一個統計的是數字,什麼最大數字,最小數字,平均數字等

當然了,Metrics還可以用來做心跳檢測,這裡就不演示了。