## Prometheus查詢
---
Prometheus提供一個函數式的表達式語言,可以使用戶實時地查找和聚合時間序列數據。表達式計算結果可以在圖表中展示,也可以在Prometheus表達式瀏覽器中以表格形式展示,或者作為數據源, 以HTTP API的方式提供給外部系統使用。
### examples
這個文檔僅供參考, 這里先舉幾個容易上手的例子。
### 表達式語言數據類型
在Prometheus的表達式語言中,任何表達式或者子表達式都可以歸為四種類型:
- `instant vector` 瞬時向量 - 它是指在同一時刻,抓取的所有度量指標數據。這些度量指標數據的key都是相同的,也即相同的時間戳。
- `range vector` 范圍向量 - 它是指在任何一個時間范圍內,抓取的所有度量指標數據。
- `scalar` 標量 - 一個簡單的浮點值
- `string` 字符串 - 一個當前沒有被使用的簡單字符串
依賴于使用場景(例如:圖表 vs. 表格),根據用戶所寫的表達式,僅僅只有一部分類型才適用這種表達式。例如:瞬時向量類型是唯一可以直接在圖表中使用的。
### Literals
#### 字符串
字符串可以用單引號、雙引號或者反引號表示
PromQL遵循與Go相同的轉義規則。在單引號,雙引號中,反斜杠成為了轉義字符,后面可以跟著a, b, f, n, r, t, v或者\。 可以使用八進制(\nnn)或者十六進制(\xnn, \unnnn和\Unnnnnnnn)提供特定字符。
在反引號內不處理轉義字符。與Go不同,Prom不會丟棄反引號中的換行符。例如:
> "this is a string"
> 'these are unescaped: \n \\ \t'
> `these are not unescaped: \n ' " \t"'`
### 浮點數
標量浮點值可以直接寫成形式[-](digits)[.(digits)]。
> -2.43
### 時間序列選擇器
#### 即時向量選擇器
瞬時向量選擇器可以對一組時間序列數據進行篩選,并給出結果中的每個結果鍵值對(時間戳-樣本值): 最簡單的形式是,只有一個度量名稱被指定。在一個瞬時向量中這個結果包含有這個度量指標名稱的所有樣本數據鍵值對。
下面這個例子選擇所有時間序列度量名稱為`http_requests_total`的樣本數據:
> http_requests_total
通過在度量指標后面增加{}一組標簽可以進一步地過濾這些時間序列數據。
下面這個例子選擇了度量指標名稱為`http_requests_total`,且一組標簽為`job=prometheus`, `group=canary`:
> http_requests_total{job="prometheus",group="canary"}
可以采用不匹配的標簽值也是可以的,或者用正則表達式不匹配標簽。標簽匹配操作如下所示:
- `=`: 精確地匹配標簽給定的值
- `!=`: 不等于給定的標簽值
- `=~`: 正則表達匹配給定的標簽值
- `!=`: 給定的標簽值不符合正則表達式
例如:度量指標名稱為`http_requests_total`,正則表達式匹配標簽`environment`為`staging, testing, development`的值,且http請求方法不等于`GET`。
> http_requests_total{environment=~"staging|testing|development", method!="GET"}
匹配空標簽值的標簽匹配器也可以選擇沒有設置任何標簽的所有時間序列數據。正則表達式完全匹配。
向量選擇器必須指定一個度量指標名稱或者至少不能為空字符串的標簽值。以下表達式是非法的:
> {job=~".*"} #Bad!
上面這個例子既沒有度量指標名稱,標簽選擇器也可以正則匹配空標簽值,所以不符合向量選擇器的條件
相反地,下面這些表達式是有效的,第一個一定有一個字符。第二個有一個有用的標簽method
> {job=~".+"} # Good!
> {job=~".*", method="get"} # Good!
標簽匹配器能夠被應用到度量指標名稱,使用`__name__`標簽篩選度量指標名稱。例如:表達式`http_requests_total`等價于`{__name__="http_requests_total"}`。 其他的匹配器,如:`= ( !=, =~, !~)`都可以使用。下面的表達式選擇了度量指標名稱以`job:`開頭的時間序列數據:
> {__name__=~"^job:.*"} #
#### 范圍向量選擇器
范圍向量類似瞬時向量, 不同在于,它們從當前實例選擇樣本范圍區間。在語法上,時間長度被追加在向量選擇器尾部的方括號[]中,用以指定對于每個樣本范圍區間中的每個元素應該抓取的時間范圍樣本區間。
時間長度有一個數值決定,后面可以跟下面的單位:
- `s` - seconds
- `m` - minutes
- `h` - hours
- `d` - days
- `w` - weeks
- `y` - years
在下面這個例子中, 選擇過去5分鐘內,度量指標名稱為`http_requests_total`, 標簽為`job="prometheus"`的時間序列數據:
> http_requests_total{job="prometheus"}[5m]
#### 偏移修飾符
這個`offset`偏移修飾符允許在查詢中改變單個瞬時向量和范圍向量中的時間偏移
例如,下面的表達式返回相對于當前時間的前5分鐘時的時刻, 度量指標名稱為`http_requests_total`的時間序列數據:
> http_requests_total offset 5m
注意:`offset`偏移修飾符必須直接跟在選擇器后面,例如:
> sum(http_requests_total{method="GET"} offset 5m) // GOOD.
然而,下面這種情況是不正確的
> sum(http_requests_total{method="GET"}) offset 5m // INVALID.
offset偏移修飾符在范圍向量上和瞬時向量用法一樣的。下面這個返回了相對于當前時間的前一周時,過去5分鐘的度量指標名稱為`http_requests_total`的速率:
> rate(http_requests_total[5m] offset 1w)
### 操作符
Prometheus支持二元和聚合操作符。詳見[表達式語言操作符](https://prometheus.io/docs/querying/operators/)
### 函數
Prometheus提供了一些函數列表操作時間序列數據。詳見[表達式語言函數](https://prometheus.io/docs/querying/functions/)
### 陷阱
#### 插值和陳舊
當運行查詢后,獨立于當前時刻被選中的時間序列數據所對應的時間戳,這個時間戳主要用來進行聚合操作,包括`sum`, `avg`等,大多數聚合的時間序列數據所對應的時間戳沒有對齊。由于它們的獨立性,我們需要在這些時間戳中選擇一個時間戳,并已這個時間戳為基準,獲取小于且最接近這個時間戳的時間序列數據。
如果5分鐘內,沒有獲取到任何的時間序列數據,則這個時間戳不會存在。那么在圖表中看到的數據都是在當前時刻5分鐘前的數據。
```
注意:差值和陳舊處理可能會發生變化。詳見[https://github.com/prometheus/prometheus/issues/398](https://github.com/prometheus/prometheus/issues/398)和[https://github.com/prometheus/prometheus/issues/581](https://github.com/prometheus/prometheus/issues/581)
#### 避免慢查詢和高負載
如果一個查詢需要操作非常大的數據量,圖表繪制很可能會超時,或者服務器負載過高。因此,在對未知數據構建查詢時,始終需要在Prometheus表達式瀏覽器的表格視圖中構建查詢,直到結果是看起來合理的(最多為數百個,而不是數千個)。只有當你已經充分過濾或者聚合數據時,才切換到圖表模式。如果表達式的查詢結果仍然需要很長時間才能繪制出來,則需要通過記錄規則重新清洗數據。
像`api_http_requests_total`這樣簡單的度量指標名稱選擇器,可以擴展到具有不同標簽的數千個時間序列中,這對于Prometheus的查詢語言是非常重要的。還要記住,聚合操作即使輸出的結果集非常少,但是它會在服務器上產生負載。這類似于關系型數據庫查詢可一個字段的總和,總是非常緩慢。
```