prometheus golang 客户端的使用

简单使用

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")
    }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容