github.com/kubeshop/testkube@v1.17.23/contrib/executor/jmeterd/pkg/parser/csvjtl.go (about) 1 package parser 2 3 import ( 4 "encoding/csv" 5 "errors" 6 "io" 7 "strconv" 8 "time" 9 10 "github.com/kubeshop/testkube/pkg/executor/output" 11 "github.com/kubeshop/testkube/pkg/ui" 12 ) 13 14 type CSVResults struct { 15 HasError bool 16 LastErrorMessage string 17 Results []CSVResult 18 } 19 20 type CSVResult struct { 21 Success bool 22 Error string 23 Label string 24 ResponseCode string 25 Duration time.Duration 26 } 27 28 func parseCSV(reader io.Reader) (results CSVResults, err error) { 29 res, err := CSVToMap(reader) 30 if err != nil { 31 return 32 } 33 34 for _, r := range res { 35 result := MapElementToResult(r) 36 results.Results = append(results.Results, result) 37 38 if !result.Success { 39 results.HasError = true 40 results.LastErrorMessage = result.Error 41 } 42 } 43 44 return 45 } 46 47 // CSVToMap takes a reader and returns an array of dictionaries, using the header row as the keys 48 func CSVToMap(reader io.Reader) ([]map[string]string, error) { 49 r := csv.NewReader(reader) 50 var rows []map[string]string 51 var header []string 52 for { 53 record, err := r.Read() 54 if err != nil { 55 if errors.Is(err, io.EOF) { 56 break 57 } 58 return nil, err 59 } 60 if header == nil { 61 header = record 62 } else { 63 dict := map[string]string{} 64 for i := range header { 65 dict[header[i]] = record[i] 66 } 67 rows = append(rows, dict) 68 } 69 } 70 return rows, nil 71 } 72 73 func MapElementToResult(in map[string]string) CSVResult { 74 elapsed, err := strconv.Atoi(in["elapsed"]) 75 if err != nil { 76 output.PrintLogf("%s Error parsing elapsed time to int from JTL report: %s", ui.IconWarning, err.Error()) 77 } 78 79 return CSVResult{ 80 Success: in["success"] == "true", 81 Error: in["failureMessage"], 82 Label: in["label"], 83 Duration: time.Millisecond * time.Duration(elapsed), 84 ResponseCode: in["responseCode"], 85 } 86 }