rate/increaseFunction Compute結果中為何出現異常的巨大數值?
rate與increase僅適用於遞增類型的指標資料,即指標數值隨時間增長逐漸增大。此處基於Prometheus Engine源碼解釋異常原理,可參考源碼。
下面的截圖中展示了rate與increase函數針對時間視窗內資料點的詳細計算過程:先計算首位兩個數值的差值resultFloat,然後開始遍曆餘下的數值點,若出現數值下降時則會將前一個數值prevValue累加到值resultFloat中,從而造成最終的結果值變得異常巨大。

排查方式:
使用PromQL查詢先確定是否出現數值下降,首先將時間篩選框縮小到出現異常的時間段,並執行以下的PromQL語句(需將“xxxx_metric”更換為真實指標資料),若此查詢的結果集中存在資料點則能夠說明出現了“數值下降”的現象。
Query語句:(xxxx_metric{} - xxxx_metric{} offset 1s) < 0 Step 參數:1s針對出現異常數值的時間軸,可使用SQL方式將原始的異常數值點查詢出來,例如:
* | select *, from_unixtime(__time_nano__/1000000.0) from "時序庫名.prom" where __name__='指標名' and element_at(__labels__, '用於篩選的某個labelKey')='用於篩選的某個labelValue' order by __time_nano__ // 建議在SQL中添加多個 element_at 函數來進一步縮小時間軸範圍。SQL結果集中已按時間戳記排序,可直接觀察到已寫入的原始髒資料點。
已寫入時序資料,使用PromQL為什麼查不到資料?
首先確認下述兩種情境是否存在問題。
情境一:PromQL文法是否正確,時序庫的查詢方塊中會自動提示法解析情況,若存在問題請按照提示修改;

情境二:參見下面的截圖進入時序庫的“自訂分析”頁面,並執行下述的SQL確認對應時間段內有無資料。
此SQL中的
__name__欄位表示MetricName。* | select * from "MetricStore名字.prom" where __name__ = 'demo_api_request_duration_seconds_bucket'

上述兩種情境檢查沒有問題,則可能是Prometheus計算引擎中的特殊的“選點”邏輯和“lookback-delta”機製造成的。
Prometheus計算引擎提供了一種名為PromQL的查詢語言,該語言在執行計算時不一定會將全部資料點都納入計算點,在執行計算前實際還存在一個“選點”過程。PromQL文法所包含的所有運算元、函數、運算子在資料“選點”這個流程上可分成兩類:帶“[1m]、[1h]”等操作符的RangeVectorSelector 和 InstantVectorSelector。
下面分別列舉了幾項包含兩種VectorSelector的PromQL樣本。
RangeVectorSelector:
rate(http_requests_total[5m])
delta(http_requests_total[5m])
count_over_time(http_requests_total[5m])
InstantVector:
http_requests_total
absent(http_requests_total)
count(http_requests_total)RangeVectorSelector的“選點”流程是將“[xx]”操作符所覆蓋時間範圍內的資料點都納入計算,如下圖,操作符“count_over_time ( up [30s] )”表示每次計算時都會將目前時間點及往前30秒的資料點都納入到計算中。

PromQL中的“lookback-delta”機制僅對InstantVectorSelector有效,在“選點”時會根據“lookback-delta”參數值大小往前找特定時間區間,並將最近時間點的資料點作為目前時間點的資料值。在絕大多數情況下,未經處理資料的寫入時間點和查詢時間點是沒有對齊的,在“選點”時會往前回溯n分鐘(SLS預設3分鐘,可通過自訂參數調整,請參見時序指標查詢API),並將最近的資料點作為目前時間點的資料。
下圖樣本中,查詢的startTime為09分28秒,該時間點不存在未經處理資料點,則會往前找到06分28秒,而這段時間都沒有寫入資料,則表示09分28秒沒有選取到資料點。同理,09分43秒則選取了09分40秒的資料點、09分58秒選取了09分55秒的資料點。

