英文:
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
			}
		}
	]
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论