Prometheus-rate与irate源码详解

article/2025/9/28 16:53:22

我们先看prometheus的函数格式

一 类型

var Functions = map[string]*Function{..."rate": {Name:       "rate",ArgTypes:   []ValueType{ValueTypeMatrix},ReturnType: ValueTypeVector,Call:       funcRate,},..."irate": {Name:       "irate",ArgTypes:   []ValueType{ValueTypeMatrix},ReturnType: ValueTypeVector,Call:       funcIrate,},...
}
func getFunction(name string) (*Function, bool) {function, ok := Functions[name]return function, ok
}
//通过getfunc 传递name 我们拿到func 并且调用

二 irate

那么我们具体看一下rate是如何实现的

func funcIrate(vals []Value, args Expressions, enh *EvalNodeHelper) Vector {return instantValue(vals, enh.out, true)
}
func instantValue(vals []Value, out Vector, isRate bool) Vector {samples := vals[0].(Matrix)[0]/*type Matrix []Seriestype Series struct {Metric labels.Labels `json:"metric"`Points []Point       `json:"values"`}type Point struct {T int64V float64}type Vector []Sampletype Sample struct {PointMetric labels.Labels}也就是说samples = Series  type*/// No sense in trying to compute a rate without at least two points. Drop// this Vector element.//试图计算一个没有至少两个点的速率是没有意义的。删除这个向量元素if len(samples.Points) < 2 {return out}// 2个值以上//倒数第一个值lastSample := samples.Points[len(samples.Points)-1]//倒数第二个值previousSample := samples.Points[len(samples.Points)-2]//声明一个新的valuevar resultValue float64//如果是rate 并且倒数第一个值小于倒数第二个值if isRate && lastSample.V < previousSample.V {// Counter reset.//那么 把倒数第一个值赋予我们新的变量resultValue = lastSample.V} else {//否则就算差值resultValue = lastSample.V - previousSample.V}//采样时间间隔等于 两个值的时间差sampledInterval := lastSample.T - previousSample.Tfmt.Println("\n\n")fmt.Printf("vals %#v\n",vals)fmt.Printf("out %#v\n",out)fmt.Println("last",lastSample.T)fmt.Println("pre",previousSample.T)fmt.Println("samp",sampledInterval)fmt.Println("len",len(vals[0].(Matrix)[0].Points))fmt.Println("\n\n")//时间间隔为0 就直接返回outif sampledInterval == 0 {// Avoid dividing by 0.return out}//这里是irate 传递的是true 详情见funcIrateif isRate {// Convert to per-second.//转换为每s// a = float64(sampledInterval) / 1000// resultValue = resultValue / a//这里sampledInterval 是我们计算的时间差resultValue /= float64(sampledInterval) / 1000}return append(out, Sample{Point: Point{V: resultValue},})
}

我这里prome配置的采集间隔为20s

irate(go_memstats_alloc_bytes_total[1m])

在这里插入图片描述

irate(go_memstats_alloc_bytes_total[2m])

在这里插入图片描述
根据代码以及promeql不难看出 1m 3个采集点 也就是说20 * 3 ,2m 6个采集点 也就是说20 * 6
根据代码是从采集点中首先判断如果低于2个指标直接返回,如果2个以上取最后两个并且判断大小 如果后续大于上一个 那么就取差值,并且除以采集间隔,算出每秒的数据 counter是只增不减的数据类型

三 rate

