2019独角兽企业重金招聘Python工程师标准>>>
由于spring boot的metrics与prometheus的metrics在格式上并不兼容.前者是json格式输出,后者是text格式输出.
在使用prometheus对服务或者方法进行监控的时候, 需要对spring boot metrics进行转换,或者自己增加prometheus的metrics信息. 本文通过创建自定义注解的形式,引入prometheus, 只需要在被监控的方法外启用注解即可.
引入依赖
io.prometheus
simpleclient_spring_boot
0.0.26
- 1
- 2
- 3
- 4
- 5
启动类增加注解
@SpringBootApplication
@EnablePrometheusEndpoint
@EnableSpringBootMetricsCollector
public class Application extends SpringBootServletInitializer {
@Override
protected ApplicationBuilder configure(
SpringApplicationBuilder application) {
return application.sources(Application.class);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
自定义注解
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PrometheusMetrics {
/**
* 默认为空,程序使用method signature作为Metric name
* 如果name有设置值,使用name作为Metric name
* @return
*/
String name() default "";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
创建Aspect , 对注解方法增加Metrics记录
@Aspect
@Component
@Slf4j
public class PrometheusMetricsAspect {
private static final Counter requestTotal = Counter.build().name("couter_all").labelNames("api").help
("total request couter of api").register();
private static final Counter requestError = Counter.build().name("couter_error").labelNames("api").help
("response Error couter of api").register();
private static final Histogram histogram = Histogram.build().name("histogram_consuming").labelNames("api").help
("response consuming of api").register();
@Pointcut("@annotation(com.ubbor.common.aspect.PrometheusMetrics)")
public void pcMethod() {
}
@Around(value="pcMethod() && @annotation(annotation)")
public Object MetricsCollector(ProceedingJoinPoint joinPoint, PrometheusMetrics annotation) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
PrometheusMetrics prometheusMetrics = methodSignature.getMethod().getAnnotation(PrometheusMetrics.class);
if (prometheusMetrics != null) {
String name;
if (StringUtil.isNotEmpty(prometheusMetrics.name()) ){
name = prometheusMetrics.name();
}else{
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
name = request.getRequestURI();
}
requestTotal.labels(name).inc();
Histogram.Timer requestTimer = histogram.labels(name).startTimer();
Object object;
try {
object = joinPoint.proceed();
} catch (Exception e) {
requestError.labels(name).inc();
throw e;
} finally {
requestTimer.observeDuration();
}
return object;
} else {
return joinPoint.proceed();
}
}
}
- 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
给需要监控的方法增加自定义注解
@PrometheusMetrics
@RequestMapping(value = "/test", method = RequestMethod.POST)
@ResponseBody
public ResponseMessage execute (RequestMessage request) throws Exception {
//do something
}
- 1
- 2
- 3
- 4
- 5
- 6
增加配置
spring.metrics.servo.enabled=false
- 1
去掉重复的metrics,不然在prometheus的控制台的targets页签里,会一直显示此endpoint为down状态
检查输出
http://localhost:9001/prometheus
参考资料
https://prometheus.io/docs/introduction/getting_started
https://github.com/prometheus/docs/blob/master/content/docs/operating/configuration.md