Yammer Metrics的使用

 

 

Yammer Metrics简介

最近用到的某个框架,其官网提到利用Yammer Metrics来测量系统运行状态,需要对其统计的具体参数有个基本的了解,OK,那就需要弄清几个简单的问题:

  • Yammer Metrics是什么?
  • Yammer Metrics收集哪些数据?
  • Yammer Metrics收集数据的基本过程、原理?

Yammer Metrics的官网

上述列了几个问题,但有个最基本的问题:官网地址在哪?为什么说这个最基础、最重要,因为这是信息源,其他所有的网络信息都是以此为基础的。 在google中输入yammer metrics wiki没有搜到类似一个明显的官网,到时找到了github上的两个工程:

一时间有点蒙,赶紧去查看了一下当前Eclipse下使用的metrics-core-2.2.0.jar包,主要是其jar内的META-INF信息,查询得知jar包为coda在2012年编译的,再到google上一查,大部分人都在使用metrics 2.2.0版本,再理一下上面两个github工程的关系,初步肯定:codahale/metrics是较早之前的版本,而且现在已经变为metrics的go语言实现版本,同时codahale/metrics也指出java实现的metrics已经移到dropwizard/metrics。当前算是找到yammer metrics的官方地址了,赶快打开看一下,发现其已经是3.1.0版本了,心里有个小疑问,会不会有很多东西与2.2.0版本不同?不用担心,Metrics doc 3.x的URL上,修改一下版本的位置,即可看到2.2.0版本的官方文档Metrics doc 2.x

 

Yammer metrics的作用

为什么要用Metrics?Metrics doc 3.x中有句话很经典:

Metrics is a Java library which gives you unparalleled insight into what your code does in production.(注:unparalleled,空前的、无与伦比的)

Yammer Metrics相关术语

特别说明:从Yammer metrics官网可知,当前为3.1.0版本,但是当前在项目中广泛使用的是2.2.0版本,因此,本文将主要关注http://dropwizard.github.io/metrics/2.2.0/

 

intro to yammer metrics中有个基本的总结:

  • Gauges: an instantaneous measurement of a discrete value.
  • Counters: a value that can be incremented and decremented. Can be used in queues to monitorize the remaining number of pending jobs.
  • Meters: measure the rate of events over time. You can specify the rate unit, the scope of events or event type.
  • Histograms: measure the statistical distribution of values in a stream of data.
  • Timers: measure the amount of time it takes to execute a piece of code and the distribution of its duration.
  • Healthy checks: as his name suggests, it centralize our service’s healthy checks of external systems.

Gauges

Gauge是一个瞬时的测量值,例如,我们想要测量在队列中准备运行的Job数量

Metrics.newGauge(QueueManager.class, "pending-jobs", new Gauge<Integer>() {
	@Override
	public Integer value() {
		return queue.size();
	}
});

 Gauges每次被测量时候,都将返回队列中job的数量

For most queue and queue-like structures, you won’t want to simply return queue.size(). Most of java.util and java.util.concurrent have implementations of #size() which are O(n), which means your gauge will be slow (potentially while holding a lock).

Counters

counter仅是 AtomicLong 实例的一个计量器。我们可以增加或降低这个值,例如,我们可能想要有更有效的方式测量队列中的Job

private final Counter pendingJobs = Metrics.newCounter(QueueManager.class, "pending-jobs");
public void addJob(Job job) {
	pendingJobs.inc();
	queue.offer(job);
}
public Job takeJob() {
	pendingJobs.dec();
	return queue.take();
}

counters每次被测量时候,都将返回队列中job的数量

 

Meters

Meter测量随事件时间推移的速率

A meter measures the rate of events over time (e.g., “requests per second”). In addition to the mean rate, meters also track 1-5-, and 15-minute moving averages.

private final Meter requests = Metrics.newMeter(RequestHandler.class, "requests", "requests", TimeUnit.SECONDS);
public void handleRequest(Request request, Response response) {
	requests.mark();
	// etc
}

