application.ymlio.micrometer micrometer-registry-prometheusorg.springframework.boot spring-boot-actuator-autoconfigure
management:
endpoints:
web:
exposure:
include: '*'
metrics:
tags:
application: ${spring.appliclation.name}
spring.appliclation.name 这个是项目名称 自己定义
*Application.java 项目启动类 添加下面方法
@Bean MeterRegistryCustomizerconfigurer( @Value("${spring.application.name}") String applicationName) { return (registry) -> registry.config().commonTags("application", applicationName); }
commonController.java 提供一个访问接口 用于prometheus 获取指标数据
@RestController
public class CommonController {
@GetMapping(value="/metrics")
public void metrics(HttpServletResponse response) throws IOException {
response.sendRedirect("/actuator/prometheus");
}
}
aop 埋点
package com.ifeng.filter;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;
@Component
@Aspect
@Slf4j
public class AspectAop {
@Pointcut("execution(public * com.ifeng.controller.*.*(..))") // 对所有controller总的方法做切面
public void pointCut(){
}
@Autowired
MeterRegistry registry;
private Counter httpRpcCount; // 统计调用次数
private Timer httpRpcTimer; // 统计调用耗时
ThreadLocal localStartTime=new ThreadLocal<>();
@Before(value = "pointCut()")
public void before(JoinPoint joinPoint) {
registry.counter("http_rpc_total").increment(); // 统计调用次数
localStartTime.set(System.currentTimeMillis()); // 用于记录某次调用开始时间
}
@AfterReturning(returning = "returnVal",pointcut = "pointCut()")
public void doAfterReturning(Object returnVal){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String sourceFrom = request.getHeader("sourceFrom"); // header中添加一个来源参数,标识调用方
String uri = request.getRequestURI(); // 访问的地址方法是哪一个
long duration = System.currentTimeMillis() - localStartTime.get(); // 计算耗时
// http_rpc_success_duration 这个指标 访问的地址是什么,来源是哪里
httpRpcTimer=registry.timer("http_rpc_success_duration","uri",uri,"sourceFrom", StringUtils.isNotBlank(sourceFrom)?sourceFrom:"default");
httpRpcTimer.record(duration,TimeUnit.MILLISECONDS);// 记录耗时
}
// 调用异常时 也记录
@AfterThrowing(throwing="obj",pointcut = "pointCut()")
public void doAfterThrowing(Throwable obj){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String sourceFrom = request.getHeader("sourceFrom");
String uri = request.getRequestURI();
long duration = System.currentTimeMillis() - localStartTime.get();
httpRpcTimer=registry.timer("http_rpc_error_duration","uri",uri,"sourceFrom",StringUtils.isNotBlank(sourceFrom)?sourceFrom:"default");
httpRpcTimer.record(duration,TimeUnit.MILLISECONDS);
}
}
registry.timer 耗时统计 ,每次都会新建一个,第一个参数是指标名称 ,后边的参数是补充的数据
体现在grafana ,会在指标后自动天见 seconds_count seconds_sum seconds_max ,分别表示 调用次数,调用总耗时 ,调用最大耗时
rate(http_rpc_success_duration_seconds_sum{application=“ai_news_tencents”,sourceFrom="KaTeX parse error: Expected 'EOF', got '}' at position 14: {sourceFrom}"}̲[1m])/rate(http…{sourceFrom}"}[1m])*1000



