ReportJSON

This commit is contained in:
Tomás Senart
2013-09-10 13:45:01 +01:00
parent 6e9f34846b
commit ee9a1a0954
4 changed files with 42 additions and 15 deletions

View File

@@ -30,7 +30,7 @@ Usage of vegeta:
-ordering="random": Attack ordering [sequential, random] -ordering="random": Attack ordering [sequential, random]
-output="stdout": Reporter output file -output="stdout": Reporter output file
-rate=50: Requests per second -rate=50: Requests per second
-reporter="text": Reporter to use [text, plot:timings] -reporter="text": Reporter to use [text, json, plot:timings]
-targets="targets.txt": Targets file -targets="targets.txt": Targets file
``` ```
@@ -75,6 +75,24 @@ Error Set:
Server Timeout Server Timeout
Page Not Found Page Not Found
``` ```
##### -reporter=json
```json
{
"total_requests": 50,
"total_timing": 34779791,
"mean_timing": 695595,
"total_bytes_in": 272850,
"mean_bytes_in": 5457,
"total_bytes_out": 0,
"mean_bytes_out": 0,
"total_success": 50,
"mean_success": 1,
"status_codes": {
"200": 50
},
"errors": []
}
```
##### -reporter=plot:timings ##### -reporter=plot:timings
Plots the request timings in SVG format. Plots the request timings in SVG format.
![plot](https://dl.dropboxusercontent.com/u/83217940/plot.svg) ![plot](https://dl.dropboxusercontent.com/u/83217940/plot.svg)

View File

@@ -1,35 +1,36 @@
package vegeta package vegeta
import ( import (
"strconv"
"time" "time"
) )
// Metrics holds the stats computed out of a slice of Results // Metrics holds the stats computed out of a slice of Results
// that is used for some of the Reporters // that is used for some of the Reporters
type Metrics struct { type Metrics struct {
TotalRequests uint64 `json:"total_requests"` TotalRequests uint64 `json:"total_requests"`
TotalTiming time.Duration `json:"total_timing"` TotalTiming time.Duration `json:"total_timing"`
MeanTiming time.Duration `json:"mean_timing"` MeanTiming time.Duration `json:"mean_timing"`
TotalBytesIn uint64 `json:"total_bytes_in"` TotalBytesIn uint64 `json:"total_bytes_in"`
MeanBytesIn float64 `json:"mean_bytes_in"` MeanBytesIn float64 `json:"mean_bytes_in"`
TotalBytesOut uint64 `json:"total_bytes_out"` TotalBytesOut uint64 `json:"total_bytes_out"`
MeanBytesOut float64 `json:"mean_bytes_out"` MeanBytesOut float64 `json:"mean_bytes_out"`
TotalSuccess uint64 `json:"total_success"` TotalSuccess uint64 `json:"total_success"`
MeanSuccess float64 `json:"mean_success"` MeanSuccess float64 `json:"mean_success"`
StatusCodes map[uint16]uint64 `json:"status_codes"` StatusCodes map[string]int `json:"status_codes"`
Errors []string `json:"errors"` Errors []string `json:"errors"`
} }
// NewMetrics computes and returns a Metrics struct out of a slice of Results // NewMetrics computes and returns a Metrics struct out of a slice of Results
func NewMetrics(results []Result) *Metrics { func NewMetrics(results []Result) *Metrics {
m := &Metrics{ m := &Metrics{
TotalRequests: uint64(len(results)), TotalRequests: uint64(len(results)),
StatusCodes: map[uint16]uint64{}, StatusCodes: map[string]int{},
} }
errorSet := map[string]struct{}{} errorSet := map[string]struct{}{}
for _, result := range results { for _, result := range results {
m.StatusCodes[result.Code]++ m.StatusCodes[strconv.Itoa(int(result.Code))]++
m.TotalTiming += result.Timing m.TotalTiming += result.Timing
m.TotalBytesOut += result.BytesOut m.TotalBytesOut += result.BytesOut
m.TotalBytesIn += result.BytesIn m.TotalBytesIn += result.BytesIn

View File

@@ -6,6 +6,7 @@ import (
"code.google.com/p/plotinum/plotutil" "code.google.com/p/plotinum/plotutil"
"code.google.com/p/plotinum/vg" "code.google.com/p/plotinum/vg"
"code.google.com/p/plotinum/vg/vgsvg" "code.google.com/p/plotinum/vg/vgsvg"
"encoding/json"
"fmt" "fmt"
"io" "io"
"text/tabwriter" "text/tabwriter"
@@ -41,6 +42,11 @@ func ReportText(results []Result, out io.Writer) error {
return w.Flush() return w.Flush()
} }
// ReportJSON writes a computed Metrics struct to out as JSON
func ReportJSON(results []Result, out io.Writer) error {
return json.NewEncoder(out).Encode(NewMetrics(results))
}
// ReportTimingsPlot builds up a plot of the response times of the requests // ReportTimingsPlot builds up a plot of the response times of the requests
// in SVG format and writes it to out // in SVG format and writes it to out
func ReportTimingsPlot(results []Result, out io.Writer) error { func ReportTimingsPlot(results []Result, out io.Writer) error {

View File

@@ -17,7 +17,7 @@ func main() {
targetsf = flag.String("targets", "targets.txt", "Targets file") targetsf = flag.String("targets", "targets.txt", "Targets file")
ordering = flag.String("ordering", "random", "Attack ordering [sequential, random]") ordering = flag.String("ordering", "random", "Attack ordering [sequential, random]")
duration = flag.Duration("duration", 10*time.Second, "Duration of the test") duration = flag.Duration("duration", 10*time.Second, "Duration of the test")
reporter = flag.String("reporter", "text", "Reporter to use [text, plot:timings]") reporter = flag.String("reporter", "text", "Reporter to use [text, json, plot:timings]")
output = flag.String("output", "stdout", "Reporter output file") output = flag.String("output", "stdout", "Reporter output file")
cpus = flag.Int("cpus", runtime.NumCPU(), "Number of CPUs to use") cpus = flag.Int("cpus", runtime.NumCPU(), "Number of CPUs to use")
) )
@@ -72,6 +72,8 @@ func run(rate uint64, duration time.Duration, targetsf, ordering, reporter, outp
switch reporter { switch reporter {
case "text": case "text":
rep = vegeta.ReportText rep = vegeta.ReportText
case "json":
rep = vegeta.ReportJSON
case "plot:timings": case "plot:timings":
rep = vegeta.ReportTimingsPlot rep = vegeta.ReportTimingsPlot
default: default: