TimingsPlotReporter
This commit is contained in:
11
lib/reporter.go
Normal file
11
lib/reporter.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package vegeta
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Reporter represents any reporter of the results of the test
|
||||
type Reporter interface {
|
||||
Report(io.Writer) error
|
||||
add(res *result)
|
||||
}
|
||||
@@ -7,12 +7,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Reporter represents any reporter of the results of the test
|
||||
type Reporter interface {
|
||||
Report(io.Writer) error
|
||||
add(res *result)
|
||||
}
|
||||
|
||||
// TextReporter prints the test results as text
|
||||
// Metrics incude avg time per request, success ratio,
|
||||
// total number of request, avg bytes in and avg bytes out
|
||||
90
lib/timings_plot_reporter.go
Normal file
90
lib/timings_plot_reporter.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package vegeta
|
||||
|
||||
import (
|
||||
"code.google.com/p/plotinum/plot"
|
||||
"code.google.com/p/plotinum/plotter"
|
||||
"code.google.com/p/plotinum/plotutil"
|
||||
"code.google.com/p/plotinum/vg"
|
||||
"code.google.com/p/plotinum/vg/vgsvg"
|
||||
"container/list"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TimingsPlotReporter struct {
|
||||
responses *list.List
|
||||
}
|
||||
|
||||
// NewTimingsPlotReporter initializes a TimingsPlotReporter
|
||||
func NewTimingsPlotReporter() *TimingsPlotReporter {
|
||||
return &TimingsPlotReporter{responses: list.New()}
|
||||
}
|
||||
|
||||
// add inserts response to be used in the report, sorted by timestamp.
|
||||
func (r *TimingsPlotReporter) add(res *result) {
|
||||
// Empty list
|
||||
if r.responses.Len() == 0 {
|
||||
r.responses.PushFront(res)
|
||||
return
|
||||
}
|
||||
// Happened after all others
|
||||
if last := r.responses.Back().Value.(*result); last.timestamp.Before(res.timestamp) {
|
||||
r.responses.PushBack(res)
|
||||
return
|
||||
}
|
||||
// Happened before all others
|
||||
if first := r.responses.Front().Value.(*result); first.timestamp.After(res.timestamp) {
|
||||
r.responses.PushFront(res)
|
||||
return
|
||||
}
|
||||
// O(n) worst case insertion time
|
||||
for e := r.responses.Front(); e != nil; e = e.Next() {
|
||||
needle := e.Value.(*result)
|
||||
if res.timestamp.Before(needle.timestamp) {
|
||||
r.responses.InsertBefore(res, e)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Report builds up a plot of the response times of the requests
|
||||
// in SVG format and writes it to out
|
||||
func (r *TimingsPlotReporter) Report(out io.Writer) error {
|
||||
timestamps := make([]time.Time, 0)
|
||||
timings := make([]time.Duration, 0)
|
||||
|
||||
for e := r.responses.Front(); e != nil; e = e.Next() {
|
||||
r := e.Value.(*result)
|
||||
timestamps = append(timestamps, r.timestamp)
|
||||
timings = append(timings, r.timing)
|
||||
}
|
||||
|
||||
p, err := plot.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pts := make(plotter.XYs, len(timestamps))
|
||||
for i := 0; i < len(pts); i++ {
|
||||
pts[i].X = timestamps[i].Sub(timestamps[0]).Seconds()
|
||||
pts[i].Y = timings[i].Seconds()
|
||||
}
|
||||
|
||||
line, err := plotter.NewLine(pts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
line.Color = plotutil.Color(1)
|
||||
|
||||
p.Add(line)
|
||||
p.X.Padding = vg.Length(3.0)
|
||||
p.X.Label.Text = "Time elapsed"
|
||||
p.Y.Padding = vg.Length(3.0)
|
||||
p.Y.Label.Text = "Latency (seconds)"
|
||||
|
||||
w, h := vg.Millimeters(float64(len(timestamps))), vg.Centimeters(12.0)
|
||||
canvas := vgsvg.New(w, h)
|
||||
p.Draw(plot.MakeDrawArea(canvas))
|
||||
|
||||
_, err = canvas.WriteTo(out)
|
||||
return err
|
||||
}
|
||||
6
main.go
6
main.go
@@ -20,7 +20,7 @@ func main() {
|
||||
targetsf = flag.String("targets", "targets.txt", "Targets file")
|
||||
ordering = flag.String("ordering", "random", "Attack ordering [sequential, random]")
|
||||
duration = flag.Duration("duration", 10*time.Second, "Duration of the test")
|
||||
reporter = flag.String("reporter", "text", "Reporter to use [text]")
|
||||
reporter = flag.String("reporter", "text", "Reporter to use [text, plot:timings]")
|
||||
output = flag.String("output", "stdout", "Reporter output file")
|
||||
)
|
||||
flag.Parse()
|
||||
@@ -56,8 +56,10 @@ func main() {
|
||||
switch *reporter {
|
||||
case "text":
|
||||
rep = vegeta.NewTextReporter()
|
||||
case "plot:timings":
|
||||
rep = vegeta.NewTimingsPlotReporter()
|
||||
default:
|
||||
log.Println("reporter provided is not supported. using text")
|
||||
log.Println("Reporter provided is not supported. using text")
|
||||
rep = vegeta.NewTextReporter()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user