自定义Metrics|让Prometheus监控你的应用程序

这是我参与更文挑战的第12天,活动详情查看: 更文挑战

前言:

本文将以Spring Boot/Spring Cloud为例,介绍如果使用Prometheus SDK实现自定义监控指标的定义以及暴露,并且会介绍Prometheus中四种不同指标类型(Counter, Gauge, Histogram, Summary)的实际使用场景;

需求背景:

最近在做的一个新的项目,上线后要实现Prometheus监控,以及对项目里自己比较在意的指标进行自定义监控,用的是公司已有的Grafana,并没有自己搭建Grafana+Prometheus的仪表盘,下一篇文章会更新一些如何使用Grafana+Prometheus搭建项目仪表盘,这里就不多做赘述啦!下面看正文👇👇👇;

对于后端的一些应用以及环境架构。一般而言,我们通常会从几个层面进行监控指标的采集:

  • 入口网关:这里可以是Nginx/HaProxy这一类的负载均衡器,也可以是注入Spring Cloud Zuul这一类框架提供的微服务入口。一般来说我们需要对所有Http Request相关的指标数据进行采集。如请求地址,Http Method,返回状态码,响应时长等。从而可以通过这些指标历史数据去分析业务压力,服务状态等信息。
  • 应用服务:对于应用服务而言,基本的如应用本身的资源使用率,比如如果是Java类程序可以直接通过JVM信息来进行统计,如果是部署到容器中,则可以通过Container的资源使用情况来统计。除了资源用量外,某些特殊情况下,我们可能还会对应用中的某些业务指标进行采集。
  • 基础设施:虚拟机或者物理机的资源使用情况等。
  • 其它:集群环境中所使用到的数据库,缓存,消息队列等中间件状态等。

对于以上的集中场景中,除了直接使用Prometheus社区提供的Exporter外,不同的项目可能还需要实现一些自定义的Exporter用于实现对于特定目的的指标的采集和监控需求。

对于监控系统主要由以下几个结构组成:

  • 目标服务:该服务即为各个组上线的服务,通过接入架构组提供的公共监控服务包后,会在服务启动之后暴露出一个数据监控接口 /actuator/prometheus,我们的一些监控数据指标也暴露在这里,直接请求http://localhost:8080/actuator/prometheus 即可
  • 数据搜集服务:即prometheus服务,该服务主要负责将定时各个目标服务接口暴露的数据搜集起来,并将接口中的数据根据【Metric】数据格式整合起来,供监控展示服务使用
  • 数据展示服务:即grafana,该服务为单纯的数据展示服务,可支持包括prometheus等多种数据搜集服务的数据展示,同时提供一些特性函数以应对多种复合的展示场景

接入方法

pom依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
xml复制代码<!--监控点开始-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${starter-actuator.version}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>${prometheus-simpleclient.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_spring_boot</artifactId>
<version>${prometheus-simpleclient.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_hotspot</artifactId>
<version>${prometheus-simpleclient.version}</version>
</dependency>
<!--监控点结束-->

application.properties配置文件:

1
2
3
4
5
6
7
ini复制代码management.metrics.export.prometheus.enabled=true
management.metrics.export.prometheus.step=1m
management.metrics.export.prometheus.descriptions=true
management.web.server.auto-time-requests=true
management.endpoints.prometheus.id=produce-server
management.endpoints.web.exposure.include=health,info,env,prometheus,metrics,httptrace,threaddump,heapdump,springmetrics,git
management.health.rabbit.enabled=false

不同项目对于暴露出去的接口要求不同,可针对各值环境对上述management.endpoints.web.exposure.include 参数进行相应调整

项目内新增prometheus数据收集组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
java复制代码import io.micrometer.core.instrument.ImmutableTag;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
* levelDb自定义监控指标
*
* @author taoze
* @version 1.0
* @date 4/27/21 10:42 AM
*/
@Component
@Slf4j
public class LevelDbMetrics {

/**
* levelDB监控项
*/
private AtomicLong levelDBHead = Metrics.gauge("a.levelDb.head", init(), new AtomicLong(0));
private AtomicLong levelDBTail = Metrics.gauge("a.levelDb.tail", init(), new AtomicLong(0));

/**
* 初始化tag
*
* @return
*/
List<Tag> init() {
List<Tag> list = new ArrayList<>();
String ip = null;
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
list.add(new ImmutableTag("host", StringUtils.isBlank(ip) ? "127.0.0.1" : ip));
return list;
}

public void setLevelDBHead(Long head) {
levelDBHead.set(head);
log.info("levelDB head = [{}]", levelDBHead.get());
}

public void setLevelDBTail(Long tail) {
levelDBTail.set(tail);
log.info("levelDB tail = [{}]", levelDBTail.get());
}
}
  • 想要将自定义数据暴露在/actuator/prometheus 中,就需要在项目中建立对一个Metrics对象,然后对这个对象进行数据更新,最终在调用接口时就会从这个Metrics对象存储的数据中获取到指定的数据
  • 更新值的时候调用 setLevelDBHead或setLevelDBTail方法即可或使用定时任务定时修改值

Metrics指标类型以及使用场景:

  • Counter,只增不减的计数器
  • Gauge,可增可减的仪表盘
  • Histogram,自带buckets区间用于统计分布统计图
  • Summary, 客户端定义的数据分布统计图
    除了上述方法我们也可以通过拦截器/过滤器:用于统计所有应用请求的情况等

WebMvcConfigurerAdapter方式手机监控指标:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
scala复制代码@SpringBootApplication
@EnablePrometheusEndpoint
public class SpringApplication extends WebMvcConfigurerAdapter implements CommandLineRunner {

@Autowired
private CustomExporter customExporter;

...省略的代码

@Override
public void run(String... args) throws Exception {
...省略的代码
customExporter.register();
}
}

ok!今日分享到此结束,搜集指标代码还是比较简单的,有类似需求的小伙伴可以试试哦,希望可以对大家有帮助,有不对的地方希望大家可以提出来的,共同成长;

整洁成就卓越代码,细节之中只有天地

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%