1、实现自定义exporter
1.1 四种常用Metrics
1.1.1 Counter
连续增加不会减少的计数器,可以用于记录只增不减的类型,例如:网站访问人数,系统运行时间等。
对于 Counter 类型的指标,只包含一个increment()
的方法,就是用于计数器+1。
一般而言,Counter 类型的 metric 指标使用 _total
结束,如 http_requests_total。
1.1.2 Gauge
可增可减的仪表盘,曲线图。
对于这类可增可减的指标,用于反应应用的当前状态。
例如在监控主机时,主机当前空闲的内存大小,可用内存大小等等。
在设置指标时指定指标的值。
1.1.3 Histogram
主要用来统计数据的分布情况,这是一种特殊的 metrics 数据类型,代表的是一种近似的百分比估算数值,统计所
有离散的指标数据在各个取值区段内的次数。例如:我们想统计一段时间内 http 请求响应小于 0.005 秒、小于
0.01秒、小于0.025秒的数据分布情况。那么使用 Histogram 采集每一次 http 请求的时间,同时设置 bucket。
Histogram 会自动创建 3 个指标,分别为:
1、事件发生总次数: basename_count
:
实际含义: 当前一共发生了2次http请求
io_namespace_http_requests_latency_seconds_histogram_count{path="/",method="GET",code="200",} 2.0
2、所有事件产生值的大小的总和: basename_sum
实际含义: 发生的2次http请求总的响应时间为13.107670803000001 秒
io_namespace_http_requests_latency_seconds_histogram_sum{path="/",method="GET",code="200",} 13.107670803000001
3、事件产生的值分布在bucket中的次数: basename_bucket{le="上包含"}
在总共2次请求当中。http请求响应时间 <=0.005 秒 的请求次数为0
io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.005",} 0.0
在总共2次请求当中。http请求响应时间 <=0.01 秒 的请求次数为0
io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.01",} 0.0
在总共2次请求当中。http请求响应时间 <=0.025 秒 的请求次数为0
io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.025",} 0.0
1.1.4 Summary
Summary 和 Histogram非常相似,都可以统计事件发生的次数或者大小,以及其分布情况,他们都提供了对时间
的计数 _count
以及值的汇总 _sum
,也都提供了可以计算统计样本分布情况的功能,不同之处在于 Histogram
可以通过 histogram_quantile 函数在服务器计算分位数,而 Sumamry 的分位数则是直接在客户端进行定义的。
因此对于分位数的计算,Summary 在通过 PromQL 进行查询的时候有更好的性能表现,而 Histogram 则会消耗
更多的资源,但是相对于客户端而言 Histogram 消耗的资源就更少。用哪个都行,根据实际场景自由调整即可。
需要注意的是,Prometheus 需要收集的数据是随着时间的增长而增长的,所以它一般不建议保留长期的指标数
据,默认保留 15 天。如果监控的数据发现问题,那么需要我们配置告警发现,快速处理。
1.2 基于SpringBoot写一个简单的exporter_demo
1.2.1 pom.xml 配置如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-web-expoter-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-web-exporter-demo</name>
<description>自定义实现exporter</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.4.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.4.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.2.2 启动类
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* @author zsx
*/
@EnableScheduling
@SpringBootApplication
public class SpringWebExporterDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringWebExporterDemoApplication.class, args);
}
}
1.2.3 配置文件
management.endpoint.metrics.enabled=true
management.endpoints.web.exposure.include=*
management.endpoint.prometheus.enabled=true
spring.application.name=exporter
management.metrics.tags.application=${spring.application.name}
management.metrics.export.prometheus.enabled=true
management.metrics.enable.jvm=false
management.metrics.enable.tomcat=false
management.metrics.enable.logback=false
management.metrics.enable.process=false
management.metrics.enable.executor=false
management.metrics.enable.http=false
management.metrics.enable.system=false
management.metrics.enable.disk=false
management.metrics.enable.application=false
1.2.4 CounterDemo
package com.example.prometheus;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tags;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
/**
* @author zhangshixing
* @date 2022年03月16日 20:57
* https://vimsky.com/examples/detail/java-method-io.micrometer.core.instrument.MeterRegistry.counter.html
* https://vimsky.com/examples/detail/java-class-io.micrometer.core.instrument.MeterRegistry.html
*/
@Configuration
public class CounterDemo {
@Autowired
private MeterRegistry registry;
@Scheduled(cron = "0/5 * * * * ?")
public void changeCounter() {
Counter c = registry.counter("MyCounter", Tags.of("MyCounterKey1", "MyCounterValue1", "MyCounterKey2", "MyCounterValue2"));
c.increment(2);
}
}
1.2.5 GaugeDemo
package com.example.prometheus;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tags;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.Random;
/**
* @author zhangshixing
* @date 2022年03月16日 21:28
* https://vimsky.com/examples/detail/java-method-io.micrometer.core.instrument.MeterRegistry.gauge.html
*/
@Configuration
public class GaugeDemo {
@Autowired
private MeterRegistry registry;
@Scheduled(cron = "0/5 * * * * ?")
public void changeGauge() {
Random random = new Random();
Gauge gauge = registry.find("GaugeDemo").gauge();
if (gauge == null) {
registry.gauge("GaugeDemo", Tags.of("GaugeDemoKey1", "GaugeDemoValue1"), random.nextInt(100));
} else {
registry.remove(gauge.getId());
registry.gauge("GaugeDemo", Tags.of("GaugeDemoKey1", "GaugeDemoValue1"), random.nextInt(100));
}
}
}
1.2.6 SummaryDemo
package com.example.prometheus;
import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tags;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.Random;
/**
* @author zhangshixing
* @date 2022年03月16日 21:40
* https://vimsky.com/examples/detail/java-method-io.micrometer.core.instrument.MeterRegistry.summary.html
*/
@Configuration
public class SummaryDemo {
@Autowired
private MeterRegistry registry;
@Scheduled(cron = "0/5 * * * * ?")
public void changeSummary() {
Random random = new Random();
DistributionSummary distributionSummary = registry.summary("SummaryDemo", Tags.of("SummaryDemoKey1", "SummaryDemoValue1"));
distributionSummary.record(random.nextInt(100));
distributionSummary.record(random.nextInt(100));
distributionSummary.record(random.nextInt(100));
distributionSummary.record(random.nextInt(100));
}
}
1.2.7 HistogramDemo
package com.example.prometheus;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import java.time.Duration;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;
/**
* @author zhangshixing
* @date 2022年03月16日 21:47
* https://vimsky.com/zh-tw/examples/detail/java-class-io.micrometer.core.instrument.Timer.html
*/
@Configuration
public class HistogramDemo {
@Autowired
private MeterRegistry registry;
@Scheduled(cron = "0/5 * * * * ?")
public void changeHistogram() {
Timer timer = Timer.builder("HistogramDemo").publishPercentileHistogram().publishPercentiles(0.1, 0.5, 0.99).register(registry);
IntStream.rangeClosed(1, 20).forEach(i -> {
timer.record(Duration.ofSeconds(ThreadLocalRandom.current().nextInt(20)));
});
}
}
1.2.8 Info
package com.example.prometheus;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
/**
* @author zhangshixing
* @date 2022年03月16日 22:00
* https://vimsky.com/examples/detail/java-class-com.codahale.metrics.annotation.ExceptionMetered.html
*/
@Configuration
public class Info {
@Autowired
private MeterRegistry registry;
@Scheduled(cron = "0/5 * * * * ?")
public void info() {
registry.getMeters()
.stream()
.forEach(m -> {
System.out.println(m.getId() + "-->" + m.measure());
});
}
}
1.2.9 结果
最终的结果如下所示:
# HELP HistogramDemo_seconds
# TYPE HistogramDemo_seconds histogram
HistogramDemo_seconds{application="exporter",quantile="0.1",} 5.066719232
HistogramDemo_seconds{application="exporter",quantile="0.5",} 11.24073472
HistogramDemo_seconds{application="exporter",quantile="0.99",} 19.2937984
HistogramDemo_seconds_bucket{application="exporter",le="0.001",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.001048576",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.001398101",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.001747626",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.002097151",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.002446676",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.002796201",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.003145726",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.003495251",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.003844776",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.004194304",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.005592405",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.006990506",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.008388607",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.009786708",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.011184809",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.01258291",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.013981011",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.015379112",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.016777216",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.022369621",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.027962026",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.033554431",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.039146836",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.044739241",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.050331646",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.055924051",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.061516456",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.067108864",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.089478485",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.111848106",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.134217727",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.156587348",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.178956969",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.20132659",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.223696211",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.246065832",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.268435456",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.357913941",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.447392426",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.536870911",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.626349396",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.715827881",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.805306366",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.894784851",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="0.984263336",} 1.0
HistogramDemo_seconds_bucket{application="exporter",le="1.073741824",} 2.0
HistogramDemo_seconds_bucket{application="exporter",le="1.431655765",} 2.0
HistogramDemo_seconds_bucket{application="exporter",le="1.789569706",} 2.0
HistogramDemo_seconds_bucket{application="exporter",le="2.147483647",} 2.0
HistogramDemo_seconds_bucket{application="exporter",le="2.505397588",} 2.0
HistogramDemo_seconds_bucket{application="exporter",le="2.863311529",} 2.0
HistogramDemo_seconds_bucket{application="exporter",le="3.22122547",} 2.0
HistogramDemo_seconds_bucket{application="exporter",le="3.579139411",} 2.0
HistogramDemo_seconds_bucket{application="exporter",le="3.937053352",} 2.0
HistogramDemo_seconds_bucket{application="exporter",le="4.294967296",} 3.0
HistogramDemo_seconds_bucket{application="exporter",le="5.726623061",} 5.0
HistogramDemo_seconds_bucket{application="exporter",le="7.158278826",} 9.0
HistogramDemo_seconds_bucket{application="exporter",le="8.589934591",} 12.0
HistogramDemo_seconds_bucket{application="exporter",le="10.021590356",} 17.0
HistogramDemo_seconds_bucket{application="exporter",le="11.453246121",} 20.0
HistogramDemo_seconds_bucket{application="exporter",le="12.884901886",} 24.0
HistogramDemo_seconds_bucket{application="exporter",le="14.316557651",} 30.0
HistogramDemo_seconds_bucket{application="exporter",le="15.748213416",} 31.0
HistogramDemo_seconds_bucket{application="exporter",le="17.179869184",} 36.0
HistogramDemo_seconds_bucket{application="exporter",le="22.906492245",} 40.0
HistogramDemo_seconds_bucket{application="exporter",le="28.633115306",} 40.0
HistogramDemo_seconds_bucket{application="exporter",le="30.0",} 40.0
HistogramDemo_seconds_bucket{application="exporter",le="+Inf",} 40.0
HistogramDemo_seconds_count{application="exporter",} 40.0
HistogramDemo_seconds_sum{application="exporter",} 446.0
# HELP HistogramDemo_seconds_max
# TYPE HistogramDemo_seconds_max gauge
HistogramDemo_seconds_max{application="exporter",} 19.0
# HELP SummaryDemo
# TYPE SummaryDemo summary
SummaryDemo_count{SummaryDemoKey1="SummaryDemoValue1",application="exporter",} 8.0
SummaryDemo_sum{SummaryDemoKey1="SummaryDemoValue1",application="exporter",} 366.0
# HELP SummaryDemo_max
# TYPE SummaryDemo_max gauge
SummaryDemo_max{SummaryDemoKey1="SummaryDemoValue1",application="exporter",} 98.0
# HELP MyCounter_total
# TYPE MyCounter_total counter
MyCounter_total{MyCounterKey1="MyCounterValue1",MyCounterKey2="MyCounterValue2",application="exporter",} 4.0
# HELP GaugeDemo
# TYPE GaugeDemo gauge
GaugeDemo{GaugeDemoKey1="GaugeDemoValue1",application="exporter",} 0.0