Prometheus 4种 Metrics类型


原文链接: Prometheus 4种 Metrics类型

Metrics,谷歌翻译就是度量的意思。当我们需要为某个系统某个服务做监控、做统计,就需要用到Metrics。

举个栗子,一个图片压缩服务:

每秒钟的请求数是多少(TPS)?
平均每个请求处理的时间?
请求处理的最长耗时?
等待处理的请求队列长度?

又或者一个缓存服务:

缓存的命中率?
平均查询缓存的时间?

基本上每一个服务、应用都需要做一个监控系统,这需要尽量以少量的代码,实现统计某类数据的功能。

Metric Registries

MetricRegistry类是Metrics的核心,它是存放应用中所有metrics的容器。也是我们使用 Metrics 库的起点。

MetricRegistry registry = new MetricRegistry();

每一个 metric 都有它独一无二的名字,Metrics 中使用句点名字,如 com.example.Queue.size。当你在 com.example.Queue 下有两个 metric 实例,可以指定地更具体:com.example.Queue.requests.size 和 com.example.Queue.response.size 。使用MetricRegistry类,可以非常方便地生成名字。

MetricRegistry.name(Queue.class, "requests", "size")
MetricRegistry.name(Queue.class, "responses", "size")

Metrics 数据展示

Metircs 提供了 Report 接口,用于展示 metrics 获取到的统计数据。metrics-core中主要实现了四种 reporter: JMX, console, SLF4J, 和 CSV。 在本文的例子中,我们使用 ConsoleReporter 。

五种 Metrics 类型

Gauges

最简单的度量指标,只有一个简单的返回值,例如,我们想衡量一个待处理队列中任务的个数,代码如下:

-- Gauges ------------------------------------------------
com.alibaba.wuchong.metrics.GaugeTest.queue.size

         value = 6

其中第7行和第8行添加了ConsoleReporter,可以每秒钟将度量指标打印在屏幕上,理解起来会更清楚。

但是对于大多数队列数据结构,我们并不想简单地返回queue.size(),因为java.util和java.util.concurrent中实现的#size()方法很多都是 O(n) 的复杂度,这会影响 Gauge 的性能。

Counters

Counter 就是计数器,Counter 只是用 Gauge 封装了 AtomicLong 。我们可以使用如下的方法,使得获得队列大小更加高效。

-- Counters ----------------------------------------------
java.util.Queue.pending-jobs.size

         count = 5

Meters

Meter度量一系列事件发生的速率(rate),例如TPS。Meters会统计最近1分钟,5分钟,15分钟,还有全部时间的速率。
-- Meters ------------------------------------------------
com.alibaba.wuchong.metrics.MeterTest.request.tps

         count = 134
     mean rate = 2.13 events/second
 1-minute rate = 2.52 events/second
 5-minute rate = 3.16 events/second
15-minute rate = 3.32 events/second

注:非常像 Unix 系统中 uptime 和 top 中的 load。

Histograms

Histogram统计数据的分布情况。比如最小值,最大值,中间值,还有中位数,75百分位, 90百分位, 95百分位, 98百分位, 99百分位, 和 99.9百分位的值(percentiles)。

比如request的大小的分布:
-- Histograms --------------------------------------------
java.util.Queue.queue.histogram

         count = 56
           min = 1122
           max = 99650
          mean = 48735.12
        stddev = 28609.02
        median = 49493.00
          75% <= 72323.00
          95% <= 90773.00
          98% <= 94011.00
          99% <= 99650.00
        99.9% <= 99650.00

Timers

Timer其实是 Histogram 和 Meter 的结合, histogram 某部分代码/调用的耗时, meter统计TPS。
-- Timers ------------------------------------------------
com.alibaba.wuchong.metrics.TimerTest.get-latency

         count = 38
     mean rate = 1.90 calls/second
 1-minute rate = 1.66 calls/second
 5-minute rate = 1.61 calls/second