由於該機制的特殊性,在“選點”時還存在一種特殊情境:在已經不存在資料的時間點,使用PromQL卻查出了資料。下圖樣本中,10分00秒後已經不存在資料,但10分13秒、10分28秒、10分43秒、12分58秒等時間點都因為“lookback-delta”的機制往前回溯3分鐘並選取到了10分00秒的資料點。

兩類VectorSelector的“選點”邏輯是完全不一致的,而查不到資料通常也和這兩類“選點”邏輯有關係,下面分別對兩類邏輯查不到資料的可能性情境做分析。
RangeVectorSelector
操作符
“[xx]”中表示的時間區間較小,而運算的步長“step”參數較大,可能導致單次計算前的“選點”流程並沒有選取到資料點。例如,原始寫入的指標資料
“up”為每小時(整點)一個點,查詢參數為:startTime: 10:30:00 endTime : 18:30:00 step : 1h query : count_over_time(up[10m])預期會返回7個資料點,而實際的查詢結果為空白,原因分析:PromQL計算邏輯會從startTime開始每間隔step執行一次計算,即在“11:30:00、12:30:00、13:30:00、14:30:00、15:30:00、16:30:00、17:30:00、18:30:00”這些時間點都會計算一次計算,但每次計算前的“選點”僅選取了近10分鐘範圍內所有點,致使每次“選點”都沒有選到資料點。
InstantVectorSelector
“lookback-delta”參數較小,而運算的步長“step”參數較大,可能導致單次計算前的“選點”流程沒有找到最近的資料點。例如,原始寫入的指標資料
“up”為每小時(整點)一個點,查詢參數為:startTime: 10:30:00 endTime : 18:30:00 step : 1h query : count(up)Prometheus中預設的
“lookback-delta”參數為5分鐘,SLS時序庫中預設為3分鐘。在每次計算前的“選點”僅會往前找3分鐘,即在“11:30:00、12:30:00、13:30:00、14:30:00、15:30:00、16:30:00、17:30:00、18:30:00”這些時間點都近會往前找3分鐘,並將時間最近的資料點作為當前時刻的資料值。由於未經處理資料的分布較稀疏,上述幾次“選點”都沒有找到資料點,致使最後的計算結果同樣為空白。
解決方案
調整查詢參數中的
startTime、endTime和step參數,將參數與寫入時間點對齊後,就能夠選取到寫入時間點的資料。例如,下面的查詢會返回7個資料點。在實際的應用情境中,指標資料點採集時刻並不是非常規整的,並且查詢時也並不會刻意去對齊參數,所以不推薦使用此方案。
startTime: 10:00:00 endTime : 18:00:00 step : 1h query : count(up)調小step參數,例如我們將step參數設定為3分鐘,以上述InstantVectorSelector情境為例,一定有多次“選點”能夠選取原始的資料點。此方案是讓“選取”流程變得更密集,以確保能夠選取到原本較稀疏的資料點。
調大“lookback-delta”參數或者調大“[xx]”操作符的數值,調整此兩項參數則是通過擴大“選點”的時間區間,將儘可能多的資料點納入選擇範圍。
特定時間點之後已不再寫入資料,為什麼使用PromQL仍能查出在該時間點之後的資料?
原因與Prometheus計算引擎中的“lookback-delta”機制有關,請參見“lookback-delta”機制。
為什麼查詢結果中資料點的時間與寫入時間不一致?
原因與Prometheus計算引擎中的“lookback-delta”機制有關,請參見“lookback-delta”機制。
針對相同時間範圍,為什麼最新執行結果與歷史執行結果不一致?
存在兩種可能性:
如果時間框選擇的是“相對時間”模式,可能是 start 和 end 參數變化後,計算引擎在執行“lookback-delta”操作時選取到的數值點發生了變化,從而造成前後兩次結果不一致。此現象符合Prometheus標準,屬於正常情況。
如果前後兩次執行相隔較長且查詢的時間範圍也一致,可能是歷史執行時,預期內將參與計算的資料還未到SLS側(寫入資料存在延遲)。前後兩次參與計算的資料不一致造成了結果不一致。若屬於此類現象,可在PromQL語句中使用 offset 文法將查詢區間往前平移一段時間,去除因寫入延遲造成的結果錯誤。
單次Query計算資源超限,請求被拒絕
如果Query請求返回的錯誤中包含了“too many time Series or items,xxxxxx” 、“too many time Series or items in parallelMaster node,xxxxx”等文本提示,則說明該次Query讀取了很大的資料量,已觸發了計算層的記憶體限制。

