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时间序列的当前值。
-
http_requests_total{method="GET"}
这条查询将返回所有使用GET方法的HTTP请求总数的当前值。
-
-
代码解析: 在Prometheus的源码中,
Vector类型是一个重要的概念,它基本上是对[]Sample类型的别名,但有一个重要的约定:在Vector中,所有的Sample都必须具有相同的时间戳。
-
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
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)。这些样本通常代表了在某个特定时间点上的度量值。
// 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()方法
func (Vector) Type() parser.ValueType { return parser.ValueTypeVector }
这个方法返回Vector的类型,即ValueTypeVector。这是parser.ValueType枚举中的一个值,表示这是一个向量类型。
1.2.2、ContainsSameLabelset() 方法
func (vec Vector) ContainsSameLabelset() bool
这个方法检查Vector中的所有Sample是否包含相同的标签集。如果所有Sample的标签都相同,则返回true;否则返回false
1.2.3、String()方法
func (vec Vector) String() string
这个方法返回Vector的字符串表示形式。这通常用于调试或日志记录,以便能够轻松地查看Vector的内容。
1.2.4、TotalSamples()方法
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
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请求总数的样本数据。
-
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)。D:\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, 值]的数组,其中时间戳转换为秒。
sum(http_requests_total{method="GET"})这条查询将返回所有使用GET方法的HTTP请求总数的总和。
-
// 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函数来修改时间序列的标签,其中涉及字符串操作。
-

浙公网安备 33010602011771号