# Metrics

## Metrics简介

上一节安装了Node-Exporter与Prometheus。如果我们访问Node-Exporter的Metrics链接，会看到如下的类似输出（不同版本的Node Exporter可能不会一样）

每一个监控指标之前都会有一段类似于如下形式的信息：

```
# HELP node_cpu_seconds_total Seconds the cpus spent in each mode.
# TYPE node_cpu_seconds_total counter
node_cpu_seconds_total{cpu="0",mode="idle"} 14945.01
node_cpu_seconds_total{cpu="0",mode="iowait"} 1.4
node_cpu_seconds_total{cpu="0",mode="irq"} 0
node_cpu_seconds_total{cpu="0",mode="nice"} 0.02
node_cpu_seconds_total{cpu="0",mode="softirq"} 30.96
node_cpu_seconds_total{cpu="0",mode="steal"} 0
node_cpu_seconds_total{cpu="0",mode="system"} 360.19
node_cpu_seconds_total{cpu="0",mode="user"} 167
node_cpu_seconds_total{cpu="1",mode="idle"} 14962.62
node_cpu_seconds_total{cpu="1",mode="iowait"} 1.42
node_cpu_seconds_total{cpu="1",mode="irq"} 0
node_cpu_seconds_total{cpu="1",mode="nice"} 0
node_cpu_seconds_total{cpu="1",mode="softirq"} 30.56
node_cpu_seconds_total{cpu="1",mode="steal"} 0
node_cpu_seconds_total{cpu="1",mode="system"} 354.76
node_cpu_seconds_total{cpu="1",mode="user"} 164.88
```

其中HELP用于解释当前指标的含义，TYPE则说明当前指标的数据类型。比如上面的`node_cpu_seconds_total`表示cpu在每一种模式（mode）下的时间（秒），比如第一行`node_cpu_seconds_total{cpu="0",mode="idle"} 14945.01`表示cpu0处于空闲（idle）状态的时间为14945.01秒（从开机到现在）。TYPE表示该指标的类型，这里的counter表示计数器类型，它是累加的，该指标的值会一直变大。

关于指标类型，可以参考附录。

## 根据Metric绘制CPU使用率走势图

对于CPU使用率，我们经常关注的有两点：一是查看当前CPU的使用情况，二是查看CPU一段时间（比如一天）内使用率的走势图。其实，如果我们能计算出来每一个时间点的CPU使用率，然后把这些点连起来，那么就可以得到走势图。

首先我们来介绍一下某个时间点CPU使用率计算方法：CPU是一种不可压缩的资源，我们通常所说的某一时间点CPU使用率为百分之多少，指的是该时间点往前的一个时间段内（比如1分钟），CPU的使用时间与时间段的比例。这个时间段的长度不同，计算出来的某个时间点的CPU使用率也会不同。但是我们一般不关注这种误差，比如top命令查看cpu使用率时默认时间段为3s，可以通过`top -d 10`指定时间段为10s。

第二，我们在描绘走势图时，应该选择哪些时间点？其实，选择哪些时间点关系不大，但每两个时间点的间隔要一样。

上面我们可以根据node-exporter的指标`node_cpu_seconds_total{cpu="0",mode="idle"}`得到cpu0的空闲时间。接下来，我们来介绍如何通过这个指标，描绘CPU0的空闲率走势图。

假设我们没有Prometheus，自已如何写一个监控插件去实现这个功能。首先，这个插件应该需要定时地采集这个指标的数据并保存起来，保存起来的应该是类似于如下的数据：

| timestamp | value |
| --------- | ----- |
| t0        | a     |
| t1        | b     |
| t2        | c     |
| t3        | d     |
| ...       | ...   |

那么，tn时刻cpu0的空闲率计算为

```
(t(n)时刻cpu0的idle值 - t(n-1)时刻cpu0的idle值) / (t(n) - t(n-1))
```

通过这种方法，我们可以求出每个采样点时间CPU0的空闲率，从而描绘出CPU0空闲率的散点图。

其实，Prometheus的原理就是这样，它有一个采样间隔T，每隔时间T就会采集一个样本，然后保存到自已的时序数据库中。我们可以通过Prometheus的PromQL语句直接描绘出cpu0的空闲率的走势图。

