diff --git a/lib/attack.go b/lib/attack.go index 1730f66..971cbe7 100644 --- a/lib/attack.go +++ b/lib/attack.go @@ -13,31 +13,31 @@ import ( func Attack(targets Targets, rate uint64, duration time.Duration, rep Reporter) { hits := make(chan *http.Request, rate*uint64((duration).Seconds())) defer close(hits) - responses := make(chan *result, cap(hits)) - defer close(responses) - go drill(rate, hits, responses) // Attack! + results := make(chan *Result, cap(hits)) + defer close(results) + go drill(rate, hits, results) // Attack! for i := 0; i < cap(hits); i++ { hits <- targets[i%len(targets)] } // Wait for all requests to finish - for i := 0; i < cap(responses); i++ { - rep.add(<-responses) + for i := 0; i < cap(results); i++ { + rep.add(<-results) } } -// result represents the metrics we want out of an http.Response -type result struct { - code uint64 - timestamp time.Time - timing time.Duration - bytesOut uint64 - bytesIn uint64 - err error +// Result represents the metrics we want out of an http.Response +type Result struct { + Code uint64 + Timestamp time.Time + Timing time.Duration + BytesOut uint64 + BytesIn uint64 + Error error } // drill loops over the passed reqs channel and executes each request. // It is throttled to the rate specified. -func drill(rate uint64, reqs chan *http.Request, res chan *result) { +func drill(rate uint64, reqs chan *http.Request, res chan *Result) { throttle := time.Tick(time.Duration(1e9 / rate)) for req := range reqs { <-throttle @@ -48,19 +48,19 @@ func drill(rate uint64, reqs chan *http.Request, res chan *result) { // hit executes the passed http.Request and puts a generated *result into res. // Both transport errors and unsucessfull requests (non {2xx,3xx}) are // considered errors which are set in the Response. -func hit(req *http.Request, res chan *result) { +func hit(req *http.Request, res chan *Result) { began := time.Now() r, err := http.DefaultClient.Do(req) - result := &result{ - timestamp: began, - timing: time.Since(began), - bytesOut: uint64(req.ContentLength), - err: err, + result := &Result{ + Timestamp: began, + Timing: time.Since(began), + BytesOut: uint64(req.ContentLength), + Error: err, } if err == nil { - result.bytesIn, result.code = uint64(r.ContentLength), uint64(r.StatusCode) - if body, err := ioutil.ReadAll(r.Body); err != nil && (result.code < 200 || result.code >= 300) { - result.err = errors.New(string(body)) + result.BytesIn, result.Code = uint64(r.ContentLength), uint64(r.StatusCode) + if body, err := ioutil.ReadAll(r.Body); err != nil && (result.Code < 200 || result.Code >= 300) { + result.Error = errors.New(string(body)) } } diff --git a/lib/reporter.go b/lib/reporter.go index 1a26694..533cc1b 100644 --- a/lib/reporter.go +++ b/lib/reporter.go @@ -7,5 +7,5 @@ import ( // Reporter represents any reporter of the results of the test type Reporter interface { Report(io.Writer) error - add(res *result) + add(res *Result) } diff --git a/lib/text_reporter.go b/lib/text_reporter.go index 7faf129..898e4eb 100644 --- a/lib/text_reporter.go +++ b/lib/text_reporter.go @@ -11,18 +11,18 @@ import ( // Metrics incude avg time per request, success ratio, // total number of request, avg bytes in and avg bytes out type TextReporter struct { - responses []*result + results []*Result } // NewTextReporter initializes a TextReporter with n responses func NewTextReporter() *TextReporter { - return &TextReporter{responses: make([]*result, 0)} + return &TextReporter{results: make([]*Result, 0)} } // Report computes and writes the report to out. // It returns an error in case of failure. func (r *TextReporter) Report(out io.Writer) error { - totalRequests := len(r.responses) + totalRequests := len(r.results) totalTime := time.Duration(0) totalBytesOut := uint64(0) totalBytesIn := uint64(0) @@ -30,16 +30,16 @@ func (r *TextReporter) Report(out io.Writer) error { histogram := map[uint64]uint64{} errors := map[string]struct{}{} - for _, res := range r.responses { - histogram[res.code]++ - totalTime += res.timing - totalBytesOut += res.bytesOut - totalBytesIn += res.bytesIn - if res.code >= 200 && res.code < 300 { + for _, res := range r.results { + histogram[res.Code]++ + totalTime += res.Timing + totalBytesOut += res.BytesOut + totalBytesIn += res.BytesIn + if res.Code >= 200 && res.Code < 300 { totalSuccess++ } - if res.err != nil { - errors[res.err.Error()] = struct{}{} + if res.Error != nil { + errors[res.Error.Error()] = struct{}{} } } @@ -71,6 +71,6 @@ func (r *TextReporter) Report(out io.Writer) error { // add adds a response to be used in the report // Order of arrival is not relevant for this reporter -func (r *TextReporter) add(res *result) { - r.responses = append(r.responses, res) +func (r *TextReporter) add(res *Result) { + r.results = append(r.results, res) } diff --git a/lib/timings_plot_reporter.go b/lib/timings_plot_reporter.go index 31f8028..5f0744d 100644 --- a/lib/timings_plot_reporter.go +++ b/lib/timings_plot_reporter.go @@ -12,36 +12,36 @@ import ( ) type TimingsPlotReporter struct { - responses *list.List + results *list.List } // NewTimingsPlotReporter initializes a TimingsPlotReporter func NewTimingsPlotReporter() *TimingsPlotReporter { - return &TimingsPlotReporter{responses: list.New()} + return &TimingsPlotReporter{results: list.New()} } // add inserts response to be used in the report, sorted by timestamp. -func (r *TimingsPlotReporter) add(res *result) { +func (r *TimingsPlotReporter) add(res *Result) { // Empty list - if r.responses.Len() == 0 { - r.responses.PushFront(res) + if r.results.Len() == 0 { + r.results.PushFront(res) return } // Happened after all others - if last := r.responses.Back().Value.(*result); last.timestamp.Before(res.timestamp) { - r.responses.PushBack(res) + if last := r.results.Back().Value.(*Result); last.Timestamp.Before(res.Timestamp) { + r.results.PushBack(res) return } // Happened before all others - if first := r.responses.Front().Value.(*result); first.timestamp.After(res.timestamp) { - r.responses.PushFront(res) + if first := r.results.Front().Value.(*Result); first.Timestamp.After(res.Timestamp) { + r.results.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) + for e := r.results.Front(); e != nil; e = e.Next() { + needle := e.Value.(*Result) + if res.Timestamp.Before(needle.Timestamp) { + r.results.InsertBefore(res, e) return } } @@ -53,10 +53,10 @@ 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) + for e := r.results.Front(); e != nil; e = e.Next() { + r := e.Value.(*Result) + timestamps = append(timestamps, r.Timestamp) + timings = append(timings, r.Timing) } p, err := plot.New()