github.com/grafana/pyroscope@v1.18.0/tools/monitoring-chart-extractor/main.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "errors" 6 "flag" 7 "fmt" 8 "io" 9 "log" 10 "os" 11 "path/filepath" 12 "strings" 13 14 "go.yaml.in/yaml/v3" 15 ) 16 17 func main() { 18 outputPath := flag.CommandLine.String("output.path", "./operations/monitoring/", "Provide the output path for the code generation. Warning: All existing files will be overwritten.") 19 flag.Parse() 20 21 if err := run(*outputPath); err != nil { 22 log.Fatal(err) 23 } 24 } 25 26 func outputRules(outputPath string, fileName string, body []byte) error { 27 if fileName == "prometheus.yaml" { 28 return nil 29 } 30 path := filepath.Join(outputPath, "rules", fileName) 31 32 if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { 33 return err 34 } 35 36 return os.WriteFile(path, body, 0644) 37 } 38 39 func outputDashboards(outputPath string, fileName string, body []byte) error { 40 path := filepath.Join(outputPath, "dashboards", fileName) 41 42 if !strings.HasSuffix(path, ".json") { 43 return nil 44 } 45 46 data := map[string]any{} 47 if err := json.Unmarshal(body, &data); err != nil { 48 return fmt.Errorf("error Unmarshalling body of '%s': %w", fileName, err) 49 } 50 51 bodyFormatted, err := json.MarshalIndent(data, "", " ") 52 if err != nil { 53 return fmt.Errorf("error marshalling body of '%s': %w", fileName, err) 54 } 55 56 if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { 57 return err 58 } 59 60 return os.WriteFile(path, bodyFormatted, 0644) 61 } 62 63 func run(outputPath string) error { 64 d := yaml.NewDecoder(os.Stdin) 65 obj := map[string]any{} 66 67 for { 68 err := d.Decode(&obj) 69 if err != nil { 70 if err == io.EOF { 71 return nil 72 } 73 return err 74 } 75 76 metaIntf, ok := obj["metadata"] 77 if !ok { 78 return errors.New("metadata not found") 79 } 80 81 meta, ok := metaIntf.(map[string]any) 82 if !ok { 83 return fmt.Errorf("metadata not object: %T", metaIntf) 84 } 85 86 nameIntf, ok := meta["name"] 87 if !ok { 88 return errors.New("name not found") 89 } 90 91 name, ok := nameIntf.(string) 92 if !ok { 93 return errors.New("name not string") 94 } 95 96 var handle func(string, string, []byte) error 97 98 switch name { 99 case "pyroscope-monitoring-dashboards": 100 handle = outputDashboards 101 case "pyroscope-monitoring-rules": 102 handle = outputRules 103 default: 104 continue 105 } 106 107 dataIntf, ok := obj["data"] 108 if !ok { 109 return errors.New("data not found") 110 } 111 112 data, ok := dataIntf.(map[string]any) 113 if !ok { 114 return fmt.Errorf("data not object: %T", dataIntf) 115 } 116 117 for key, bodyIntf := range data { 118 body, ok := bodyIntf.(string) 119 if !ok { 120 continue 121 } 122 if err := handle(outputPath, key, []byte(body)); err != nil { 123 return err 124 } 125 } 126 } 127 }