func funcRate(vals []Value, args Expressions, enh *EvalNodeHelper) Vector {return extrapolatedRate(vals, args, enh, true, true)
}
/*
extrapolatedRate是用于速率/增加/增量的实用函数。
它计算速率(如果isCounter为true,则允许计数器重置),
如果第一个/最后一个采样接近边界,则进行推断,
并以每秒(如果isRate为true)或总体形式返回结果。*/
//rate 传递的参数为extrapolatedRate(vals, args, enh, true, true)
//由此可以理解rate一般用于Counter类型
func extrapolatedRate(vals []Value, args Expressions, enh *EvalNodeHelper, isCounter bool, isRate bool) Vector {ms := args[0].(*MatrixSelector)/*type MatrixSelector struct {// 如果解析器未返回错误,则可以假定这是一个VectorSelector。VectorSelector ExprRange          time.DurationEndPos Pos}type Expr interface {Node// Type返回表达式求值的类型。 它不会执行深入检查,因为这是在解析时完成的。Type() ValueType//expr确保没有其他类型的接口意外实现。expr()}type ValueType stringtype Node interface {// 当作为有效查询的一部分进行解析时,返回给定节点的节点的字符串表示形式。String() string//PositionRange返回AST节点在查询字符串中的位置。PositionRange() PositionRange}*/vs := ms.VectorSelector.(*VectorSelector)/*type VectorSelector struct {Name          stringOffset        time.DurationLabelMatchers []*labels.Matcher//在查询准备时填充未扩展的seriesSet。unexpandedSeriesSet storage.SeriesSetseries              []storage.SeriesPosRange PositionRange}*/var (samples    = vals[0].(Matrix)[0]//durationMilliseconds//d/  (s/ns)//int64(d / (time.Millisecond / time.Nanosecond))rangeStart = enh.ts - durationMilliseconds(ms.Range+vs.Offset)rangeEnd   = enh.ts - durationMilliseconds(vs.Offset))// 在没有至少两个点的情况下尝试计算速率没有任何意义。 删除此Vector元素。if len(samples.Points) < 2 {return enh.out}var (counterCorrection float64lastValue         float64)fmt.Printf("%#v\n",ms)fmt.Printf("%#v\n",vs)fmt.Printf("%#v\n",samples.Points)//这里主要是为了防止不是counter类型的 会出现忽大忽小for _, sample := range samples.Points {if isCounter && sample.V < lastValue {counterCorrection += lastValue}lastValue = sample.V}//拿到第一个根最后一个的中间差resultValue := lastValue - samples.Points[0].V + counterCorrection// Duration between first/last samples and boundary of range.//第一个/最后一个样本与范围边界之间的持续时间。durationToStart := float64(samples.Points[0].T-rangeStart) / 1000durationToEnd := float64(rangeEnd-samples.Points[len(samples.Points)-1].T) / 1000sampledInterval := float64(samples.Points[len(samples.Points)-1].T-samples.Points[0].T) / 1000averageDurationBetweenSamples := 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.//计数器不能为负。//如果我们有任何斜率(即resultValue上升),我们可以外推计数器的零点。//如果到零点的持续时间比durationToStart短,我们将零点作为序列的开始,从而避免外推到负计数器值。durationToZero := sampledInterval * (samples.Points[0].V / resultValue)if durationToZero < durationToStart {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.//如果第一个/最后一个样本接近范围的边界,则外推结果。//就像我们期望的那样,考虑到到目前为止我们看到的样本之间的间隔,还会有另一个样本存在,并且要考虑到噪声。extrapolationThreshold := averageDurationBetweenSamples * 1.1extrapolateToInterval := sampledIntervalif durationToStart < extrapolationThreshold {extrapolateToInterval += durationToStart} else {extrapolateToInterval += averageDurationBetweenSamples / 2}if durationToEnd < extrapolationThreshold {extrapolateToInterval += durationToEnd} else {extrapolateToInterval += averageDurationBetweenSamples / 2}resultValue = resultValue * (extrapolateToInterval / sampledInterval)if isRate {resultValue = resultValue / ms.Range.Seconds()}return append(enh.out, Sample{Point: Point{V: resultValue},})
}

http://chatgpt.dhexx.cn/article/9a0mGVQ6.shtml

相关文章

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;而…

C# winform中,简单实现Listview.Subitem.BackColor.ForeColor改变字体颜色,Listview.Subitem.BackColor 改变背景

做项目的时候,客户的查询结果中要在listview中亮显查询关键字.在网上找了半天,没有合适的代码.于是就自己琢磨了一下.贴出代码,希望对大家有所帮助. 注意事项&#xff1a; 一定要把listview的OwnerDraw属性设置为True&#xff08;默认是False&#xff09;。 当设置Owner…