将 Prometheus 抓取的数据转换为数组

Posted

技术标签:

【中文标题】将 Prometheus 抓取的数据转换为数组【英文标题】:Convert Prometheus scraped data into an array 【发布时间】:2021-04-08 16:59:25 【问题描述】:

我已经从 Prometheus 抓取了数据,响应如下。我想使用 Go 将维度数据放入一个数组(用于操作)。谁能帮帮我。谢谢你:)

func main() 
    resp, err := http.Get("http://desktop-o1hkgm7:9090/federate?match%5B%5D=%7Bdialer_name%3D%22alertmanager%22%7D")
    if err != nil 
        log.Fatalln(err)
    
    //We Read the response body on the line below.
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil 
        log.Fatalln(err)
    
    //Convert the body to type string
    sb := string(body)
    log.Printf(sb)

回复如下:

# TYPE net_conntrack_dialer_conn_attempted_total untyped
net_conntrack_dialer_conn_attempted_totaldialer_name="alertmanager",instance="localhost:9090",job="prometheus" 0 1609568651186
# TYPE net_conntrack_dialer_conn_closed_total untyped
net_conntrack_dialer_conn_closed_totaldialer_name="alertmanager",instance="localhost:9090",job="prometheus" 0 1609568651186
# TYPE net_conntrack_dialer_conn_established_total untyped
net_conntrack_dialer_conn_established_totaldialer_name="alertmanager",instance="localhost:9090",job="prometheus" 0 1609568651186
# TYPE net_conntrack_dialer_conn_failed_total untyped
net_conntrack_dialer_conn_failed_totaldialer_name="alertmanager",instance="localhost:9090",job="prometheus",reason="refused" 0 1609568651186
"prometheus",reason="timeout" 0 1609568651186
net_conntrack_dialer_conn_failed_totaldialer_name="alertmanager",instance="localhost:9090",job="prometheus",reason="unknown" 0 1609568651186

我在得到键和值后得到了这个值。我可以遍历指标内的“名称”和“值”吗?如果可能的话,我该怎么做?我试过了,但显示无法循环通过 MetricFamily。

Image

【问题讨论】:

我之前回答过一个类似的问题:***.com/a/65388822/5821408(您可以修改代码并使其适合您的用例)。 这能回答你的问题吗? How to parse Prometheus data @shmsr。谢谢你的好意回复。我想自动化它,我不想在每次程序运行时都构建。有没有其他方法可以像你建议的那样直接获得价值。我也想得到标签内的尺寸。 每次都构建?为什么?您只需要更改获取展示格式的方式即可。我正在从文件中读取它;在你的情况下,你必须使用 HTTP 来获取它。 试试看,很简单。 【参考方案1】:

OP 在解释他/她真正想要什么方面不是很清楚。 OP 所指的输出是“Prometheus Exposition Format”。这是 EBNF 语法,最好用metric_namelabel_namelabel_value 等来说话,而不是说get the dimension data into an array (for manipulation)

展示形式:

metric_name [
  "" label_name "=" `"` label_value `"`  "," label_name "=" `"` label_value `"`  [ "," ] ""
] value [ timestamp ]

我的假设是,对于每个metric_name,OP 都希望循环遍历labels,即label_namelabel_value

我将其标记为重复,因为我之前回答过一个非常相似的问题,并且为了达到要求,只需要进行微小的更改。

在以下程序中,存在度量的源文件(以说明格式)存储在本地文件系统中。因此,一种改变它的方法是让它通过 HTTP 获取指标,然后循环遍历每个 metric_name 的标签。

示例输入:
# HELP net_conntrack_dialer_conn_attempted_total
# TYPE net_conntrack_dialer_conn_attempted_total untyped
net_conntrack_dialer_conn_attempted_totaldialer_name="federate",instance="localhost:9090",job="prometheus" 1 1608520832877
样本输出:
KEY: net_conntrack_dialer_conn_attempted_total
VAL: name:"dialer_name" value:"federate"
VAL: name:"instance" value:"localhost:9090"
VAL: name:"job" value:"prometheus"

代码:

package main

import (
    "flag"
    "fmt"
    "log"
    "os"

    dto "github.com/prometheus/client_model/go"
    "github.com/prometheus/common/expfmt"
)

func fatal(err error) 
    if err != nil 
        log.Fatalln(err)
    


func parseMetricFamily(path string) (map[string]*dto.MetricFamily, error) 
    reader, err := os.Open(path)
    if err != nil 
        return nil, err
    

    var parser expfmt.TextParser
    mf, err := parser.TextToMetricFamilies(reader)
    if err != nil 
        return nil, err
    
    return mf, nil


func main() 
    f := flag.String("f", "", "set filepath")
    flag.Parse()

    mf, err := parseMetricFamily(*f)
    fatal(err)

    for k, v := range mf 
        fmt.Printf("KEY: %v\n", k)
        for _, m := range v.Metric 
            for _, l := range m.Label 
                fmt.Printf("VAL: %v\n", l)
            
        
    

【讨论】:

谢谢你。这不完全是我正在寻找的答案。但从这里我得到了这个想法。 :)。非常感谢

以上是关于将 Prometheus 抓取的数据转换为数组的主要内容,如果未能解决你的问题,请参考以下文章

Prometheus 没有抓取 stats d exporter

读取 kafka 主题并通过 Rest API 公开数据以供 prometheus 抓取(Nodejs)

有没有办法配置数据抓取将'ssf'转换为'select * from'

prometheus-relabel_configs和metric_relabel_configs

6.prometheus重新打标

将prometheus采集的数据远程存储到influxdb中