github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/benchmark/internal/cireport/metareport.go (about) 1 package cireport 2 3 import ( 4 "fmt" 5 "strings" 6 "text/template" 7 8 "github.com/sirupsen/logrus" 9 ) 10 11 type MetaReport struct { 12 allowlist map[string]bool 13 } 14 15 // NewMetaReport creates a meta report 16 // the allowlist parameter refers to which keys are valid 17 func NewMetaReport(allowlist []string) (*MetaReport, error) { 18 if len(allowlist) <= 0 { 19 return nil, fmt.Errorf("at least one item should be allowed") 20 } 21 22 a := make(map[string]bool) 23 for _, v := range allowlist { 24 a[v] = true 25 } 26 27 return &MetaReport{ 28 allowlist: a, 29 }, nil 30 } 31 32 type meta struct { 33 Key string 34 Val string 35 } 36 37 // Report generates a markdown report 38 func (mr *MetaReport) Report(title string, vars []string) (string, error) { 39 if len(vars) <= 0 { 40 return "", fmt.Errorf("at least one item should be reported") 41 } 42 43 // transform 'A=B' into {key: A, val: B} 44 m := make([]meta, 0, len(vars)) 45 for _, v := range vars { 46 key, val, err := mr.breakOnEqual(v) 47 logrus.Debugf("breaking string %s on '=' produces key %s value %s\n", v, key, val) 48 if err != nil { 49 return "", err 50 } 51 52 n := meta{key, val} 53 m = append(m, n) 54 } 55 56 // validate it's in the allowlist 57 logrus.Debug("validating there're no values not in the allowlist") 58 err := mr.validate(m) 59 if err != nil { 60 return "", err 61 } 62 63 logrus.Debug("generating template") 64 report, err := mr.tpl(title, m) 65 if err != nil { 66 return "", err 67 } 68 69 return report, nil 70 } 71 72 func (*MetaReport) breakOnEqual(s string) (key string, value string, err error) { 73 split := strings.Split(s, "=") 74 if len(split) != 2 { 75 return "", "", fmt.Errorf("expect value in format A=B") 76 } 77 78 if split[0] == "" || split[1] == "" { 79 return "", "", fmt.Errorf("expect non empty key/value") 80 } 81 82 return split[0], split[1], nil 83 } 84 85 func (mr *MetaReport) validate(m []meta) error { 86 for _, v := range m { 87 if _, ok := mr.allowlist[v.Key]; !ok { 88 return fmt.Errorf("key is not allowed: '%s'", v.Key) 89 } 90 } 91 92 return nil 93 } 94 95 func (*MetaReport) tpl(title string, m []meta) (string, error) { 96 var tpl strings.Builder 97 98 data := struct { 99 Title string 100 Meta []meta 101 }{ 102 Title: title, 103 Meta: m, 104 } 105 t, err := template.New("meta-report.gotpl"). 106 ParseFS(resources, "resources/meta-report.gotpl") 107 108 if err != nil { 109 return "", err 110 } 111 112 if err := t.Execute(&tpl, data); err != nil { 113 return "", err 114 } 115 116 return tpl.String(), nil 117 }