15-minute rate = 1.60 calls/second
           min = 13.90 milliseconds
           max = 988.71 milliseconds
          mean = 519.21 milliseconds
        stddev = 286.23 milliseconds
        median = 553.84 milliseconds
          75% <= 763.64 milliseconds
          95% <= 943.27 milliseconds
          98% <= 988.71 milliseconds
          99% <= 988.71 milliseconds
        99.9% <= 988.71 milliseconds

其他

初次之外,Metrics还提供了 HealthCheck 用来检测某个某个系统是否健康,例如数据库连接是否正常。还有Metrics Annotation,可以很方便地实现统计某个方法,某个值的数据。感兴趣的可以点进链接看看。
使用经验总结

一般情况下,当我们需要统计某个函数被调用的频率(TPS),会使用Meters。当我们需要统计某个函数的执行耗时时,会使用Histograms。当我们既要统计TPS又要统计耗时时,我们会使用Timers。

本文将介绍Prometheus下的四种基本数据结构,以及其使用场景。

上一篇文章中分享了在Kubernetes部署Prometheus的内容,Prometheus除了监控数据采集,存储,查询以外。也提供了非常方便的扩展接口,可以方便用户根据自己的业务实现自己的数据采集Exporter。 再实现自定义Exporter或者在现有应用上扩展API接口支持Prometheus采集数据之前,我们需要先了解一下Prometheus下的度量指标数据结构基本类型

Prometheus metric类型

Prometheus的Client Library提供度量的四种基本类型包括:Counter,Gauge,Histogram,Summary。当访问Exporter的/metrics API地址时我们可以看到类似于一下返回值,其中HELP用于说明度量类型,TYPE用于数据类型说明。

# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 255.477922
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
process_open_fds 312.0

需要注意的是,虽然Prometheus Client Library可以定义不同的数据类型,但是Prometheus Server在获取到这些监控数据后并没有使用它们的类型(Type)信息而直接将这些数据扁平处理,并且无区别的保存到时序数据库当中。 因此这四种数据类型主要是提供一些参考,用于不同的度量数据场景

Counter计数器

Counter类型,Counter类型好比计数器,用于统计类似于:CPU时间,API访问总次数,异常发生次数等等场景。这些指标的特点就是增加不减少。

Example: 容器CPU使用率

在使用cAdvisor采集容器数据时,我们会得到监控指标container_cpu_user_seconds_total,该指标的的数据类型为Counter用户反映当前容器在各个CPU内核上已经使用的CPU总时间。

通过Prometheus直接查询该指标我们会得到以下数据

container_cpu_usage_seconds_total{beta_kubernetes_io_arch="amd64",beta_kubernetes_io_os="linux",container_name="mysql",cpu="cpu03",id="/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod74ab5e96_6209_11e7_9990_00163e122a49.slice/docker-fb332c4ede82562be6eaebe3eef6376d3f37b3402a7fd570c7c95f8963012c0b.scope",image="docker.io/mysql@sha256:d178dffba8d81afedc251498e227607934636e06228ac63d58b72f9e9ec271a6",instance="dev-4",job="kubernetes-nodes",kubernetes_io_hostname="dev-4",name="k8s_mysql_go-todo-mysql-3723120250-vf8wx_default_74ab5e96-6209-11e7-9990-00163e122a49_0",namespace="default",pod_name="go-todo-mysql-3723120250-vf8wx"}
container_cpu_usage_seconds_total{beta_kubernetes_io_arch="amd64",beta_kubernetes_io_os="linux",container_name="mysql",cpu="cpu01",id="/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod74ab5e96_6209_11e7_9990_00163e122a49.slice/docker-fb332c4ede82562be6eaebe3eef6376d3f37b3402a7fd570c7c95f8963012c0b.scope",image="docker.io/mysql@sha256:d178dffba8d81afedc251498e227607934636e06228ac63d58b72f9e9ec271a6",instance="dev-4",job="kubernetes-nodes",kubernetes_io_hostname="dev-4",name="k8s_mysql_go-todo-mysql-3723120250-vf8wx_default_74ab5e96-6209-11e7-9990-00163e122a49_0",namespace="default",pod_name="go-todo-mysql-3723120250-vf8wx"}

如果使用图形化查询我们可以看出

