在应用中内置Prometheus支持

本小节将以Spring Boot为例,介绍如何在应用代码中集成client_java。

添加Prometheus Java Client相关的依赖:

dependencies {
    compile 'io.prometheus:simpleclient:0.0.24'
    compile "io.prometheus:simpleclient_spring_boot:0.0.24"
    compile "io.prometheus:simpleclient_hotspot:0.0.24"
}

通过注解@EnablePrometheusEndpoint启用Prometheus Endpoint,这里同时使用了simpleclient_hotspot中提供的DefaultExporter。该Exporter会在metrics endpoint中统计当前应用JVM的相关信息:

@SpringBootApplication
@EnablePrometheusEndpoint
public class SpringApplication implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }

    @Override
    public void run(String... strings) throws Exception {
        DefaultExports.initialize();
    }
}

默认情况下Prometheus暴露的metrics endpoint为 /prometheus,可以通过endpoint配置进行修改:

启动应用程序访问http://localhost:8080/metrics可以看到以下输出内容:

添加拦截器,为监控埋点做准备

除了获取应用JVM相关的状态以外,我们还可能需要添加一些自定义的监控Metrics实现对系统性能,以及业务状态进行采集,以提供日后优化的相关支撑数据。首先我们使用拦截器处理对应用的所有请求。

继承WebMvcConfigurerAdapter类并复写addInterceptors方法,对所有请求/**添加拦截器

PrometheusMetricsInterceptor继承自HandlerInterceptorAdapter,通过复写父方法preHandle和afterCompletion可以拦截一个HTTP请求生命周期的不同阶段:

自定义监控指标

一旦PrometheusMetricsInterceptor能够成功拦截和处理请求之后,我们就可以使用client java自定义多种监控指标。

计数器可以用于记录只会增加不会减少的指标类型,比如记录应用请求的总量(http_requests_total),cpu使用时间(process_cpu_seconds_total)等。 一般而言,Counter类型的metrics指标在命名中我们使用_total结束。

使用Counter.build()创建Counter类型的监控指标,并且通过name()方法定义监控指标的名称,通过labelNames()定义该指标包含的标签。最后通过register()将该指标注册到Collector的defaultRegistry中中。

在afterCompletion方法中,可以获取到当前请求的请求路径、请求方法以及状态码。 这里通过labels指定了当前样本各个标签对应的值,最后通过.inc()计数器+1:

通过指标io_namespace_http_requests_total我们可以实现:

  • 查询应用的请求总量

  • 查询每秒Http请求量

  • 查询当前应用请求量Top N的URI

使用Gauge可以反映应用的当前状态,例如在监控主机时,主机当前空闲的内容大小(node_memory_MemFree),可用内存大小(node_memory_MemAvailable)。或者容器当前的CPU使用率,内存使用率。这里我们使用Gauge记录当前应用正在处理的Http请求数量。

通过指标io_namespace_http_inprogress_requests我们可以直接查询应用当前正在处理中的Http请求数量:

Histogram主要用于在指定分布范围内(Buckets)记录大小(如http request bytes)或者事件发生的次数。以请求响应时间requests_latency_seconds为例。

Histogram会自动创建3个指标,分别为:

  • 事件发生总次数: basename_count

  • 所有事件产生值的大小的总和: basename_sum

  • 事件产生的值分布在bucket中的次数: basename_bucket{le="上包含"}

Summary和Histogram非常类型相似,都可以统计事件发生的次数或者发小,以及其分布情况。Summary和Histogram都提供了对于事件的计数_count以及值的汇总_sum。 因此使用_count,和_sum时间序列可以计算出相同的内容,例如http每秒的平均响应时间:rate(basename_sum[5m]) / rate(basename_count[5m])。同时Summary和Histogram都可以计算和统计样本的分布情况,比如中位数,9分位数等等。其中 0.0<= 分位数Quantiles <= 1.0。

不同在于Histogram可以通过histogram_quantile函数在服务器端计算分位数,而Sumamry的分位数则是直接在客户端进行定义。因此对于分位数的计算。 Summary在通过PromQL进行查询时有更好的性能表现,而Histogram则会消耗更多的资源。相对的对于客户端而言Histogram消耗的资源更少。

使用Summary指标,会自动创建多个时间序列:

  • 事件发生总的次数

  • 事件产生的值的总和

  • 事件产生的值的分布情况

使用Collector暴露其它指标

除了在拦截器中使用Prometheus提供的Counter,Summary,Gauage等构造监控指标以外,我们还可以通过自定义的Collector实现对相关业务指标的暴露。例如,我们可以通过自定义Collector直接从应用程序的数据库中统计监控指标.

CustomExporter集成自io.prometheus.client.Collector,在调用Collector的register()方法后,当访问/metrics时,则会自动从Collector的collection()方法中获取采集到的监控指标。

由于这里CustomExporter存在于Spring的IOC容器当中,这里可以直接访问业务代码,返回需要的业务相关的指标。

这里也可以使用CounterMetricFamily,SummaryMetricFamily声明其它的指标类型。

Last updated