meter将度量每秒请求中请求的速率

Histograms

A histogram measures the statistical distribution of values in a stream of data. In addition to minimum, maximum, mean, etc., it also measures median, 75th, 90th, 95th, 98th, 99th, and 99.9th percentiles.

private final Histogram responseSizes = Metrics.newHistogram(RequestHandler.class, "response-sizes");
public void handleRequest(Request request, Response response) {
	// etc
	responseSizes.update(response.getContent().length);
}

This histogram will measure the size of responses in bytes.

Timers

A timer measures both the rate that a particular piece of code is called and the distribution of its duration.

private final Timer responses = Metrics.newTimer(RequestHandler.class, "responses", TimeUnit.MILLISECONDS, TimeUnit.SECONDS);
public String handleRequest(Request request, Response response) {
	final TimerContext context = responses.time();
	try {
		// etc;
		return "OK";
	} finally {
		context.stop();
	}
}

This timer will measure the amount of time it takes to process each request in milliseconds and provide a rate of requests in requests per second.

Health Checks

Metrics also has the ability to centralize your service’s health checks. First, implement a HealthCheck instance:

import com.yammer.metrics.core.HealthCheck.Result;
public class DatabaseHealthCheck extends HealthCheck {
	private final Database database;
	public DatabaseHealthCheck(Database database) {
		super("database");
		this.database = database;
	}
	@Override
	public Result check() throws Exception {
		if (database.isConnected()) {
			return Result.healthy();
		} else {
			return Result.unhealthy("Cannot connect to " + database.getUrl());
		}
	}
}

Then register an instance of it with Metrics:

HealthChecks.register(new DatabaseHealthCheck(database));

To run all of the registered health checks:

final Map<String, Result> results = HealthChecks.runHealthChecks();
for (Entry<String, Result> entry : results.entrySet()) {
	if (entry.getValue().isHealthy()) {
		System.out.println(entry.getKey() + " is healthy");
	} else {
		System.err.println(entry.getKey() + " is UNHEALTHY: " + entry.getValue().getMessage());
		final Throwable e = entry.getValue().getError();
		if (e != null) {
			e.printStackTrace();
		}
	}
}

Metrics comes with a pre-built health check: DeadlockHealthCheck, which uses Java 1.6’s built-in thread deadlock detection to determine if any threads are deadlocked.

Yammer metrics原理与具体用法

进一步的内容将参考:

下面将针对java中Yammer Metrics的用法进行简要介绍,此次我使用的是Maven来管理的java工程,具体pom.xml中的配置:

<dependency>
  		<groupId>com.yammer.metrics</groupId>
  		<artifactId>metrics-core</artifactId>
  		<version>2.2.0</version>
  	</dependency>

工程包截图

 

package com.bigdata.kafka.sourceparse.metrix.yammer.gauge;

import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Gauge;
import com.yammer.metrics.reporting.ConsoleReporter;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by yuanhailong on 2018/12/19.
 */
public class LearnGauge {
    private List<String> stringList = new LinkedList<>();

    Gauge<Integer> gauge = Metrics.newGauge(LearnGauge.class, "list-size-gauge", new Gauge<Integer>() {
        @Override
        public Integer value() {
            return stringList.size();
        }
    });

    public void inputElement(String input){
        stringList.add(input);
    }

    public static void main(String[] args) throws Exception {
        //周期性报告注册的所有指标到控制台上 这里设定为1秒钟
        ConsoleReporter.enable(1, TimeUnit.SECONDS);
        LearnGauge learnGauge=new LearnGauge();

        for(int i=0;i<100000;i++){
            learnGauge.inputElement(String.valueOf(i));
            Thread.sleep(500);
        }

    }


}

运行结果

counter

package com.bigdata.kafka.sourceparse.metrix.yammer.counter;

import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Counter;
import com.yammer.metrics.reporting.ConsoleReporter;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by yuanhailong on 2018/12/19.
 */
