已寫入時序數據,使用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”機制。
單次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__ != rightLabels
PromQL中涉及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分鐘。
在控制臺中,查詢到的時序數據缺失較多時間線
在日志服務控制臺的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參數。