diff --git a/README.md b/README.md index ed978533..8af9496b 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,9 @@ Options: -o Output path. If none provided stdout is used. -O Output type. If none provided, a summary is printed. - "json" outputs the metrics report in JSON format. "csv" outputs the response metrics in comma-separated values format. + "json" outputs the metrics report in JSON format. + "pretty" outputs the metrics report in pretty JSON format. -i Comma separated list of proto import paths. The current working directory and the directory of the protocol buffer file are automatically added to the import list. diff --git a/cmd/grpcannon/main.go b/cmd/grpcannon/main.go index 3aeadd50..809e5f02 100644 --- a/cmd/grpcannon/main.go +++ b/cmd/grpcannon/main.go @@ -82,8 +82,9 @@ Options: -o Output path. If none provided stdout is used. -O Output type. If none provided, a summary is printed. - "json" outputs the metrics report in JSON format. "csv" outputs the response metrics in comma-separated values format. + "json" outputs the metrics report in JSON format. + "pretty" outputs the metrics report in pretty JSON format. -i Comma separated list of proto import paths. The current working directory and the directory of the protocol buffer file are automatically added to the import list. diff --git a/printer/printer.go b/printer/printer.go index cb6e3ee0..e9d58056 100644 --- a/printer/printer.go +++ b/printer/printer.go @@ -42,12 +42,23 @@ func (rp *ReportPrinter) Print(format string) { rp.printf(buf.String()) rp.printf("\n") - case "json": + case "json", "pretty": rep, err := json.Marshal(*rp.Report) if err != nil { log.Println("error:", err.Error()) return } + + if format == "pretty" { + var out bytes.Buffer + err = json.Indent(&out, rep, "", " ") + if err != nil { + log.Println("error:", err.Error()) + return + } + rep = out.Bytes() + } + rp.printf(string(rep)) } } diff --git a/reporter.go b/reporter.go index 6fa673bb..f45fd5a4 100644 --- a/reporter.go +++ b/reporter.go @@ -23,39 +23,44 @@ type Reporter struct { // Report holds the data for the full test type Report struct { - Count uint64 - Total time.Duration - Average time.Duration - Fastest time.Duration - Slowest time.Duration - Rps float64 - - ErrorDist map[string]int - StatusCodeDist map[string]int - - LatencyDistribution []LatencyDistribution - Histogram []Bucket - Details []ResultDetail + Count uint64 `json:"count"` + Total time.Duration `json:"total"` + Average time.Duration `json:"average"` + Fastest time.Duration `json:"fastest"` + Slowest time.Duration `json:"slowest"` + Rps float64 `json:"rps"` + + ErrorDist map[string]int `json:"errorDistribution"` + StatusCodeDist map[string]int `json:"statusCodeDistribution"` + + LatencyDistribution []LatencyDistribution `json:"latencyDistribution"` + Histogram []Bucket `json:"histogram"` + Details []ResultDetail `json:"details"` } // LatencyDistribution holds latency distribution data type LatencyDistribution struct { - Percentage int - Latency time.Duration + Percentage int `json:"percentage"` + Latency time.Duration `json:"latency"` } // Bucket holds histogram data type Bucket struct { - Mark float64 // The Mark for histogram bucket in seconds - Count int // The count in the bucket - Frequency float64 // The frequency of results in the bucket as a decimal percentage + // The Mark for histogram bucket in seconds + Mark float64 `json:"mark"` + + // The count in the bucket + Count int `json:"count"` + + // The frequency of results in the bucket as a decimal percentage + Frequency float64 `json:"frequency"` } // ResultDetail data for each result type ResultDetail struct { - Latency time.Duration - Error string - Status string + Latency time.Duration `json:"latency"` + Error string `json:"error"` + Status string `json:"status"` } func newReporter(results chan *callResult, n int) *Reporter {