将Prometheus指标转换为Json使用Golang

huangapple go评论91阅读模式
英文:

Transform Prometheus Metrics to Json with Golang

问题

我有一些 Prometheus 指标数据,想要使用 Golang 将其转换为 JSON 格式。我写了一些代码,但没有成功。

例如,Prometheus 指标数据如下:

# TYPE http_requests_total counter 
http_requests_total{code="200",method="GET"} 28 
http_requests_total{code="200",method="POST"} 3

我想要转换成的 JSON 格式如下:

{
	"http_requests_total": [
		{
			"http_requests_total": {
				"code": "200",
				"method": "GET",
				"value": 28
			}
		},
		{
			"http_requests_total": {
				"code": "200",
				"method": "POST",
				"value": 3
			}
		}
	]
}
英文:

I have prometgeus metrics and I want to convert it to json format using golang. I wrote some code but without success.

For example: Prometheus Metric:

# TYPE http_requests_total counter 
http_requests_total{code="200",method="GET"} 28 
http_requests_total{code="200",method="POST"} 3

The JSON I want to convert:

{
	"http_requests_total": [
		{
			"http_requests_total": {
				"code": "200",
				"method": "GET",
				"value": 28
			}
		},
		{
			"http_requests_total": {
				"code": "200",
				"method": "POST",
				"value": 3
			}
		}
	]
}

答案1

得分: 1

我假设你希望这段代码具有灵活性,即不仅仅处理特定的指标。如果是这样的话,下面的代码应该可以解决问题。

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strings"

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

func main() {
	if err := run(); err != nil {
		log.Fatal(err)
	}
}

func run() error {
	str := `# TYPE http_requests_total counter
http_requests_total{code="200",method="GET"} 28
http_requests_total{code="200",method="POST"} 3
`

	parser := &expfmt.TextParser{}
	families, err := parser.TextToMetricFamilies(strings.NewReader(str))
	if err != nil {
		return fmt.Errorf("failed to parse input: %w", err)
	}

	out := make(map[string][]map[string]map[string]interface{})

	for key, val := range families {
		family := out[key]

		for _, m := range val.GetMetric() {
			metric := make(map[string]interface{})
			for _, label := range m.GetLabel() {
				metric[label.GetName()] = label.GetValue()
			}
			switch val.GetType() {
			case dto.MetricType_COUNTER:
				metric["value"] = m.GetCounter().GetValue()
			case dto.MetricType_GAUGE:
				metric["value"] = m.GetGauge().GetValue()
			default:
				return fmt.Errorf("unsupported type: %v", val.GetType())
			}
			family = append(family, map[string]map[string]interface{}{
				val.GetName(): metric,
			})
		}

		out[key] = family
	}

	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "    ")
	if err = enc.Encode(out); err != nil {
		return fmt.Errorf("failed to encode json: %w", err)
	}

	return nil
}

输出结果:

{
    "http_requests_total": [
        {
            "http_requests_total": {
                "code": "200",
                "method": "GET",
                "value": 28
            }
        },
        {
            "http_requests_total": {
                "code": "200",
                "method": "POST",
                "value": 3
            }
        }
    ]
}

希望对你有帮助!

英文:

I'm assuming you're looking for this to be flexible, i.e. not just handling those specific metrics? If so, the following code should do the trick.

package main
import (
"encoding/json"
"fmt"
"log"
"os"
"strings"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
)
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}
func run() error {
str := `# TYPE http_requests_total counter
http_requests_total{code="200",method="GET"} 28
http_requests_total{code="200",method="POST"} 3
`
parser := &expfmt.TextParser{}
families, err := parser.TextToMetricFamilies(strings.NewReader(str))
if err != nil {
return fmt.Errorf("failed to parse input: %w", err)
}
out := make(map[string][]map[string]map[string]any)
for key, val := range families {
family := out[key]
for _, m := range val.GetMetric() {
metric := make(map[string]any)
for _, label := range m.GetLabel() {
metric[label.GetName()] = label.GetValue()
}
switch val.GetType() {
case dto.MetricType_COUNTER:
metric["value"] = m.GetCounter().GetValue()
case dto.MetricType_GAUGE:
metric["value"] = m.GetGauge().GetValue()
default:
return fmt.Errorf("unsupported type: %v", val.GetType())
}
family = append(family, map[string]map[string]any{
val.GetName(): metric,
})
}
out[key] = family
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", "    ")
if err = enc.Encode(out); err != nil {
return fmt.Errorf("failed to encode json: %w", err)
}
return nil
}

Output:

{
	"http_requests_total": [
		{
			"http_requests_total": {
				"code": "200",
				"method": "GET",
				"value": 28
			}
		},
		{
			"http_requests_total": {
				"code": "200",
				"method": "POST",
				"value": 3
			}
		}
	]
}

huangapple
  • 本文由 发表于 2022年10月29日 19:11:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/74244771.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定