将Prometheus指标转换为Json使用Golang

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

Transform Prometheus Metrics to Json with Golang

问题

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

例如,Prometheus 指标数据如下:

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

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

  1. {
  2. "http_requests_total": [
  3. {
  4. "http_requests_total": {
  5. "code": "200",
  6. "method": "GET",
  7. "value": 28
  8. }
  9. },
  10. {
  11. "http_requests_total": {
  12. "code": "200",
  13. "method": "POST",
  14. "value": 3
  15. }
  16. }
  17. ]
  18. }
英文:

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:

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

The JSON I want to convert:

  1. {
  2. "http_requests_total": [
  3. {
  4. "http_requests_total": {
  5. "code": "200",
  6. "method": "GET",
  7. "value": 28
  8. }
  9. },
  10. {
  11. "http_requests_total": {
  12. "code": "200",
  13. "method": "POST",
  14. "value": 3
  15. }
  16. }
  17. ]
  18. }

答案1

得分: 1

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

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "log"
  6. "os"
  7. "strings"
  8. dto "github.com/prometheus/client_model/go"
  9. "github.com/prometheus/common/expfmt"
  10. )
  11. func main() {
  12. if err := run(); err != nil {
  13. log.Fatal(err)
  14. }
  15. }
  16. func run() error {
  17. str := `# TYPE http_requests_total counter
  18. http_requests_total{code="200",method="GET"} 28
  19. http_requests_total{code="200",method="POST"} 3
  20. `
  21. parser := &expfmt.TextParser{}
  22. families, err := parser.TextToMetricFamilies(strings.NewReader(str))
  23. if err != nil {
  24. return fmt.Errorf("failed to parse input: %w", err)
  25. }
  26. out := make(map[string][]map[string]map[string]interface{})
  27. for key, val := range families {
  28. family := out[key]
  29. for _, m := range val.GetMetric() {
  30. metric := make(map[string]interface{})
  31. for _, label := range m.GetLabel() {
  32. metric[label.GetName()] = label.GetValue()
  33. }
  34. switch val.GetType() {
  35. case dto.MetricType_COUNTER:
  36. metric["value"] = m.GetCounter().GetValue()
  37. case dto.MetricType_GAUGE:
  38. metric["value"] = m.GetGauge().GetValue()
  39. default:
  40. return fmt.Errorf("unsupported type: %v", val.GetType())
  41. }
  42. family = append(family, map[string]map[string]interface{}{
  43. val.GetName(): metric,
  44. })
  45. }
  46. out[key] = family
  47. }
  48. enc := json.NewEncoder(os.Stdout)
  49. enc.SetIndent("", " ")
  50. if err = enc.Encode(out); err != nil {
  51. return fmt.Errorf("failed to encode json: %w", err)
  52. }
  53. return nil
  54. }

输出结果:

  1. {
  2. "http_requests_total": [
  3. {
  4. "http_requests_total": {
  5. "code": "200",
  6. "method": "GET",
  7. "value": 28
  8. }
  9. },
  10. {
  11. "http_requests_total": {
  12. "code": "200",
  13. "method": "POST",
  14. "value": 3
  15. }
  16. }
  17. ]
  18. }

希望对你有帮助!

英文:

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.

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "log"
  6. "os"
  7. "strings"
  8. dto "github.com/prometheus/client_model/go"
  9. "github.com/prometheus/common/expfmt"
  10. )
  11. func main() {
  12. if err := run(); err != nil {
  13. log.Fatal(err)
  14. }
  15. }
  16. func run() error {
  17. str := `# TYPE http_requests_total counter
  18. http_requests_total{code="200",method="GET"} 28
  19. http_requests_total{code="200",method="POST"} 3
  20. `
  21. parser := &expfmt.TextParser{}
  22. families, err := parser.TextToMetricFamilies(strings.NewReader(str))
  23. if err != nil {
  24. return fmt.Errorf("failed to parse input: %w", err)
  25. }
  26. out := make(map[string][]map[string]map[string]any)
  27. for key, val := range families {
  28. family := out[key]
  29. for _, m := range val.GetMetric() {
  30. metric := make(map[string]any)
  31. for _, label := range m.GetLabel() {
  32. metric[label.GetName()] = label.GetValue()
  33. }
  34. switch val.GetType() {
  35. case dto.MetricType_COUNTER:
  36. metric["value"] = m.GetCounter().GetValue()
  37. case dto.MetricType_GAUGE:
  38. metric["value"] = m.GetGauge().GetValue()
  39. default:
  40. return fmt.Errorf("unsupported type: %v", val.GetType())
  41. }
  42. family = append(family, map[string]map[string]any{
  43. val.GetName(): metric,
  44. })
  45. }
  46. out[key] = family
  47. }
  48. enc := json.NewEncoder(os.Stdout)
  49. enc.SetIndent("", " ")
  50. if err = enc.Encode(out); err != nil {
  51. return fmt.Errorf("failed to encode json: %w", err)
  52. }
  53. return nil
  54. }

Output:

  1. {
  2. "http_requests_total": [
  3. {
  4. "http_requests_total": {
  5. "code": "200",
  6. "method": "GET",
  7. "value": 28
  8. }
  9. },
  10. {
  11. "http_requests_total": {
  12. "code": "200",
  13. "method": "POST",
  14. "value": 3
  15. }
  16. }
  17. ]
  18. }

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:

确定