Prometheus 中文名称为普罗米修斯,受启发于Google的Brogmon监控系统,从2012年开始由前Google工程师在Soundcloud以开源软件的形式进行研发,2016年6月发布1.0版本。Prometheus 能够看做是 Google 内部监控系统 Borgmon 的一个实现java
首先了解下 prometheus 架构图web
目前,监控系统采集指标有两种方式,一种是『推』,另外一种就是『拉』:正则表达式
推的表明有 ElasticSearch,InfluxDB,OpenTSDB 等,须要你从程序中将指标使用 TCP,UDP 等方式推送至相关监控应用,只是使用 TCP 的话,一旦监控应用挂掉或存在瓶颈,容易对应用自己产生影响,而使用 UDP 的话,虽然不用担忧监控应用,可是容易丢数据。spring
拉的表明,主要表明就是 Prometheus,让咱们不用担忧监控应用自己的状态。并且能够利用 DNS-SRV 或者 Consul 等服务发现功能就能够自动添加监控。架构
prometheus 监控应用的方式很是简单,只须要进程暴露了一个用于获取当前监控样本数据的HTTP访问地址。这样的一个程序称为Exporter,Exporter的实例称为一个Target。Prometheus经过轮训的方式定时从这些Target中获取监控数据样本,对于java 应用来说,只须要暴露一个包含监控数据的http访问地址便可,固然提供的数据须要知足必定的格式,这个格式就是 Metrics 格式app
metircs 的格式很是简单ide
metric name>{<label name>=<label value>, ...}
主要分为三个部分
各个部分需符合相关的正则表达式
metric name:指标的名称,主要反映被监控样本的含义 a-zA-Z_:*
label name: 标签 反映了当前样本的特征维度 [a-zA-Z0-9_]*
label value: 各个标签的值,不限制格式
须要注意的是,label value 最好使用枚举值,而不要使用无限制的值,好比用户 ID,Email 等,否则会消耗大量内存,也不符合指标采集的意义spring-boot
Prometheus定义了4中不一样的指标类型(metric type):Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要)。
Counter:只增不减的计数器
Gauge:可增可减的仪表盘
Histogram:直方图,内置分析样本的分布状况
Summary:摘要 自定义样本分布状况ui
prometheus 官方提供了spring boot 的依赖,可是该客户端已经不支持spring boot 2url
<dependency> <groupId>io.prometheus</groupId> <artifactId>simpleclient_spring_boot</artifactId> <version>0.4.0</version> </dependency>
因为 spring boot 2 的actuator 使用了 Micrometer 进行监控数据统计,
而Micrometer 提供了prometheus 支持,咱们可使用 micrometer-registry-prometheus 来集成 spring boot 2
加入相应依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-core</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency>
若是要统计http 请求的总数量,咱们能够直接使用prometheus 提供的 Counter 类
首先咱们注册一个 Counter 实例到spring 容器
@Bean public Counter requestTotalCountCollector(){ return Counter.build() .name("http_requests_total") .labelNames("path", "method", "code") .help("http请求总计数").register(collectorRegistry); }
继承HandlerInterceptorAdapter ,声明一个拦截器
public class PrometheusInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
在 prehandle 中 执行
requestTotalCountCollector.labels(requestURI, method,code).inc();
在配置文件 applicaion.yml 中启用metrics,prometheus监控
management: metrics: export: prometheus: enabled: true endpoint: metrics: enabled: true prometheus: enabled: true endpoints: web: exposure: include: ["prometheus","health"]
启动项目,访问路径下的 /actuator/prometheus,便可看到监控项
自定义一个metrics 收集器
只须要继承 prometheus 的 Collector,重写抽象方法collect
public class RequestTimeCollector extends Collector{ @Override public List<MetricFamilySamples> collect() { } }
注册RequestTimeCollector 到 spring 容器
@Bean @Primary public RequestTimeCollector requestTimeCollector(){ return new RequestTimeCollector("request_time","接口请求时间",Arrays.asList("url","method", "status")).register(collectorRegistry); }
声明一个around 切面拦截controller方法
@Around("execution(* com.xxx.controller..*.*(..))") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { try { requestTimeCollector.setValue(diff, uri, method, String.valueOf(200)); return proceed; } catch (Throwable throwable) { if (throwable instanceof BaseException) { requestTimeCollector.setValue(diff, uri, method, String.valueOf(statEnum.key())); } throw throwable; } } }
启动项目,访问路径下的 /actuator/prometheus,便可看到监控项