Skip to content

Commit

Permalink
CSV output
Browse files Browse the repository at this point in the history
Signed-off-by: Raul Sevilla <rsevilla@redhat.com>
  • Loading branch information
rsevilla87 committed Nov 3, 2023
1 parent 96e3f33 commit 4c56887
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 6 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,33 @@ Flags:
-k, --keepalive Enable HTTP keepalive (default true)
--http2 Use HTTP2 protocol, if possible (default true)
--pprof Enable pprof endpoint in localhost:6060
-o, --output string Dump request outputs in the given CSV file
-h, --help help for ./bin/hloader
```
## Compilation
```
```shell
$ make build
GOARCH=amd64 CGO_ENABLED=0 go build -v -ldflags "-X github.com/cloud-bulldozer/go-commons/version.GitCommit=a5c03b3c983255096635b872d4153c98419f8bd1 -X github.com/cloud-bulldozer/go-commons/version.Version=main -X github.com/cloud-bulldozer/go-commons/version.BuildDate=2023-10-24-12:13:18" -o bin/hloader cmd/hloader.go
```
## CSV output
The csv output has the following format:
```csv
1699016948650,200,276028,537,false,false
<timestamp in milliseconds>,<status code>,<latency in microseconds>,<bytes read>,<timeout>,<http error>
```
Like for example:
```csv
1699016948640,200,283085,537,false,false
1699016948650,200,276028,537,false,false
1699016948670,200,255849,537,false,false
1699016948700,200,225850,537,false,false
1699016948709,200,216579,537,false,false
```
4 changes: 3 additions & 1 deletion cmd/hloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func main() {
var requestRate, connections int
var url string
var pprof, http2, insecure, keepalive bool
var csv string
rootCmd := &cobra.Command{
Use: fmt.Sprintf(os.Args[0]),
Short: "HTTP loader",
Expand All @@ -43,7 +44,7 @@ func main() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
}
l := loader.NewLoader(duration, requestTimeout, requestRate, connections, url, insecure, keepalive, http2)
l := loader.NewLoader(duration, requestTimeout, requestRate, connections, url, insecure, keepalive, http2, csv)
return l.Run()
},
}
Expand All @@ -56,6 +57,7 @@ func main() {
rootCmd.Flags().BoolVarP(&keepalive, "keepalive", "k", true, "Enable HTTP keepalive")
rootCmd.Flags().BoolVar(&http2, "http2", true, "Use HTTP2 protocol, if possible")
rootCmd.Flags().BoolVar(&pprof, "pprof", false, "Enable pprof endpoint in localhost:6060")
rootCmd.Flags().StringVarP(&csv, "output", "o", "", "Dump request outputs in the given CSV file")
rootCmd.Flags().SortFlags = false
rootCmd.MarkFlagRequired("url")
rootCmd.AddCommand(versionCmd)
Expand Down
5 changes: 3 additions & 2 deletions pkg/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"golang.org/x/time/rate"
)

func NewLoader(duration, requestTimeout time.Duration, requestRate, connections int, url string, insecure, keepalive, http2 bool) Loader {
func NewLoader(duration, requestTimeout time.Duration, requestRate, connections int, url string, insecure, keepalive, http2 bool, csv string) Loader {
var limit rate.Limit
if requestRate > 0 {
limit = rate.Limit(requestRate + 1) // We add 1 to count the main goroutine
Expand All @@ -29,6 +29,7 @@ func NewLoader(duration, requestTimeout time.Duration, requestRate, connections
keepalive: keepalive,
limiter: rate.NewLimiter(limit, 1),
http2: http2,
csv: csv,
}
}

Expand All @@ -55,7 +56,7 @@ out:
close(stopCh)
wg.Wait()
l.duration = time.Since(now)
err := normaliceResults(l.results, l.duration)
err := normaliceResults(l.results, l.duration, l.csv)
if err != nil {
fmt.Println(err)
os.Exit(1)
Expand Down
29 changes: 27 additions & 2 deletions pkg/loader/results.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,47 @@
package loader

import (
"encoding/csv"
"encoding/json"
"fmt"
"math"
"net/http"
"os"
"strconv"
"time"

"github.com/montanaflynn/stats"
)

func normaliceResults(results []requestResult, duration time.Duration) error {
func normaliceResults(results []requestResult, duration time.Duration, csvFile string) error {
var latencies []float64
var totalRead int64
var csvWriter *csv.Writer
var err error
var f *os.File
if csvFile != "" {
f, err = os.Create(csvFile)
if err != nil {
return err
}
csvWriter = csv.NewWriter(f)
}
result := testResult{
StatusCodes: make(map[int]int64),
}
for _, r := range results {
if csvFile != "" {
line := []string{
strconv.FormatInt(r.timestamp.UnixMilli(), 10),
strconv.Itoa(r.code),
strconv.FormatInt(r.latency, 10),
strconv.FormatInt(r.bytesRead, 10),
strconv.FormatBool(r.timeout),
strconv.FormatBool(r.readError),
}
csvWriter.Write(line)
csvWriter.Flush()
}
result.StatusCodes[r.code]++
if r.timeout {
result.Timeouts++
Expand All @@ -37,7 +62,7 @@ func normaliceResults(results []requestResult, duration time.Duration) error {
result.P99Latency, _ = stats.Percentile(latencies, 99)
result.LatencyStdev, _ = stats.StandardDeviation(latencies)
result.LatencyStdev, _ = stats.Round(result.LatencyStdev, 2)
jsonResult, err := json.Marshal(&result)
jsonResult, err := json.MarshalIndent(&result, "", " ")
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions pkg/loader/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Loader struct {
results []requestResult
limiter *rate.Limiter
http2 bool
csv string
sync.Mutex
}

Expand Down

0 comments on commit 4c56887

Please sign in to comment.