已写入时序数据,使用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参数。