詳解Metrics應(yīng)用監(jiān)控指標(biāo)的使用說明
題前:做過虛擬化級別、系統(tǒng)級別、容器級別監(jiān)控;應(yīng)用級別監(jiān)控有哪些方法可以做?
Metrics是個(gè)很好的選擇。java、python、go均可支持。
Metrics可以為你的代碼的運(yùn)行提供無與倫比的洞察力。作為一款監(jiān)控指標(biāo)的度量類庫,它提供了很多模塊可以為第三方庫或者應(yīng)用提供輔助統(tǒng)計(jì)信息, 比如Jetty, Logback, Log4j, Apache HttpClient, Ehcache, JDBI, Jersey, 它還可以將度量數(shù)據(jù)發(fā)送給Ganglia和Graphite以提供圖形化的監(jiān)控。
Metrics提供了Gauge、Counter、Meter、Histogram、Timer等度量工具類以及Health Check功能。

引用Metric庫
將metrics-core加入到maven pom.xml中:
<dependencies>
<dependency>
<groupId>com.codahale.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>${metrics.version}</version>
</dependency>
</dependencies>將metrics.version 設(shè)置為metrics最新的版本。
現(xiàn)在你可以在你的程序代碼中加入一些度量了。
Registry
Metric的中心部件是MetricRegistry。 它是程序中所有度量metric的容器。讓我們接著在代碼中加入一行:
final MetricRegistry metrics = new MetricRegistry();
Gauge (儀表)
Gauge代表一個(gè)度量的即時(shí)值。 當(dāng)你開汽車的時(shí)候, 當(dāng)前速度是Gauge值。 你測體溫的時(shí)候, 體溫計(jì)的刻度是一個(gè)Gauge值。 當(dāng)你的程序運(yùn)行的時(shí)候, 內(nèi)存使用量和CPU占用率都可以通過Gauge值來度量。
比如我們可以查看一個(gè)隊(duì)列當(dāng)前的size。
public class QueueManager {
private final Queue queue;
public QueueManager(MetricRegistry metrics, String name) {
this.queue = new Queue();
metrics.register(MetricRegistry.name(QueueManager.class, name, "size"),
new Gauge<Integer>() {
@Override
public Integer getValue() {
return queue.size();
}
}
);
}
}registry 中每一個(gè)metric都有唯一的名字。 它可以是以.連接的字符串。 如"things.count" 和 "com.colobu.Thing.latency"。 MetricRegistry 提供了一個(gè)靜態(tài)的輔助方法用來生成這個(gè)名字:
MetricRegistry.name(QueueManager.class, "jobs", "size")
生成的name為com.colobu.QueueManager.jobs.size。
實(shí)際編程中對于隊(duì)列或者類似隊(duì)列的數(shù)據(jù)結(jié)構(gòu),你不會簡單的度量queue.size(), 因?yàn)樵趈ava.util和java.util.concurrent包中大部分的queue的#size是O(n),這意味的調(diào)用此方法會有性能的問題, 更深一步,可能會有l(wèi)ock的問題。
RatioGauge可以計(jì)算兩個(gè)Gauge的比值。 Meter和Timer可以參考下面的代碼創(chuàng)建。下面的代碼用來計(jì)算計(jì)算命中率 (hit/call)。
public class CacheHitRatio extends RatioGauge {
private final Meter hits;
private final Timer calls;
public CacheHitRatio(Meter hits, Timer calls) {
this.hits = hits; this.calls = calls;
}
@Override
public Ratio getValue() {
return Ratio.of(hits.oneMinuteRate(), calls.oneMinuteRate());
}
}CachedGauge可以緩存耗時(shí)的測量。DerivativeGauge可以引用另外一個(gè)Gauage。
Counter (計(jì)數(shù)器)
Counter是一個(gè)AtomicLong實(shí)例, 可以增加或者減少值。 例如,可以用它來計(jì)數(shù)隊(duì)列中加入的Job的總數(shù)。
private final Counter pendingJobs
= metrics.counter(name(QueueManager.class, "pending-jobs"));
public void addJob(Job job) {
pendingJobs.inc();
queue.offer(job);
}
public Job takeJob() {
pendingJobs.dec();
return queue.take();
}和上面Gauage不同,這里我們使用的是metrics.counter方法而不是metrics.register方法。 使用metrics.counter更簡單。
Meter ()
Meter用來計(jì)算事件的速率。 例如 request per second。 還可以提供1分鐘,5分鐘,15分鐘不斷更新的平均速率。
private final Histogram responseSizes
= metrics.histogram(name(RequestHandler.class, "response-sizes");
public void handleRequest(Request request, Response response) {
// etc
responseSizes.update(response.getContent().length);
}Histogram (直方圖)
Histogram可以為數(shù)據(jù)流提供統(tǒng)計(jì)數(shù)據(jù)。 除了最大值,最小值,平均值外,它還可以測量 中值(median),百分比比如XX%這樣的Quantile數(shù)據(jù) 。
private final Histogram responseSizes = metrics.histogram(name(RequestHandler.class, "response-sizes"); public void handleRequest(Request request, Response response) { // etc responseSizes.update(response.getContent().length); }
這個(gè)例子用來統(tǒng)計(jì)response的字節(jié)數(shù)。
Metrics提供了一批的Reservoir實(shí)現(xiàn),非常有用。例如SlidingTimeWindowReservoir 用來統(tǒng)計(jì)最新N個(gè)秒(或其它時(shí)間單元)的數(shù)據(jù)。
Timer (計(jì)時(shí)器)
Timer用來測量一段代碼被調(diào)用的速率和用時(shí)。
private final Timer responses = metrics.timer(name(RequestHandler.class, "responses"));
public String handleRequest(Request request, Response response) {
final Timer.Context context = responses.time();
try {
// etc;
return "OK";
} finally {
context.stop();
}
}這段代碼用來計(jì)算中間的代碼用時(shí)以及request的速率。
Health Check (健康檢查)
Metric還提供了服務(wù)健康檢查能力, 由metrics-healthchecks模塊提供。
先創(chuàng)建一個(gè)HealthCheckRegistry實(shí)例。
final HealthCheckRegistry healthChecks = new HealthCheckRegistry();
再實(shí)現(xiàn)一個(gè)HealthCheck子類, 用來檢查數(shù)據(jù)庫的狀態(tài)。
public class DatabaseHealthCheck extends HealthCheck {
private final Database database;
public DatabaseHealthCheck(Database database) {
this.database = database;
}
@Override
public HealthCheck.Result check() throws Exception {
if (database.isConnected()) {
return HealthCheck.Result.healthy();
} else {
return HealthCheck.Result.unhealthy("Cannot connect to " +
database.getUrl());
}
}
}注冊一下。
healthChecks.register("mysql", new DatabaseHealthCheck(database));最后運(yùn)行健康檢查并查看檢查結(jié)果。
final Map<String, HealthCheck.Result> results = healthChecks.runHealthChecks();
for (Entry<String, HealthCheck.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();
}
}
}Metric內(nèi)置一個(gè)ThreadDeadlockHealthCheck, 它使用java內(nèi)置的線程死鎖檢查方法來檢查程序中是否有死鎖。
JMX報(bào)表
通過JMX報(bào)告Metric。
final JmxReporter reporter = JmxReporter.forRegistry(registry).build(); reporter.start();
一旦啟動(dòng), 所有registry中注冊的metric都可以通過JConsole或者VisualVM查看 (通過MBean插件)。
HTTP報(bào)表
Metric也提供了一個(gè)servlet (AdminServlet)提供JSON風(fēng)格的報(bào)表。它還提供了單一功能的servlet (MetricsServlet, HealthCheckServlet, ThreadDumpServlet, PingServlet)。
你需要在pom.xml加入metrics-servlets。
<dependency>
<groupId>com.codahale.metrics</groupId>
<artifactId>metrics-servlets</artifactId>
<version>${metrics.version}</version>
</dependency>其它報(bào)表
除了JMX和HTTP, metric還提供其它報(bào)表。
STDOUT, using ConsoleReporter from metrics-core
final ConsoleReporter reporter = ConsoleReporter.forRegistry(registry)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
reporter.start(1, TimeUnit.MINUTES);CSV files, using CsvReporter from metrics-core
final CsvReporter reporter = CsvReporter.forRegistry(registry)
.formatFor(Locale.US)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build(new File("~/projects/data/"));
reporter.start(1, TimeUnit.SECONDS);SLF4J loggers, using Slf4jReporter from metrics-core
final Slf4jReporter reporter = Slf4jReporter.forRegistry(registry)
.outputTo(LoggerFactory.getLogger("com.example.metrics"))
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
reporter.start(1, TimeUnit.MINUTES);Ganglia, using GangliaReporter from metrics-ganglia
final GMetric ganglia = new GMetric("ganglia.example.com", 8649, UDPAddressingMode.MULTICAST, 1);
final GangliaReporter reporter = GangliaReporter.forRegistry(registry)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build(ganglia);
reporter.start(1, TimeUnit.MINUTES);Graphite, using GraphiteReporter from metrics-graphite
MetricSet
可以將一組Metric組織成一組便于重用。
final Graphite graphite = new Graphite(new InetSocketAddress("graphite.example.com", 2003));
final GraphiteReporter reporter = GraphiteReporter.forRegistry(registry)
.prefixedWith("web1.example.com")
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.filter(MetricFilter.ALL)
.build(graphite);
reporter.start(1, TimeUnit.MINUTES);一些模塊 metrics-json提供了json格式的序列化。
以及為其它庫提供度量的能力metrics-ehcachemetrics-httpclientmetrics-jdbimetrics-jerseymetrics-jettymetrics-log4jmetrics-logbackmetrics-jvmmetrics-servlet 注意不是metrics-servlets
第三方庫
- metrics-librato 提供Librato Metrics報(bào)表
- Metrics Spring Integration 提供了Spring的集成
- sematext-metrics-reporter 提供了SPM報(bào)表.
- wicket-metrics提供Wicket應(yīng)用.
- metrics-guice 提供Guice集成.
- metrics-scala 提供了為Scala優(yōu)化的API.
這里重點(diǎn)介紹一下Metrics for Spring
Metrics for Spring
這個(gè)庫為Spring增加了Metric庫, 提供基于XML或者注解方式。
- 可以使用注解創(chuàng)建metric和代理類。 @Timed, @Metered, @ExceptionMetered, @Counted
- 為注解了 @Gauge 和 @CachedGauge的bean注冊Gauge
- 為@Metric注解的字段自動(dòng)裝配
- 注冊HealthCheck
- 通過XML配置產(chǎn)生報(bào)表
- 通過XML注冊metric和metric組
你需要在pom.xml加入
<dependency>
<groupId>com.ryantenney.metrics</groupId>
<artifactId>metrics-spring</artifactId>
<version>3.0.1</version>
</dependency>基本用法
XML風(fēng)格的配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:metrics="http://www.ryantenney.com/schema/metrics"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.ryantenney.com/schema/metrics http://www.ryantenney.com/schema/metrics/metrics-3.0.xsd">
<!-- Registry should be defined in only one context XML file -->
<metrics:metric-registry id="metrics" />
<!-- annotation-driven must be included in all context files -->
<metrics:annotation-driven metric-registry="metrics" />
<!-- (Optional) Registry should be defined in only one context XML file -->
<metrics:reporter type="console" metric-registry="metrics" period="1m" />
<!-- (Optional) The metrics in this example require the metrics-jvm jar-->
<metrics:register metric-registry="metrics">
<bean metrics:name="jvm.gc" class="com.codahale.metrics.jvm.GarbageCollectorMetricSet" />
<bean metrics:name="jvm.memory" class="com.codahale.metrics.jvm.MemoryUsageGaugeSet" />
<bean metrics:name="jvm.thread-states" class="com.codahale.metrics.jvm.ThreadStatesGaugeSet" />
<bean metrics:name="jvm.fd.usage" class="com.codahale.metrics.jvm.FileDescriptorRatioGauge" />
</metrics:register>
<!-- Beans and other Spring config -->
</beans>java注解的方式
import java.util.concurrent.TimeUnit;
import org.springframework.context.annotation.Configuration;
import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.SharedMetricRegistries;
import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;
import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter;
@Configuration
@EnableMetrics
public class SpringConfiguringClass extends MetricsConfigurerAdapter {
@Override
public void configureReporters(MetricRegistry metricRegistry) {
ConsoleReporter.forRegistry(metricRegistry).build().start(1, TimeUnit.MINUTES);
}
}注: go Metrics使用: Go語言metrics應(yīng)用監(jiān)控指標(biāo)基本使用說明
以上就是詳解Metrics應(yīng)用監(jiān)控指標(biāo)的使用說明的詳細(xì)內(nèi)容,更多關(guān)于Metrics應(yīng)用監(jiān)控指標(biāo)使用的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
VSCode 使用Settings Sync同步配置(最新版教程,非常簡單)
這篇文章主要介紹了VSCode 使用Settings Sync同步配置(最新版教程,非常簡單),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
使用HTTP_X_FORWARDED_FOR獲取客戶端IP的嚴(yán)重后果
我的建議是不要再使用上面的方法去獲取客戶端IP.即是不要再理會代理情況.2009-11-11
VSCode讓終端默認(rèn)在當(dāng)前文件的路徑啟動(dòng)(方法推薦)
這篇文章主要介紹了VSCode中如何讓終端默認(rèn)在當(dāng)前文件的路徑啟動(dòng),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
Jenkins定時(shí)構(gòu)建語法規(guī)則及時(shí)間設(shè)置
這篇文章主要為大家介紹了Jenkins定時(shí)構(gòu)建時(shí)間設(shè)置,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06