解決方案
縮小查詢區間。
若強依賴於上述時間範圍的執行時序計算,建議開啟並發計算,參考並發計算配置即可。
vector cannot contain metrics with the same labelset錯誤
原因一:
__labels__欄位值中的LabelName不符合字母序。寫入MetricStore的
__labels__欄位由多組Label (LabelName#$#LabelValue)組成,且所有Label之間使用豎線(|)串連。在時序標識中,要求所有Label按照LabelName的字母序排序。更多資訊,請參見時序標識。當
__labels__欄位值中的LabelName不符合字母序時,會出現該錯誤。您可以通過如下SQL語句確認__labels__欄位值中的LabelName是否按照字母序排序。* | select * from ( select __labels__, array_join(array_sort(split(__labels__, '|')), '|') as rightLabels from "MetricStore名字.prom" where __name__!='' ) where __labels__ != rightLabels原因二:
__labels__欄位值中存在LabelValue為空白問題。在Prometheus Engine中,LabelValue為空白的Label會被視作無效。Prometheus Engine執行計算時會刪除無效Label,因此出現該錯誤。您可以通過下述步驟確認
__labels__欄位值中是否存在LabelValue為空白問題。縮小查詢時間範圍,定位到出現此錯誤的大致時間區間。
執行如下SQL語句。
* | select __labels__ from "MetricStore名字.prom" where __name__!='' and regexp_like(__labels__, '.*#\$#\|.*|.*#\$#$')如果有返回結果,則表示存在LabelValue為空白問題。建議修正資料上報端代碼邏輯,刪除無效Label。
PromQL查詢時缺失Label資訊,但未經處理資料中存在該Label
__labels__欄位值中的LabelName未按照字母序排序時會出現該問題。您可以通過如下SQL語句確認__labels__欄位值中的LabelName是否按照字母序排序。
* | select * from (
select __labels__, array_join(array_sort(split(__labels__, '|')), '|') as rightLabels from "MetricStore名字.prom" where __name__!=''
) where __labels__ != rightLabelsPromQL中涉及by/without計算時,結果不符合預期
__labels__欄位值中的LabelName未按照字母序排序時會出現該問題。您可以通過如下SQL語句確認__labels__欄位值中的LabelName是否按照字母序排序。
* | select * from (
select __labels__, array_join(array_sort(split(__labels__, '|')), '|') as rightLabels from "MetricStore名字.prom" where __name__!=''
) where __labels__ != rightLabels指標探索中沒有資料
可能原因是預設查詢時間範圍內沒有資料。
在選取查詢時間範圍時,確保該時間範圍記憶體在資料。
使用指標探索功能時,為保證響應速度,系統預設查詢範圍為最近5分鐘。

在控制台中,查詢到的時序資料缺失較多時間軸
在Log Service控制台的MetricStore查詢分析頁面中執行查詢時,存在limit參數,該參數會限制SQL查詢或PromQL查詢的返回資料的數量。建議適當調大該參數。

PromQL計算結果中存在Warning資訊
可能原因是在拉取未經處理資料時,因Shard讀取能力上限問題,未將該時間段內的資料讀取完整。建議縮小查詢時間範圍或者分裂Shard提升整體吞吐能力。

exceeded maximum resolution of 11,000 points per timeseries. Try decreasing the query resolution (?step=XX)錯誤
在Prometheus中,限制每條時間軸最大存在11000個資料點,即 (endTime - startTime) / step的值最大為11000。建議縮小查詢區間或者調大step參數。
