简单使用
package main
import (
"context"
"github.com/prometheus/client_golang/api"
v1 "github.com/prometheus/client_golang/api/prometheus/v1"
"github.com/prometheus/common/model"
log "github.com/sirupsen/logrus"
"time"
)
func main() {
// 创建一个 prom 客户端
client,err := api.NewClient(api.Config{
Address: "http://localhost:9090",
})
if err != nil{
log.Fatalf("init client failed! %s", err)
}
// 创建一个 api v1客户端
v1Api := v1.NewAPI(client)
query := `node_cpu_seconds_total`
result, warnings, err := v1Api.Query(context.Background(), query, time.Now())
if err != nil{
log.Fatalf("query failed, %s", err)
}
if len(warnings) > 0{
log.Info("Warning,",warnings)
}
log.Infof("ResultTypeis: %s", result.Type())
vector,ok := result.(model.Vector)
if !ok {
log.Info("result is not a vector")
return
}
// 遍历结果向量中的每个样本
for _, sample := range vector {
log.Infof("Metrics: %s, Value: %s\n", sample.String(), sample.Value)
}
}
日常使用总结
查询方法
在 PromQL 中,主要有两种类型的查询方法:瞬时查询(instant query)和区间查询(range query)。他们的主要差异在于所需参数的不通,并且适用的场景也有所不同。
- 瞬时查询 (Instant Query)
瞬时查询是最常见的一种查询类型,其特点是在指定的时间点上取样一次,这种查询常用来查看当前状态下的指标值,例如查看当前时刻的 cpu 负载,网络流量等。
//例如查询当前时间 cpu 的节点消耗的总 CPU 时间
query := `node_cpu_seconds_total`
result, warnings, err := v1Api.Query(context.Background(), query, time.Now())
- 区间查询(Range Query)
区间查询则允许用户指定一个时间窗口,并在该窗口的每一段时间点上采样一次,这种查询常用来观察一段时期内的指标变化趋势,例如查看最近 7 天的平均 cpu 负载,近一个月的网络流量峰值等等
//查询了过去 60 分钟内每 5 分钟的节点空闲 CPU 时间的变化速率。
query := `rate(node_cpu_seconds_total{mode="idle"}[5m])`
stepDuration := 15 * time.Minute // Set your desired step duration here
endTime := time.Now()
startTime := endTime.Add(-60 * time.Minute)
rng := v1.Range{
Start: startTime,
End: endTime,
Step: stepDuration,
}
result, warnings, err := v1Api.QueryRange(context.Background(), query, rng)
查询结果
- Scalar Result
Scalar结果通常用于只返回一个简单数字的查询,例如计算某个特定的计数器的总和,例如,查看k8s集群中有多少个 pod。我们可以把查询语句写成count(kube_pod_info)
// 构建查询表达式
query := `sum(node_memory_MemTotal_bytes) / 1024 / 1024`
// 执行查询
result, _, err := v1Api.Query(context.Background(), query, time.Now())
if err != nil {
log.Fatal(err)
}
// 将结果断言为标量类型
scalar, ok := result.(*model.Scalar)
if !ok {
log.Fatal("Unexpected query result type")
}
// 输出标量值
log.Infof("The result is %f\n", scalar.Value)
- Vector Result
Vector通常用于返回一组带有标签的指标,例如正在运行的所有 pod 的数量
query := `kube_pod_info{namespace='prometheus'}`
result, _, err := v1Api.Query(context.Background(), query, time.Now())
vector, ok := result.(model.Vector)
if !ok {
log.Error("Unexpected query result type")
return
}
for _, sample := range vector {
// 获取标签的值
namespace := sample.Metric["namespace"]
podName := sample.Metric["pod"]
log.Infof("Metrics: namespace=%s, pod=%s, Value: %s\n", namespace, podName, sample.Value)
}
- Matrix Result
Matrix 结果通常用于返回一段时间范围内的历史数据,例如过去一天 cpu 利用率的变化趋势,例如,我们可以写这样一个表达式:
rate(node_cpu_seconds_total{mode="idle"}[5m])
,它的结果就是一个矩阵。
特别的,对于包含聚合函数的查询,如sum()、avg()等,Prometheus也会返回一个样本流,但其中只有一条记录,即聚合后的结果。这种情况下,你也无法将其转换为model.Vector类型,因为它不是一个向量,而是一个样本流。
query := `rate(node_cpu_seconds_total{mode="idle"}[5m])`
stepDuration := 15 * time.Minute // 设置您所需的步长(时间间隔)在这里
endTime := time.Now()
startTime := endTime.Add(-60 * time.Minute)
rng := v1.Range{
Start: startTime,
End: endTime,
Step: stepDuration,
}
result, _, err := v1Api.QueryRange(context.Background(), query, rng)
if err != nil {
log.Fatal(err)
}
matrix, ok := result.(model.Matrix)
if !ok {
log.Fatalf("unexpected result type: %T", result)
}
for _, stream := range matrix {
fmt.Println("Metric:", stream.Metric)
for _, sample := range stream.Values {
fmt.Printf("Time: %s, Value: %s\n", sample.Timestamp, sample.Value)
}
}
总结
本文针对 prometheus golang 客户端进行了简单的使用介绍,当查询设计多维度时,Pronetheus 会返回一个样本流而不是单个样本,以下是一个处理多种情况的示例,仅供参考
switch result.Type() {
case model.ValScalar:
scalar := result.(*model.Scalar)
fmt.Println("Scalar value:", scalar.Value)
case model.ValVector:
vector := result.(model.Vector)
for _, sample := range vector {
fmt.Println("Sample metric:", sample.Metric, " Sample value:", sample.Value)
}
case model.ValMatrix:
matrix := result.(model.Matrix)
for _, stream := range matrix {
fmt.Println("Stream values:")
for _, point := range stream.Values {
fmt.Println("\tPoint timestamp:", point.Timestamp, " Point value:", point.Value)
}
}
default:
fmt.Println("Unknown type of result")
}