如何解析普罗米修斯数据
How to parse Prometheus data
我已经能够通过如下发送 HTTP GET 来获取指标:
# TYPE net_conntrack_dialer_conn_attempted_total untyped net_conntrack_dialer_conn_attempted_total{dialer_name="federate",instance="localhost:9090",job="prometheus"} 1 1608520832877
现在我需要解析这些数据并获得对每条数据的控制权,以便我可以转换 tand 格式,如 json。
我一直在研究 Go 中的 ebnf 包:
ebnf package
有人可以指出解析上述数据的正确方向吗?
已经有一个很好的包可以做到这一点,它是由 Prometheus 的作者 本身提供的。
他们编写了一堆在 Prometheus 组件和库之间共享的 Go 库。它们被认为是 Prometheus 内部的,但您可以使用它们。
参考:github.com/prometheus/common doc. There's a package called expfmt
that can decode and encode the Prometheus's Exposition Format (Link)。是的,它遵循 EBNF 语法,因此也可以使用 ebnf
包,但您会立即获得 expfmt
。
使用的包:expfmt
示例输入:
# HELP net_conntrack_dialer_conn_attempted_total
# TYPE net_conntrack_dialer_conn_attempted_total untyped
net_conntrack_dialer_conn_attempted_total{dialer_name="federate",instance="localhost:9090",job="prometheus"} 1 1608520832877
示例程序:
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 parseMF(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 := parseMF(*f)
fatal(err)
for k, v := range mf {
fmt.Println("KEY: ", k)
fmt.Println("VAL: ", v)
}
}
示例输出:
KEY: net_conntrack_dialer_conn_attempted_total
VAL: name:"net_conntrack_dialer_conn_attempted_total" type:UNTYPED metric:<label:<name:"dialer_name" value:"federate" > label:<name:"instance" value:"localhost:9090" > label:<name:"job" value:"prometheus" > untyped:<value:1 > timestamp_ms:1608520832877 >
因此,expfmt
是您的用例的不错选择。
更新:OP 发布输入中的格式问题:
参考:
Note that in the text protocol, each line has to end with a line-feed
character (aka 'LF' or '\n'). Ending a line in other ways, e.g. with
'CR' aka '\r', 'CRLF' aka '\r\n', or just the end of the packet, will
result in a protocol error.
但是从错误消息中,我可以看到 \r
char 存在于 put 中,这在设计上是不可接受的。所以使用 \n
作为行尾。
我已经能够通过如下发送 HTTP GET 来获取指标:
# TYPE net_conntrack_dialer_conn_attempted_total untyped net_conntrack_dialer_conn_attempted_total{dialer_name="federate",instance="localhost:9090",job="prometheus"} 1 1608520832877
现在我需要解析这些数据并获得对每条数据的控制权,以便我可以转换 tand 格式,如 json。
我一直在研究 Go 中的 ebnf 包: ebnf package
有人可以指出解析上述数据的正确方向吗?
已经有一个很好的包可以做到这一点,它是由 Prometheus 的作者 本身提供的。
他们编写了一堆在 Prometheus 组件和库之间共享的 Go 库。它们被认为是 Prometheus 内部的,但您可以使用它们。
参考:github.com/prometheus/common doc. There's a package called expfmt
that can decode and encode the Prometheus's Exposition Format (Link)。是的,它遵循 EBNF 语法,因此也可以使用 ebnf
包,但您会立即获得 expfmt
。
使用的包:expfmt
示例输入:
# HELP net_conntrack_dialer_conn_attempted_total
# TYPE net_conntrack_dialer_conn_attempted_total untyped
net_conntrack_dialer_conn_attempted_total{dialer_name="federate",instance="localhost:9090",job="prometheus"} 1 1608520832877
示例程序:
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 parseMF(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 := parseMF(*f)
fatal(err)
for k, v := range mf {
fmt.Println("KEY: ", k)
fmt.Println("VAL: ", v)
}
}
示例输出:
KEY: net_conntrack_dialer_conn_attempted_total
VAL: name:"net_conntrack_dialer_conn_attempted_total" type:UNTYPED metric:<label:<name:"dialer_name" value:"federate" > label:<name:"instance" value:"localhost:9090" > label:<name:"job" value:"prometheus" > untyped:<value:1 > timestamp_ms:1608520832877 >
因此,expfmt
是您的用例的不错选择。
更新:OP 发布输入中的格式问题:
参考:
Note that in the text protocol, each line has to end with a line-feed
character (aka 'LF' or '\n'). Ending a line in other ways, e.g. with
'CR' aka '\r', 'CRLF' aka '\r\n', or just the end of the packet, will
result in a protocol error.
但是从错误消息中,我可以看到 \r
char 存在于 put 中,这在设计上是不可接受的。所以使用 \n
作为行尾。