因此当我们需要统计容器CPU的使用率时,我们需要使用rate()函数计算该Counter在过去一段时间内在每一个时间序列上的每秒的平均增长率

rate(container_cpu_user_seconds_total[5m]) * 100

Gauge仪表盘

Gauge类型,英文直译的话叫“计量器”,但是和Counter的翻译太类似了,因此我个人更喜欢使用”仪表盘“这个称呼。仪表盘的特点就是数值是可以增加或者减少的。因此Gauge适合用于如:当前内存使用率,当前CPU使用率,当前温度,当前速度等等一系列的监控指标。

Example:主机负载信息

在使用NodeExporter时,指标node_load1可以反映当前主机的负载情况,而其类型则是Gauge,因此在查询主机负载变化时比较简单,直接使用node_load1即可查询出当前所有主机的负载情况

node_load1{app="node-exporter",instance="192.168.2.2:9100",job="kubernetes-service-endpoints",kubernetes_name="node-exporter",kubernetes_namespace="default",name="node-exporter",nodeIp="192.168.2.2:9100"}
node_load1{app="node-exporter",instance="192.168.2.3:9100",job="kubernetes-service-endpoints",kubernetes_name="node-exporter",kubernetes_namespace="default",name="node-exporter",nodeIp="192.168.2.3:9100"}

Histogram柱状图

Histogram这个比较直接柱状图图,更多的是用于统计一些数据分布的情况,用于计算在一定范围内的分布情况,同时还提供了度量指标值的总和。

Example:
以Kubernates的API Server度量指标apiserver_request_latencies为例,该指标反映了Kubernates的API请求响应延迟时间。该指标会在一次监控数据抓取过程中返回2中Metrics Key

apiserver_request_latencies_bucket
apiserver_request_latencies_count
apiserver_request_latencies_sum

apiserver_request_latencies_bucket反映在各个API响应延迟范围(le)内总数

apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="+Inf",resource="podpresets",verb="WATCH"}	773
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="500000",resource="endpoints",verb="DELETE"}	85
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="1e+06",resource="configmaps",verb="PUT"}	1
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="1e+06",resource="daemonsets",verb="WATCHLIST"}	0
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="2e+06",resource="replicationcontrollers",verb="GET"}	6
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="125000",resource="deployments",verb="PATCH"}	12
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="+Inf",resource="configmaps",verb="DELETE"}	9
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="125000",resource="replicasets",verb="GET"}	1331
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="+Inf",resource="persistentvolumes",verb="LIST"}	3

apiserver_request_latencies_count反映对各个资源API的请求次数

apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="replicasets",verb="PUT"}	3030
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="deployments",verb="PUT"}	2454
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="clusterroles",verb="WATCH"}	1527
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="replicationcontrollers",verb="WATCHLIST"}	7
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="clusterroles",verb="POST"}	42
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="resourcequotas",verb="LIST"}	304
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="pods",verb="DELETE"}	913

而apiserver_request_latencies_sum则反映出对各个资源API操作延迟时间的总量

apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="replicationcontrollers",verb="LIST"}	554991
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="clusterroles",verb="LIST"}	33586061
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="configmaps",verb="DELETE"}	16466
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="pods",verb="WATCH"}	3430725671235
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="secrets",verb="LIST"}	5843
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="nodes",verb="LIST"}	92849
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="persistentvolumes",verb="LIST"}	9302
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="serviceaccounts",verb="WATCH"}	1378625982766

在Exporter获取的度量指标当中通常会以一下形式表现:

<base_name>_bucket{ label1=value1, label2=value2 }

Summary概要

Summary摘要和Histogram柱状图比较类似,主要用于计算在一定时间窗口范围内度量指标对象的总数以及所有对量指标值的总和。

例如:

apiserver_request_latencies_summary
apiserver_request_latencies_summary_count
apiserver_request_latencies_summary_sum

小结

如第一个项目而言Prometheus Server当前版本在采集数据时并没有使用metrics的数据类型,数据类型更多是Client进行参考,根据不同的场景选择不同的数据类型

`