扩展自定义spring boot prometheus metrics

实现原理很简单,主要是基于micrometer包装提供的MeterRegistry bean 进行扩展

项目结构

  • maven 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.2.10.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <groupId>com.dalong</groupId>
  <artifactId>prome</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>prome</name>
  <description>Demo project for Spring Boot</description>
  <properties>
    <java.version>1.8</java.version>
  </properties>
  <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>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.6</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      <exclusions>
        <exclusion>
          <groupId>org.junit.vintage</groupId>
          <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>
  • 项目结构
    基于spring 的starter 官网生成
 
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── dalong
    │   │           └── prome
    │   │               ├── Login.java
    │   │               ├── MyService.java
    │   │               └── PromeApplication.java
    │   └── resources
    │       ├── application.properties
    │       ├── static
    │       └── templates
 
 
  • 代码说明
    application.properties,开启prometheus 配置的
 
management.endpoints.web.exposure.include=prometheus,health,info
management.endpoints.web.base-path=/

MyService.java 一个模拟延迟处理的bean

package com.dalong.prome;
import io.micrometer.core.annotation.Timed;
import org.springframework.stereotype.Service;
import java.util.HashMap;
/**
 @author dalong
*/
@Service
public class MyService {
    // 注册timed 可以查看服务请求时间的处理,我们可以查看比较慢的请求情况,尤其是异步,而且是长时间运行的调度任务
    @Timed(description = "fetch userservice")
    public Object fetchUserinfo() throws InterruptedException {
        HashMap<String,String> userinfo  =new HashMap<>();
        userinfo.put("name","demoapp");
        userinfo.put("version","v1");
        Thread.sleep((long) (1000*Math.random()));
        return userinfo;
    }
}
 

PromeApplication.java:入口,注册了一个time的aop bean

package com.dalong.prome;
import io.micrometer.core.aop.TimedAspect;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class PromeApplication {
    @Bean
    public TimedAspect timedAspect(MeterRegistry registry) {
        return new TimedAspect(registry);
    }
    public static void main(String[] args) {
        SpringApplication.run(PromeApplication.class, args);
    }
}

Login.java 一个service

package com.dalong.prome;
import io.micrometer.core.annotation.Timed;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
/**
 @author dalong
*/
@RestController
public class Login {
    MeterRegistry meterRegistry;
    Counter okCounter;
    Counter failCounter;
    MyService myService;
    public  Login(MeterRegistry meterRegistry,MyService myService){
        this.meterRegistry=meterRegistry;
        this.myService=myService;
        okCounter = meterRegistry.counter("platform_userlogin_ok", "type", "ok"); // 1 - create a counter
        failCounter = Counter.builder("platform_userlogin_fail")    // 2 - create a counter using the fluent API
                .tag("type", "fail")
                .description("The number of fail logins")
                .register(meterRegistry);
    }
    @RequestMapping(value = {"/demoapp"})
    @Timed(description = "deoapp")
    public Object info() throws InterruptedException {
        if (Math.random()*10>1){
            // ok
            okCounter.increment();
            return myService.fetchUserinfo();
        }else{
            // fail
            failCounter.increment();
            return myService.fetchUserinfo();
        }
    }
}
  • 运行效果

接口请求


metrics


说明

不太好的地方是默认对于prometheus 包装的MeterRegistry并不如golang 或者其他语言prometheus metrics 定义的那么方便(尤其是label 的处理上)
但是总的来说还都是比较简单的,基于prometheus 灵活的能力,我们可以比较方便的分析业务指标,如果真的需要自定义扩展的metrics 推荐使用
MeterBinder 接口以及Meter进行扩展,以下包含了一个参考例子

参考资料

https://docs.spring.io/spring-metrics/docs/current/public/prometheus
https://blog.autsoft.hu/defining-custom-metrics-in-a-spring-boot-application-using-micrometer/
https://www.atlantbh.com/custom_metrics_micrometer_prometheus_spring_boot_actuator/

原文地址:https://www.cnblogs.com/rongfengliang/p/13750974.html