一灰灰blog 一灰灰blog
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)

一灰灰blog

资深搬运工
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)
  • 基础系列

  • DB系列

  • 搜索系列

  • MQ系列

  • WEB系列

  • 中间件

    • Email

    • Prometheus

      • 【中间件】zookeeper基础使用介绍
      • 【中间件】Zookeeper从0到1实现一个分布式锁
      • 【中间件】Prometheus实现应用监控
      • 【中间件】Prometheus自定义埋点上报
      • 【中间件】Prometheus自定义埋点姿势二
        • I. 自定义上报
          • 1.依赖
          • 2. 配置信息
          • 3. 自定义拦截器实现采集上报
          • 4. 注册并测试
        • II. 不能错过的源码和相关知识点
          • 0. 项目
          • 1. 微信公众号: 一灰灰Blog
      • 【中间件】Prometheus基于AOP实现埋点采集上报
      • 【中间件】Prometheus大盘配置实战
    • ZooKeeper

  • 运维

  • SpringSecurity

  • SpringCloud

  • Spring系列
  • 中间件
  • Prometheus
一灰灰
2021-11-19

【中间件】Prometheus自定义埋点姿势二

关于Prometheus的自定义埋点,前一篇博文已经介绍了,为啥这里又来一次?

看过前文的小伙伴可能会知道,之前采用的simpleclient包定义的几个metric来实现的,实际上有更简单方便的姿势,那就是直接借助MeterRegistry来创建Metric来实现数据采集即可

相比较于前文的实现,总的来说简易程度可见一般,上篇文章可以点击下文查看

  • 【中间件】Prometheus自定义埋点上报 | 一灰灰Blog (opens new window)

# I. 自定义上报

依然是搭建一个基础项目工程,本文演示的项目主要为SpringBoot2.2.1版本,更高的版本使用姿势没有太大的区别,至于1.x版本的不确保可行(因为我并没有测试)

# 1.依赖

pom依赖,主要是下面几个包

<dependencies>
    <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>
</dependencies>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 2. 配置信息

其次是配置文件,注册下Prometheus的相关信息

spring:
  application:
    name: prometheus-example
management:
  endpoints:
    web:
      exposure:
        include: "*"
  metrics:
    tags:
      application: ${spring.application.name}
1
2
3
4
5
6
7
8
9
10
11

上面配置中,有两个关键信息,前面博文也有介绍,这里简单说明

  • management.endpoints.web.exposure.include 这里指定所有的web接口都会上报
  • metrics.tags.application 这个应用所有上报的metrics 都会带上application这个标签

配置完毕之后,会提供一个 /actuator/prometheus的端点,供prometheus来拉取Metrics信息

# 3. 自定义拦截器实现采集上报

实现一个基础的拦截器,用来拦截所有的http请求,然后收集请求信息上报

public class MetricInterceptor extends HandlerInterceptorAdapter {
    @Autowired
    private MeterRegistry meterRegistry;
    private ThreadLocal<Timer.Sample> threadLocal = new ThreadLocal<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 总计数 + 1
        meterRegistry.counter("micro_req_total", Tags.of("url", request.getRequestURI(), "method", request.getMethod())).increment();
        // 处理中计数 +1
        meterRegistry.gauge("micro_process_req", Tags.of("url", request.getRequestURI(), "method", request.getMethod()), 1);

        Timer.Sample sample = Timer.start();
        threadLocal.set(sample);
        return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        try {
            super.postHandle(request, response, handler, modelAndView);
        } finally {
            meterRegistry.gauge("micro_process_req", Tags.of("url", request.getRequestURI(), "method", request.getMethod()), -1);
            //  Timer timer = meterRegistry.timer("micro_req_histogram", Tags.of("url", request.getRequestURI(), "method", request.getMethod(), "code", String.valueOf(response.getStatus())));
            Timer timer = Timer.builder("micro_req_histogram").minimumExpectedValue(Duration.ofMillis(1)).maximumExpectedValue(Duration.ofMinutes(3))
                    .sla(Duration.ofMillis(10), Duration.ofMillis(50), Duration.ofMillis(100), Duration.ofMillis(300), Duration.ofMillis(1000))
                    .tags(Tags.of("url", request.getRequestURI(), "method", request.getMethod(), "code", String.valueOf(response.getStatus())))
                    .register(meterRegistry);
            threadLocal.get().stop(timer);
            threadLocal.remove();
        }
    }
}
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

注意上面的三种Metric的创建方式

  • Counter: 直接使用 meterRegistry.counter()来创建metric并实现计数+1
    • 传参中,Tags组成的就是propmetheus中定义的label,kv格式,第一个参数用来定义MetricName
  • Gauge: 使用姿势与上面基本相同,不过需要注意计数的加减是直接在传参中
  • Histogram: 它的使用姿势就需要特别注意下了,在preHander中定义的是 Timer.Sampler对象,在 postHandler中实现的数据采集

上面短短一点代码,就实现了一个简单的自定义信息上报;接下来就是注册拦截器了

# 4. 注册并测试

拦截器依赖了Spring的bean对象,因此需要将它定义为bean对象

@RestController
@SpringBootApplication
public class Application implements WebMvcConfigurer {
    private Random random = new Random();

    @Bean
    public MetricInterceptor metricInterceptor() {
        return new MetricInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(metricInterceptor()).addPathPatterns("/**");
    }

    @GetMapping(path = "hello")
    public String hello(String name) {
        int sleep = random.nextInt(200);
        try {
            Thread.sleep(sleep);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello sleep: " + sleep + " for " + name;
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}
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

基于此一个简单的自定义采集上报就完成了;项目启动之后,通过访问采集端点查看是否有数据上报

最后小结一下,虽然SpringBoot可以非常方便的接入prometheus来采集一些常见的指标,但是当我们有自定义上报指标的需求时,直接使用MeterRegistry来收集信息,创建Metric是个不错的选择,通常我们选择的三种类型作用如下

  • 总的请求数:采用Counter
  • 当前正在处理的请求数:采用Gauge
  • 请求耗时直方图: Histogram

# II. 不能错过的源码和相关知识点

# 0. 项目

  • 工程:https://github.com/liuyueyi/spring-boot-demo (opens new window)
  • 源码:https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/421-prometheus-micro (opens new window)

# 1. 微信公众号: 一灰灰Blog

尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

  • 一灰灰Blog个人博客 https://blog.hhui.top (opens new window)
  • 一灰灰Blog-Spring专题博客 http://spring.hhui.top (opens new window)

一灰灰blog

编辑 (opens new window)
#Prometheus
上次更新: 2022/02/27, 11:13:23
【中间件】Prometheus自定义埋点上报
【中间件】Prometheus基于AOP实现埋点采集上报

← 【中间件】Prometheus自定义埋点上报 【中间件】Prometheus基于AOP实现埋点采集上报→

最近更新
01
【基础系列】基于maven多环境配置
04-25
02
【WEB系列】内嵌Tomcat配置Accesslog日志文件生成位置源码探索
04-24
03
【搜索系列】ES查询常用实例演示
04-18
更多文章>
Theme by Vdoing | Copyright © 2017-2022 一灰灰Blog
MIT License | 鄂ICP备18017282号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×