Prometheus源码专题精讲——Prometheus的四种查询类型
Prometheus源码专题精讲——Prometheus的四种查询类型
https://github.com/prometheus/prometheus/blob/v2.53.1/promql/value.go
Prometheus的查询类型基于其强大的查询语言(PromQL),支持从瞬时查询到范围查询,再到聚合查询等多种场景。通过理解和应用这些查询类型,用户可以灵活地检索、分析和可视化他们的时间序列数据。结合Prometheus的源码,我们可以更深入地理解这些查询类型背后的实现机制,从而更好地利用Prometheus进行监控和警报。
在Prometheus中,查询类型主要由返回的数据类型决定。根据promql/parser/value.go
文件中的定义,主要有以下几种查询类型:
一、 瞬时向量(Instant Vector)
-
-
定义: 一组时间序列,每个时间序列代表一个度量指标(如
http_requests_total)
,这些时间序列由一组标签(如method="GET"
)唯一标识。 -
特点: 这组时间序列中的每个样本都代表了在查询执行时(即“现在”)的度量值。所有返回的样本在逻辑上被视为具有相同的时间戳(即查询执行的瞬间)。
-
示例: http_requests_total{method="GET"}返回所有标签为method="GET"的http_requests_total时间序列的当前值。
-
1 | http_requests_total{method= "GET" } |
这条查询将返回所有使用GET方法的HTTP请求总数的当前值。
-
-
代码解析: 在Prometheus的源码中,
Vector
类型是一个重要的概念,它基本上是对[]Sample
类型的别名,但有一个重要的约定:在Vector中,所有的
Sample
都必须具有相同的时间戳。
-
1 2 3 4 5 6 7 8 | D:\worker-go\prometheus-2.53.1\promql\value.go func (Vector) Type() parser.ValueType { return parser.ValueTypeVector } // Vector is basically only an alias for []Sample, but the contract is that // in a Vector, all Samples have the same timestamp. type Vector []Sample |
1 2 3 4 5 6 7 8 9 | type Vector []Sample Vector is basically only an alias for []Sample, but the contract is that in a Vector, all Samples have the same timestamp. func (vec Vector) ContainsSameLabelset() bool func (vec Vector) String() string func (vec Vector) TotalSamples() int func (Vector) Type() parser.ValueType promql.Vector on pkg.go.dev |
1.1、Vector的数据类型定义
在Prometheus
的PromQL
中,Vector
是一个非常重要的类型,它用于表示一组具有相同时间戳的样本(Sample
)。这些样本通常代表了在某个特定时间点上的度量值。
1 2 3 4 | // Vector is basically only an alias for []Sample, but the contract is that // in a Vector, all Samples have the same timestamp. type Vector []Sample |
这段代码定义了Vector
类型,它实际上是[]Sample
(即Sample
类型的切片)的别名。但有一个重要的约定:在Vector
中,所有的Sample
都必须具有相同的时间戳。这个约定是Vector
类型与其他类型(如Matrix
)的主要区别之一。
1.2、Vector的方法
Vector
类型有几个方法,用于执行不同的操作:
1.2.1、Type()方法
1 2 | func (Vector) Type() parser.ValueType { return parser.ValueTypeVector } |
这个方法返回Vector
的类型,即ValueTypeVector
。这是parser.ValueType
枚举中的一个值,表示这是一个向量类型。
1.2.2、ContainsSameLabelset() 方法
1 2 | func (vec Vector) ContainsSameLabelset() bool |
这个方法检查Vector
中的所有Sample
是否包含相同的标签集。如果所有Sample
的标签都相同,则返回true
;否则返回false
1.2.3、String()方法
1 2 | func (vec Vector) String() string |
这个方法返回Vector
的字符串表示形式。这通常用于调试或日志记录,以便能够轻松地查看Vector
的内容。
1.2.4、TotalSamples()方法
1 2 | func (vec Vector) TotalSamples() int |
这个方法返回Vector
中Sample
的总数。这可以用于确定Vector
的大小或进行迭代操作。
Vector
是一个重要的类型,用于表示一组具有相同时间戳的样本。它提供了几个方法来执行不同的操作,如获取类型、检查标签集、转换为字符串和获取样本总数。这些方法和约定使得Vector
在PromQL查询中非常有用,特别是在处理瞬时向量时。
1.3、Vector的查询接口
对于Prometheus的HTTP
API,用于查询瞬时向量的基本地址是/api/v1/query
。当你想要执行一个PromQL查询(如http_requests_total{method="GET"}
)时,你需要向Prometheus服务器的这个API地址发送一个HTTP请求。
http://<prometheus-server-ip>:<prometheus-server-port>/api/v1/query
对应的接口查询:api/v1/query
1 2 3 4 | curl -X POST http: //192 .168.1.100:9090 /api/v1/query -d '{ "query" : "http_requests_total{method=\"GET\"}" }' -H "Content-Type: application/json" |
二、范围向量(Range Vector)
-
-
定义: 与瞬时向量类似,但返回的是一段时间内的时间序列样本集合,而不是单一时间点的值。
-
特点: 对于每个匹配的时间序列,它返回指定时间范围内(如过去5分钟)的所有样本。每个样本都有其自己的时间戳,表示实际记录的时间。
-
示例:
http_requests_total{method="GET"}[5m]
返回过去5分钟内所有使用GET
方法的HTTP
请求总数的样本数据。
-
1 2 | http_requests_total{method= "GET" }[5m] |
这条查询将返回过去5分钟内,所有使用GET方法的HTTP请求总数的样本数据。
-
-
代码解析: 在
Prometheus
中,范围向量(Range Vector
)是时间序列数据的一种表示,它表示在一定时间范围内的数据点集合。在Prometheus
的查询语言PromQL
中,范围向量是通过对瞬时向量(Instant Vector
)应用时间范围选择器(如 [5m] 表示过去5分钟内的数据)来创建的。 在D:\worker-go\prometheus-2.53.1\promql\value.go
代码中,Matrix
类型是对范围向量的一个实现。Matrix
是一个Series
类型的切片,其中Series
包含了时间序列数据。每个Series
包含了一个Metric
(指标)和一些与之相关的数据点,这些数据点可以是浮点数(Floats
)或直方图(Histograms
)。123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354D:\worker-go\prometheus-2.53.1\promql\value.go
//
Matrix is a slice of Series that implements
sort
.Interface and
//
has a String method.
type
Matrix []Series
func (m Matrix) String() string {
//
TODO(fabxc):
sort
, or can we rely on order from the querier?
strs :=
make
([]string, len(m))
for
i, ss := range m {
strs[i] = ss.String()
}
return
strings
.Join(strs,
"\n"
)
}
//
TotalSamples returns the total number of samples
in
the series within a matrix.
//
Float samples have a weight of 1
in
this number,
while
histogram samples have a higher
//
weight according to their size compared with the size of a float sample.
//
See HPoint.size
for
details.
func (m Matrix) TotalSamples() int {
numSamples := 0
for
_, series := range m {
numSamples += len(series.Floats) + totalHPointSize(series.Histograms)
}
return
numSamples
}
func (m Matrix) Len() int {
return
len(m) }
func (m Matrix) Less(i, j int) bool {
return
labels.Compare(m[i].Metric, m[j].Metric) < 0 }
func (m Matrix) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
//
ContainsSameLabelset checks
if
a matrix has samples with the same labelset.
//
Such a behavior is semantically undefined.
//
https:
//github
.com
/prometheus/prometheus/issues/4562
func (m Matrix) ContainsSameLabelset() bool {
switch len(m) {
case
0, 1:
return
false
case
2:
return
m[0].Metric.Hash() == m[1].Metric.Hash()
default:
l :=
make
(map[uint64]struct{}, len(m))
for
_, ss := range m {
hash
:= ss.Metric.Hash()
if
_, ok := l[
hash
]; ok {
return
true
}
l[
hash
] = struct{}{}
}
return
false
}
}
-
三、标量(Scalar [ˈskelɚ])
-
-
定义: 一个单一的数值结果,通常是通过聚合函数(如
sum
、avg
、count
、min
、max
等)对一组时间序列或瞬时向量进行处理后得到的。 -
特点: 标量没有与之关联的时间戳或标签,它只是一个纯数值。
-
示例:
sum(http_requests_total{method="GET"})
返回所有使用GET方法的HTTP请求总数的总和。 -
代码解析: 这段代码定义了
Scalar
结构体,代表一个不与特定度量指标关联的数据点,包含时间戳T
(以纳秒为单位)和值V
(浮点类型)。此外,还实现了两个方法:String()
方法:将Scalar
实例格式化为字符串,格式为“scalar: 值 @[时间戳]”。MarshalJSON()
方法:将Scalar
实例转换为JSON格式,格式为[时间戳/1000, 值]的数组,其中时间戳转换为秒。
12sum
(http_requests_total{method=
"GET"
})
这条查询将返回所有使用GET方法的HTTP请求总数的总和。
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Scalar is a data point that's explicitly not associated with a metric. type Scalar struct { T int64 V float64 } func (s Scalar) String() string { v := strconv.FormatFloat(s.V, 'f' , -1, 64) return fmt .Sprintf( "scalar: %v @[%v]" , v , s.T) } func (s Scalar) MarshalJSON() ([]byte, error) { v := strconv.FormatFloat(s.V, 'f' , -1, 64) return json.Marshal([...]interface{}{float64(s.T) / 1000, v }) } |
四、字符串(String)
-
-
注意:
Prometheus
的PromQL
查询语言本身不直接返回字符串类型的结果,但字符串在处理标签和进行某些特定操作时(如正则表达式匹配)是必需的。 -
应用: 虽然查询不直接返回字符串类型,但字符串用于标签过滤、标签替换等场景。
-
示例: 虽然不直接返回字符串,但可以使用
label_replace
函数来修改时间序列的标签,其中涉及字符串操作。
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具