public class LearnCounter {
    private List<String> stringList = new LinkedList<String>();
    private Counter listSizeCounter = Metrics.newCounter(LearnCounter.class, "string-list-counter");

    private void push(String input){
        listSizeCounter.inc();
        stringList.add(input);
    }

    private void pop(String input){
        listSizeCounter.dec();
        stringList.remove(input);
    }

    public static void main(String[] args) throws InterruptedException{
        ConsoleReporter.enable(1, TimeUnit.SECONDS);
        LearnCounter learnCounter = new LearnCounter();

        for(int times = 0; times < 5; times++){
            learnCounter.push(String.valueOf(times));
            Thread.sleep(1000);
        }
        for(int times = 0; times < 5; times++){
            learnCounter.pop(String.valueOf(times));
            Thread.sleep(1000);
        }
    }
}

运行结果

meter

package com.bigdata.kafka.sourceparse.metrix.yammer.meter;

import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Meter;
import com.yammer.metrics.reporting.ConsoleReporter;

import java.util.concurrent.TimeUnit;

/**
 * Created by yuanhailong on 2018/12/19.
 */
public class LearnMeter {

    private Meter meter= Metrics.newMeter(LearnMeter.class,"meter-event","request", TimeUnit.SECONDS);

    public void handleRequest(){
        meter.mark();
    }


    public static void main(String[] args) throws Exception{
        ConsoleReporter.enable(1,TimeUnit.SECONDS);
        LearnMeter learnMeter=new LearnMeter();

        for(int times = 0; times < 200; times++){
            learnMeter.handleRequest();
            Thread.sleep(100);
        }
    }
}

运行结果

histogram

package com.bigdata.kafka.sourceparse.metrix.yammer.histogram;

import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Histogram;
import com.yammer.metrics.reporting.ConsoleReporter;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by yuanhailong on 2018/12/19.
 */
public class LearnHistogram {
    private List<String> stringList = new LinkedList<String>();
    private Histogram histogram = Metrics.newHistogram(LearnHistogram.class, "size-histogram");
    public void push(String input){
        stringList.add(input);
    }
    public void pop(String output){
        stringList.remove(output);
    }
    public void updateHisto(){
        histogram.update(stringList.size());
    }
    public static void main(String[] args) throws InterruptedException{
        ConsoleReporter.enable(1, TimeUnit.SECONDS);
        LearnHistogram learnHistogram = new LearnHistogram();
        for(int time = 0 ; time < 100000 ; time++){
            learnHistogram.push(String.valueOf(time));
            if(time%10 == 0){
                learnHistogram.updateHisto();
            }
            if(time%2 == 2){
                learnHistogram.pop(String.valueOf(time));
            }
            Thread.sleep(1);
        }
    }
}

运行结果

timer

package com.bigdata.kafka.sourceparse.metrix.yammer.timer;

import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Timer;
import com.yammer.metrics.core.TimerContext;
import com.yammer.metrics.reporting.ConsoleReporter;

import java.util.concurrent.TimeUnit;

/**
 * Created by yuanhailong on 2018/12/19.
 */
public class LearnTimer {
    private Timer timer = Metrics.newTimer(LearnTimer.class, "response-timer", TimeUnit.MILLISECONDS, TimeUnit.SECONDS);
    public void handleRequest() throws InterruptedException{
        TimerContext context = timer.time();
        for(int i = 0 ; i < 2 ; i++){
            Thread.sleep(1);
        }
        context.stop();
    }
    public static void main(String[] args) throws InterruptedException{
        ConsoleReporter.enable(1, TimeUnit.SECONDS);
        LearnTimer learnTimer = new LearnTimer();
        for(int time = 0 ; time < 10000 ; time++){
            learnTimer.handleRequest();
        }
        Thread.sleep(10000);
    }
}

运行结果

 

参考资料

https://metrics.dropwizard.io/3.1.0/getting-started/
http://ju.outofmemory.cn/entry/105544
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值