1. 目的
实现Granafa+Prometeus+Spring boot的业务指标监控
2. 下载
3. 项目集成
3.1 依赖配置
核心依赖
????<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
|
3.2参数配置
3.2.1 Spring boot程序yaml配置文件
spring:
application:
name: prometheus-example
management:
endpoints:
web:
exposure:
include: health,prometheus
metrics:
tags:
application: ${spring.application.name} #为应用设置tag ,方便区分不同的应用
? |
3.3.1 Prometheus yaml文件配置
- job_name: 'prometheus-example'
# 抓取频率
scrape_interval: 5s
# 抓取的端点
metrics_path: '/actuator/prometheus'
static_configs:
# 目标机器,数组,也就是说支持集群拉取
- targets: ['127.0.0.1:8080']
|
4. Micrometer指标
4.1 计数器 Counter
? ?Counter 只会报告单个指标,可以增加一个可选的值,且该值必须是正数,默认为 1。Counter常用来记录某些将一直正增长的数据,如 请求次数、变化次数,通过在对应监控系统使用聚合函数,如 rate、increase 等,可以计算出指标在指定时间范围的变化率,也就是通常说的 QPS
4.1.1 定义
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Counter;
@Data
@RestController
public class PrometheusController {
private Counter counter;
private final MeterRegistry registry;
@Autowired
public PrometheusCustomMonitor(MeterRegistry registry) {
this.registry = registry;
counter = registry.counter("order_counter", "orderCounter", "test-auth");
}
} |
4.1.2 使用
@RequestMapping("/counter")
public String orderCounter() {
// 统计下单次数 ? ?
counter.increment();
?Random random = new Random();
int amount = random.nextInt(100);
return "下单成功, 金额: " + amount;
}
|
4.2 总计?DistributionSummary
Summary用于跟踪事件的分发。 它在结构上类似于计时器,但记录的值不代表时间单位。 例如,分发摘要可用于衡量命中服务器的请求的有效负载大小。
4.2.1 定义
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.DistributionSummary;
@Data
@RestController
public class PrometheusController {
private DistributionSummary summary;
private final MeterRegistry registry;
@Autowired
public PrometheusCustomMonitor(MeterRegistry registry) {
this.registry = registry;
? summary = registry.summary("order_summary", "orderSummary", "test-auth");
}
} |
4.2.2 使用
@RequestMapping("/summary")
public String orderSummary() {
?Random random = new Random();
int amount = random.nextInt(100);
// 统计下单记录
summary.record(amount);
return "下单成功, 金额: " + amount;
} |
4.3 量规 Gauge
一般用于监测有自然上限的事件或任务,而 Counter 一般用于无自然上限的事件或任务。有自然上限:如内存使用大小、容器大小、运行中的线程数量等。
4.3.1 定义
import io.micrometer.core.instrument.Tags;
import io.micrometer.core.instrument.MeterRegistry;
@Data
@RestController
public class PrometheusController {
? private AtomicInteger gauge;
private final MeterRegistry registry;
@Autowired
public PrometheusCustomMonitor(MeterRegistry registry) {
this.registry = registry;
? ? gauge = registry.gauge("order_gauge", Tags.of("orderGauge", "test-auth"), new AtomicInteger(1000));
}
} |
4.3.2 使用
@RequestMapping("/gauge")
public String orderGauge() {
?Random random = new Random();
int amount = random.nextInt(100);
// 记录余额
? gauge.decrementAndGet();
return "下单成功, 金额: " + amount;
} |
4.4 计时器 Timer
Timer是计时器,用来测量短时间的代码块的执行时间的分布。Timer记录代码块的执行时间后,可以对执行时间进行统计,分析记录执行的最大时间、总时间、平均时间、执行完成的总任务等。
4.4.1 定义
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.MeterRegistry;
@Data
@RestController
public class PrometheusController {
? private Timer timer;
private final MeterRegistry registry;
@Autowired
public PrometheusCustomMonitor(MeterRegistry registry) {
this.registry = registry;
? ? timer = registry.timer("order_timer", "orderTimer", "test-auth");
}
} |
4.4.2 使用
@RequestMapping("/timer")
public String orderTimer() {
?Random random = new Random();
int amount = random.nextInt(100);
// 记录接口用时
timer.record(100, TimeUnit.MILLISECONDS);
timer.record(Duration.ofMillis(100));
timer.record(() -> {
try {
Thread.sleep(amount2 * amount2 / 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}); ?
return "下单成功, 金额: " + amount;
} |
4.5 在线计时器 LongTaskTimer
LongTaskTimer一般监控长时间执行的程序,可以实时观测任务的耗时和正在执行的任务数量
4.5.1 定义
import io.micrometer.core.instrument.LongTaskTimer;
import io.micrometer.core.instrument.MeterRegistry;
@Data
@RestController
public class PrometheusController {
? private LongTaskTimer longTaskTimer;
private final MeterRegistry registry;
@Autowired
public PrometheusCustomMonitor(MeterRegistry registry) {
this.registry = registry;
? ? longTaskTimer = registry.more().longTaskTimer("order_long_task_timer", "order_long_task_time", "test-auth");
}
} |
4.5.2 使用
@RequestMapping("/long/timer")
public String orderTimer() {
? Random random = new Random();
int amount2 = random.nextInt(100);
longTaskTimer.record(() -> {
try {
Thread.sleep(amount2 * amount2 * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
return "下单成功, 金额, amount2: " + amount2;
} |
5. Prometheus client指标
5.1 计数器 Counter
? ?Counter 只会报告单个指标,可以增加一个可选的值,且该值必须是正数,默认为 1。Counter常用来记录某些将一直正增长的数据,如 请求次数、变化次数,通过在对应监控系统使用聚合函数,如 rate、increase 等,可以计算出指标在指定时间范围的变化率,也就是通常说的 QPS
5.1.1 定义
import io.prometheus.client.Counter;
import io.prometheus.client.CollectorRegistry;
@Data
@RestController
public class PrometheusController {
private Counter counter2;
private final CollectorRegistry collectorRegistry;
@Autowired
public PrometheusCustomMonitor( CollectorRegistry collectorRegistry) {
this.collectorRegistry = collectorRegistry;
? counter2 = io.prometheus.client.Counter.build().name("order_counter2").labelNames("order_counter2", "testCounter2").help("counter").register(collectorRegistry); ?
}
} |
5.1.2 使用
@RequestMapping("/order/counter2")
public String orderCounter2() {? ?
Random random = new Random();
int amount = random.nextInt(100);
// 根据不同标签区分不同数据类型
counter2.labels("amount1", "test1").inc(amount);
counter2.labels("amount1", "test3").inc(amount);
int amount2 = random.nextInt(100);
counter2.labels("amount2", "test2").inc(amount2);
return "下单成功, 金额, amount1: " + amount + " amount2: " + amount2;
}
|
5.2 总计 Summary
Summary用于跟踪事件的分发。 它在结构上类似于计时器,但记录的值不代表时间单位。 例如,分发摘要可用于衡量命中服务器的请求的有效负载大小。
5.2.1 定义
import io.prometheus.client.Summary;
import io.prometheus.client.CollectorRegistry;
@Data
@RestController
public class PrometheusController {
? private Summary summary2;
private final CollectorRegistry collectorRegistry;
@Autowired
public PrometheusCustomMonitor( CollectorRegistry collectorRegistry) {
this.collectorRegistry = collectorRegistry;
? ? summary2 = Summary.build().name("order_summary2").labelNames("order_summary2", "testSummary2").help("summary").register(collectorRegistry); ? ?
}
} |
5.2.2 使用
@RequestMapping("/order/summary2")
public String orderSummary2() {
?Random random = new Random();
int amount = random.nextInt(100);
summary2.labels("summary1", "test1").observe(amount);
int amount2 = random.nextInt(100);
summary2.labels("summary2", "test2").observe(amount2);
Summary.Timer timer = summary2.labels("summary4", "timer").startTimer();
summary2.labels("summary3", "timer").time(() -> {
try {
Thread.sleep(amount * amount);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
timer.close();
return "下单成功, 金额, amount1: " + amount + " amount2: " + amount2;
} |
5.3 量规 Gauge
一般用于监测有自然上限的事件或任务,而 Counter 一般用于无自然上限的事件或任务。有自然上限:如内存使用大小、容器大小、运行中的线程数量等。
5.3.1 定义
import io.prometheus.client.Gauge;
import io.prometheus.client.CollectorRegistry;
@Data
@RestController
public class PrometheusController {
? private Gauge gauge2;
private final CollectorRegistry collectorRegistry;
@Autowired
public PrometheusCustomMonitor( CollectorRegistry collectorRegistry) {
this.collectorRegistry = collectorRegistry;
? ? gauge2 = Gauge.build().name("order_gauge2").labelNames("order_gauge2", "testGauge2").help("gauge").register(collectorRegistry); ? ?
}
} |
5.3.2 使用
@RequestMapping("/gauge2")
public String orderGauge2() {
Random random = new Random();
int amount = random.nextInt(100);
gauge2.labels("gauge1", "test1").set(amount);
int amount2 = random.nextInt(100);
gauge2.labels("gauge2", "test2").set(amount2);
return "下单成功, 金额, amount1: " + amount + " amount2: " + amount2;
} |
5.4 直方图 Histogram
5.4.1 定义
import io.prometheus.client.Histogram;
import io.prometheus.client.CollectorRegistry;
@Data
@RestController
public class PrometheusController {
? private Histogram histogram;
private Histogram histogram2;
private Histogram histogram3;;
private final CollectorRegistry collectorRegistry;
@Autowired
public PrometheusCustomMonitor( CollectorRegistry collectorRegistry) {
this.collectorRegistry = collectorRegistry;
// 默认刻度
? ? histogram = Histogram.build().name("order_histogram").labelNames("order_histogram", "testHistogram").help("histogram").register(collectorRegistry);
// 自己设定刻度
histogram2 = Histogram.build().buckets(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10).name("order_histogram2").labelNames("order_histogram", "testHistogram").help("histogram").register(collectorRegistry);
histogram3 = Histogram.build().buckets(0, 10, 20, 30, 40, 50, 100).name("order_histogram3").labelNames("order_histogram", "testHistogram").help("histogram").register(collectorRegistry); ? ?
}
} |
5.3.2 使用
@RequestMapping("/order/timer")
public String orderTimer() {
?Random random = new Random();
? int amount = random.nextInt(100);
int amount2 = random.nextInt(100);
histogram2.labels("histogram2", "test1").observe(amount);
histogram2.labels("histogram2", "test2").observe(amount2);
histogram.labels("histogram1", "test3").time(() -> {
try {
Thread.sleep(amount * amount / 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
histogram3.labels("histogram3", "test4").time(() -> {
try {
Thread.sleep(amount2 * amount2 / 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
return "下单成功, 金额, amount1: " + amount + " amount2: " + amount2;
} |
6. Granafa配置
6.1 添加Prometheus数据源
6.1.1 启动Prometheus和Grafana
样例:windows安装启动,下载安装包解压,bin目录下双击.exe程序
Prometheus
Granafa
??
6.1.2 添加数据源
Grafana地址:http://127.0.0.1:3000/datasources
6.2 导入仪表盘模板
首先在Grafana模板仓库,找到要导入模板ID,模板地址:Dashboards | Grafana Labs
选择添加的数据源??
完成
|