关于 prometheus 中rata 函数的算法 ,在网上看部分描述,也看了官方的描述是 计算范围向量中时间序列每秒的平均增长速率,按这个描述去理解算法应该是 范围向量的差值/持续时长,但是我用数据测试之后发现并不是如此

例如:

image.png

如上图示:
按我理解的rate的算法应该是(17-10)/60=0.1166但是通过prometheus 计算结果为 0.1668,那么他们的差异是怎么来的呢?带着这个问题我看了一下 prometheus的源码。

源码地址

定位到 extrapolatedRate 这个函数

我吧关键的代码贴出来

    var (
        samples    = vals[0].(Matrix)[0]
        //根据区间和offset计算开始时间
        rangeStart = enh.Ts - durationMilliseconds(ms.Range+vs.Offset) 
        //计算结束时间
        rangeEnd   = enh.Ts - durationMilliseconds(vs.Offset)          
    )
    //计算增长的量(区间向量的最后一个值 减去  第一个值)
    resultValue := samples.Points[len(samples.Points)-1].V - samples.Points[0].V 
    //计算前面的边界时间
    durationToStart := float64(samples.Points[0].T-rangeStart) / 1000           
    //计算后面的边界时间
    durationToEnd := float64(rangeEnd-samples.Points[len(samples.Points)-1].T) / 1000 

    //第一个点和最后一个点的时间差
    sampledInterval := float64(samples.Points[len(samples.Points)-1].T-samples.Points[0].T) / 1000 
    //每个点的时间间隔
    averageDurationBetweenSamples := sampledInterval / float64(len(samples.Points)-1)              

    //抹平间隔时间的误差
    extrapolationThreshold := averageDurationBetweenSamples * 1.1 
    extrapolateToInterval := sampledInterval

  
    //加上前面的边界时间
    if durationToStart < extrapolationThreshold {
        extrapolateToInterval += durationToStart
    } else {
        extrapolateToInterval += averageDurationBetweenSamples / 2
    }
    //加上后面的边界时间
    if durationToEnd < extrapolationThreshold {
        extrapolateToInterval += durationToEnd
    } else {
        extrapolateToInterval += averageDurationBetweenSamples / 2
    }
    // 估算范围向量的差值=最终的范围向量的差值 *((范围向量时间差+加上前后边界)/范围向量时间差) 
    resultValue = resultValue * (extrapolateToInterval / sampledInterval)

    if isRate {
        rate 的值= 估算范围向量的差值/rate的持续时间
        resultValue = resultValue / ms.Range.Seconds()
    }

最终的值的算法是 范围向量的差值*(1.x的系数)/持续时长 所以 rate 方法算出来的结果比手算的要大一些 ,其中 1.x系数的算法=(区间的前后边界值的和(不能大于点之间的平均间隔时间)+(区间向量最后一个和第一个点的时间差))/(区间向量最后一个和第一个点的时间差)


曹飞龙
167 声望8 粉丝

进取・坚韧・开放・影响