普罗米修斯irate/rate算法区别(原创)

article/2025/9/29 7:45:38

文章目录

  • irate算法
    • 流程
    • 特点
    • 代码
  • rate函数
    • 流程
    • 特点
    • 代码

irate算法

流程

  • 选取时间范围内最后两个点:end1,end2

  • 计算两个点的差值,这里分两种情况:

    ​ 正常情况下:end2 > end1 ,此时 value = end2 - end1

    ​ 异常情况下,end2 < end1 ,此时 value = end2

  • 计算两个时间点的时间差time = time2 - time1

  • 计算最终结果:value / time 并换算毫秒单位

流程图

end2 > end1
end2 < end1
选取时间范围内的点集合
选取集合内最后两个点: end1 end2
计算end1和end2之间差值
差值 value = end2 - end1
差值 value = end2
值差 value
计算 end1 和 end2 之间时间差 time
time = time2 - time1
value/time

特点

  • 相当于区间内的最后时刻瞬时值
  • 只选取了区间最后两个点进行计算
  • 如果出现了counter异常类型的值,就会计算出巨大的结果

代码

package promqlvar functions = map[string]*Function{"irate": {Name:       "irate",ArgTypes:   []ValueType{ValueTypeMatrix},ReturnType: ValueTypeVector,// 处理函数 funcIrateCall:       funcIrate,},
}// irate 方法
func funcIrate(vals []Value, args Expressions, enh *EvalNodeHelper) Vector {// 注意,最后一个参数 isRate = truereturn instantValue(vals, enh.out, true)
}// irate 算法内容
// isRate = true
func instantValue(vals []Value, out Vector, isRate bool) Vector {for _, samples := range vals[0].(Matrix) {if len(samples.Points) < 2 {// 少于两个点,无效范围continue}// 取区间内最后两个数值// endindex 的点位lastSample := samples.Points[len(samples.Points)-1]// endindex - 1 的点位previousSample := samples.Points[len(samples.Points)-2]var resultValue float64// irate计算时 isRate = trueif isRate && lastSample.V < previousSample.V {// counter 中出现了明显的异常点,最后两个值是 大--小 的结构,因此 counter 重置resultValue = lastSample.V} else {// 最后两个值是 小--大 的结构,因此直接相减resultValue = lastSample.V - previousSample.V}/* 此时 resultValue有两种情况:1、正常情况时,resultValue=最后两个点的差值,2、counter 类型异常时,resultValue=最后选取的点的值,*/// 两个值的时间间隔sampledInterval := lastSample.T - previousSample.Tif sampledInterval == 0 {// 选取的两个点时间差为0.要舍弃,否则除以0最终会是无限大continue}// irate 时 isRate = trueif isRate {// 变化值除以时间间隔,这里的1000看来默认时间单位是秒,这里除以1000,换算成毫秒?// 此时如果 counter 遇到了 重置点, 那么这里计算出来的值会【异常的大】resultValue /= float64(sampledInterval) / 1000}out = append(out, Sample{Point: Point{V: resultValue},})}return out
}

rate函数

流程

  1. 查找点集合的值差

    如果始终 next > current,那么 value = end - begin

    如果中间存在 A = next < current,那么 value = end - begin + 每个异常的落差A

  2. 计算点集合的时间跨度比例P

    计算开头、结尾空隙

    计算时间跨度的有效值与时间范围的比例P

  3. 按照P等比例扩大value的值

  4. 计算最终结果: value/区间时间跨度

流程图

end2 > end1
end2 < end1
选取时间范围内的点集合
计算首尾两个点的差值
差值 value = end - begin
差值 value = end - begin + 所有异常落差值
值差 value
计算点集合的起始位置
对比区间长度, 计算点集合的范围与区间跨度的比例P
按照比例P扩大value的值=value2
按照调整后的value2 计算最终结果: value2/区间长度

计算点集合落差的异常值

目的&特点:无论中间是否出现倒序情况,都能算出近似于总落差的值
在这里插入图片描述

等比例扩大区间的理解

在这里插入图片描述

特点

  • 相当于区间内的平均值

  • 读取了区间内最后一个点第一个点的差值

  • 又等比例扩大了点集合的时间范围到区间跨度

  • 因此计算比irate较为严谨

代码

var functions = map[string]*Function{// rate 方法入口"rate": {Name:       "rate",ArgTypes:   []ValueType{ValueTypeMatrix},ReturnType: ValueTypeVector,Call:       funcRate,},
}// rate 入口
func funcRate(vals []Value, args Expressions, enh *EvalNodeHelper) Vector {// isRate = truereturn extrapolatedRate(vals, args, enh, true, true)
}// 算法实现
func extrapolatedRate(vals []Value, args Expressions, enh *EvalNodeHelper, isCounter bool, isRate bool) Vector {ms := args[0].(*MatrixSelector)var (// 默认是毫秒单位matrix     = vals[0].(Matrix)rangeStart = enh.ts - durationMilliseconds(ms.Range+ms.Offset)rangeEnd   = enh.ts - durationMilliseconds(ms.Offset))for _, samples := range matrix {// No sense in trying to compute a rate without at least two points. Drop// this Vector element.if len(samples.Points) < 2 {continue}var (counterCorrection float64lastValue         float64)for _, sample := range samples.Points {// Counter类型数据,但是数值又小于上一次的 value,说明重置了 counter// 否则的话,这个值一直为空if isCounter && sample.V < lastValue {// 所有异常节点的差值累计counterCorrection += lastValue}// 由于是 for 循环,因此这里的 lastValue 最终就是当前点集合最后一个点的值lastValue = sample.V}// 集合首位两个点的差值。 集合最后一个点的值 - 第一个点的值,最后加上了定时器重置的 counter(一般为0)// 这个 counterCorrection 的理解可以参考下图,是计算的关键点resultValue := lastValue - samples.Points[0].V + counterCorrection// 区间开始时间与 第一个点的时间间隔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)if isCounter && resultValue > 0 && samples.Points[0].V >= 0 {// Counters cannot be negative. If we have any slope at// all (i.e. resultValue went up), we can extrapolate// the zero point of the counter. If the duration to the// zero point is shorter than the durationToStart, we// take the zero point as the start of the series,// thereby avoiding extrapolation to negative counter// values.// 这里较为难理解,目的: 区间内是一个递增的序列,假设这个序列是线性的,那么要寻找,这个线性序列的值为0的那个点所在的时间点// 如果这个0所在的时间点在第一个点左边,那么就要砍掉0值左侧的区域// 比如 1 3 5 7这个序列,那么推测的0值位置就在 6*(1/6) = 1,也就是说这个线性序列的0值就是开始的位置durationToZero := sampledInterval * (samples.Points[0].V / resultValue)if durationToZero < durationToStart {// 如果中间counter重置了,这里好像是在找重置时那个0点的位置,我们将会把区间起点调整到0点附近// 如果选择的序列所推测的的0值位置在时间开始与第一个节点之间的位置,那么就要调整整个有效区间的开始位置durationToStart = durationToZero}}// If the first/last samples are close to the boundaries of the range,// extrapolate the result. This is as we expect that another sample// will exist given the spacing between samples we've seen thus far,// with an allowance for noise.// 噪音处理,因为点集合的区间实际上小于时间区间,两边有一段空白,因此这里 *1.1 来扩大了一下点集合的区间范围extrapolationThreshold := averageDurationBetweenSamples * 1.1// 默认是所有集合点的时间差extrapolateToInterval := sampledInterval// 将点集合与区间两端的时间空隙添加到 extrapolateToInterval 中if durationToStart < extrapolationThreshold {// 决定最终区间的起点extrapolateToInterval += durationToStart} else {extrapolateToInterval += averageDurationBetweenSamples / 2}if durationToEnd < extrapolationThreshold {// 决定区间的终点extrapolateToInterval += durationToEnd} else {extrapolateToInterval += averageDurationBetweenSamples / 2}// extrapolateToInterval 是经过调整的区间长度,添加了 集合点与时间区间两端的时间空隙,因此 extrapolateToInterval 会比 sampledInterval 大一点// 这个操作等于按照  实际时间区间/集合点时间区间  这个比例,把 resultValue 这个集合点两端的差值等比例扩大resultValue = resultValue * (extrapolateToInterval / sampledInterval)if isRate {// 利用等比例扩大后的插值,除以时间间隔。计算最终的每次 for 循环的变化率resultValue = resultValue / ms.Range.Seconds()}enh.out = append(enh.out, Sample{Point: Point{V: resultValue},})}return enh.out
}

http://chatgpt.dhexx.cn/article/d4H8xMPN.shtml

相关文章

Prometheus-rate与irate源码详解

我们先看prometheus的函数格式 一 类型 var Functions map[string]*Function{..."rate": {Name: "rate",ArgTypes: []ValueType{ValueTypeMatrix},ReturnType: ValueTypeVector,Call: funcRate,},..."irate": {Name: &qu…

Prometheus监控:rate与irate的区别

对官网文档的解读 irate和rate都会用于计算某个指标在一定时间间隔内的变化速率。但是它们的计算方法有所不同&#xff1a;irate取的是在指定时间范围内的最近两个数据点来算速率&#xff0c;而rate会取指定时间范围内所有数据点&#xff0c;算出一组速率&#xff0c;然后取平…

【博客486】prometheus-----rate,irate,increase的原理

prometheus-----rate&#xff0c;irate&#xff0c;increase的原理 三者综合比较 这三个函数接受的都是 Range Vector&#xff0c;返回的是 Instant Vector&#xff0c;比较常用。 区别&#xff1a; rate计算指定时间范围内&#xff1a;增量/时间范围&#xff1b; irate计算指…

【博客650】irate适用于绘制细粒度灵敏图,但警惕用于告警

irate适用于绘制细粒度灵敏图&#xff0c;但警惕用于告警 1、irate解析 作用&#xff1a; irate(v range-vector) 函数用于计算区间向量的增长率&#xff0c;但是其反应出的是瞬时增长率。 原理&#xff1a; irate 函数是通过区间向量中最后两个两本数据来计算区间向量的增长…

git查看用户名和密码

一、查看 查看用户名 &#xff1a;git config user.name 查看密码&#xff1a; git config user.password 查看邮箱&#xff1a;git config user.email 查看配置信息&#xff1a; $ git config --list 二、修改 修改用户名 git config --global user.name “xxxx(新的用户名)”…

Linux中git保存用户名密码

Linux下命令行使用git&#xff0c;每次操作都要输入用户名和密码很麻烦&#xff0c;可以通过配置保存用户名和密码。 进入到git项目的根目录下&#xff0c;打开.git目录下的config文件 cd .git vim config添加如下内容 [credential]helper store:wq保存退出 执行上述操作之…

git设置单个仓库用户名以及密码

有些时候我们的服务器可能要部署多个git仓库&#xff0c;不同git仓库的用户名以及密码都是不一样的&#xff0c;此时需要我们设置单个仓库的用户名以及密码。 1.git设置用户名以及邮箱 命令如下&#xff1a; git config user.name "userName" //你的用户名 …

git 修改用户名和密码

windows 在控制面板修改凭证就可以进行修改用户名密码。 Linux 执行vim ~/.git-credentials&#xff0c;可以看到被保存的账号密码&#xff0c;删掉、修改或新增都可以&#xff01; eg&#xff1a;http://账号:密码git仓库http地址或用https://账号:密码git仓库http地址 h…

mac下git设置用户名密码

设置用户名和邮箱 git config --global user.name [username] git config --global user.email [email] 查看用户名和邮箱 git config --global user.name git config --global user.email 查看配置文件 git config --list 编辑配置文件 vi .gitconfig sourcetree中的…

linux 分配git用户名和密码,配置Git记住用户名密码的俩种方法

前言 相信大家在使用github过程中&#xff0c;也有这情况&#xff0c;总是让大家输入烦人的用户名&#xff0c;密码&#xff0c;浪费时间。下面这俩种办法也是网上找来的&#xff0c;我做了些整合&#xff0c;避免大家走入当时跟我一样的坑中。 方法一 1.1创建文件储存git用户名…

git重新设置用户名密码

设置密码 我们输入git config --global user.name "youname"设置密码&#xff0c;在输入git config --global user.email "aaqq.com"设置邮箱

git设置用户名、密码和邮箱(全局设置)

&#xff08;1&#xff09;git设置用户名&#xff08;如下图一&#xff09;&#xff1a; git config --global user.name Urasaki &#xff08;2&#xff09;git设置密码&#xff08;如下图一&#xff09;&#xff1a; git config --global user.password Am100100 &#xff…

设置git账户名和密码

git config --global user.email [email] //邮箱 git config --global user.name [username] //密码查看是否配置成功 git config --list出现user.email和user.name表示配置成功

git设置账户名密码

最近新创建了一个项目&#xff0c;同步git代码&#xff0c;但是每次连接远程都要重新输入用户名密码信息&#xff0c;很烦&#xff0c;就想着怎么让他记住账号。就用了以下方法&#xff0c;亲测有效&#xff0c;分享记录下。 一. 打开当前项目下.git文件夹&#xff0c;找到con…

git记住用户名和密码

在使用git时&#xff0c;如果用的是HTTPS的方式&#xff0c;则每次提交&#xff0c;都会让输入用户名和密码&#xff0c;久而久之&#xff0c;就会感觉非常麻烦&#xff0c;那么该如何解决呢&#xff1f; 方式一&#xff1a;使用SSH&#xff0c;添加ssh key。 方式二&#xf…

git设置用户名密码(单用户和多用户)

刚换电脑重头配置git&#xff0c;写篇文章纪念一下。 一、前言 Git共有三个级别的config文件&#xff0c;分别是system、global和local。global的在$home\.gitconfig&#xff0c;local的在仓库目录下的.git\config。这三个级别都分别配置了用户信息&#xff0c;当git commit时…

JS的 execCommand 方法实现一个简单的富文本编辑器

一、document.execCommand() 从其名字上可以看出execCommand()是用来执行命令的&#xff0c;当一个HTML文档切换到设计模式时&#xff0c;document暴露 execCommand方法&#xff0c;该方法允许运行命令来操纵可编辑内容区域的元素。如保存文件、打开新文件、撤消、重做、剪切…

用c语言,制作一个心形彩色告白图案(附源码)

今天我们来一个好玩的&#xff0c;用c语言&#xff0c;制作一个心形彩色告白图案。 送给c语言初学者 代码&#xff1a; #include<stdio.h> #include<math.h> #include<windows.h> #include<time.h> #define u 0.1 #define v 0.053 void setcolor(uns…

ASP.NET 2.0中使用Gridview控件的高级技巧

ASP.NET 2.0中&#xff0c;新增加的gridview控件的确十分强大&#xff0c;弥补了在asp.net 1.1中&#xff0c;使用datagrid控件时的不足之处。因为在asp.net 1.1中&#xff0c;在使用datagrid时&#xff0c;很多情况下依然要编写大量的代码&#xff0c;十分不方便&#xff0c;而…