在Prometheus的页面上进入Graph，然后输入下面的PromQL语句（关于irate函数请参考《Prometheus内置函数》）

```
irate(node_cpu_seconds_total{cpu="0",mode="idle"}[1m])
```

我们就可以看到cpu0的空闲率走势图，如下

![](https://3339440762-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M69DxRRZI4bEIn73eYR%2Fsync%2F59d3bc1cfcf66b51f9b708308f90b63715207704.png?generation=1588235905287290\&alt=media)

这个图其实就是一个散点图，但是如果我们把它放大，会发现这个图的每一秒上都有数据，但是我们的采样间隔是15s。也就是说，假设Prometheus是在每分钟的hh:mm:00、hh:mm:15、hh:mm:30、hh:mm:45秒采样，那么其他时间点比如hh:mm:50的cpu空闲率应该是多少呢？通过上面图的放大版，或者了解了irate函数后，我们会发现其实hh:mm:50这个点的cpu空闲率的值就是前一个采样点hh:mm:45的cpu空闲率的值。

如果我们把上面Prometheus的页面从Graph切换到Console，再执行上面的PromQL语句，会发现它返回的就是一个值，这个值就是执行PromQL语句这个时间点cpu0的空闲率。而这个时间点不一定是采样时间点，那么它的值其实就是前一个采样时间点的值。

**所以，如果我们要查询当前时间cpu的空闲率，得到的就是前一个采样点时的cpu空闲率**

## Prometheus的API

上面我们是通过Prometheus的UI来查询CPU的空闲率。接下来，我们来介绍如何利用Prometheus的API来查询CPU的空闲率。

Prometheus的API文档可以参考<https://prometheus.io/docs/prometheus/latest/querying/api/>

首先，我们可能只想查询当前时间的CPU空闲率。那么，我们使用瞬时查询（Instant Query）接口。如下：

![](https://3339440762-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M69DxRRZI4bEIn73eYR%2Fsync%2F75f097c35f7f82240b74138ead64a729c67c6871.png?generation=1588235905540063\&alt=media)

即时查询使用的API为`/api/v1/query`，Query参数有query和time，其中query就是PromQL，time是时间戳（如果不指定则默认为该请求的时间戳）。该请求的返回值`data.result.value`是一个瞬时向量（Instant Vector），如上的返回值`[1572523915.645, "0.8906666666666752"]`表示在`1572523915.645`这个时间戳（即发起请求的时间戳）的CPU0的空闲率为`0.8906666666666752`。我们利用命令`date -d @1572523915.645`把时间戳`1572523915.645`换成时间就是`Thu Oct 31 20:11:55 CST 2019`。

第二，如果我们需要描绘一段时间内（比如最近一个小时）的CPU0空间率，那么我们可以使用Range Query（区间查询，或者叫范围查询）。如下：

![](https://3339440762-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M69DxRRZI4bEIn73eYR%2Fsync%2F773ee8de9a1856cd1598e4506f08800ec2e000b5.png?generation=1588235905328557\&alt=media)

区间查询的API为`/api/v1/qeury_range`，Query参数有query、start、end和step。query就是PromQL，start就是开始时间戳，end就是结束时间戳，step就是时间间隔。比如上面的截图中，我们查询`[1572520499, 1572520799]`（`[Thu Oct 31 19:14:59 CST 2019, Thu Oct 31 19:19:59 CST 2019]`）这个时间段内，每隔15秒的CPU0空闲率。它的返回结果如下：

![](https://3339440762-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M69DxRRZI4bEIn73eYR%2Fsync%2Fdca85de508d0accc488cd32ed792a41e74bf9c1d.png?generation=1588235905099066\&alt=media)

`data.result.values`是一个区间向量（Range Vector），即每个时间点和这个时间点对应的值。那么，根据区间向量我们就可以描绘出这个时间段内CPU0的空闲率散点图。

## Reference

* 指标类型：<https://prometheus.io/docs/concepts/metric_types/>
* 指标类型：<https://songjiayang.gitbooks.io/prometheus/content/concepts/data-model.html>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://pshizhsysu.gitbook.io/kubernetes/jian-kong/prometheus/exporter/metrics.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
