Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: observe error instead of failure count #15

Merged
merged 5 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ bin/

# Go workspace file
go.work

#tmp folder which contains .yaml files
tmp/
4 changes: 2 additions & 2 deletions api/types/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import "time"
type ResponseStats struct {
// Total represents total number of requests.
Total int
// Failures represents number of failure request.
Failures int
// List of failures
FailureList []error
// Duration means the time of benchmark.
Duration time.Duration
// PercentileLatencies represents the latency distribution in seconds.
Expand Down
5 changes: 4 additions & 1 deletion cmd/kperf/commands/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@ func loadConfig(cliCtx *cli.Context) (*types.LoadProfile, error) {
func printResponseStats(stats *types.ResponseStats) {
fmt.Println("Response stat:")
fmt.Printf(" Total: %v\n", stats.Total)
fmt.Printf(" Failures: %v\n", stats.Failures)
fmt.Printf(" Total Failures: %v\n", len(stats.FailureList))
for _, v := range stats.FailureList {
fmt.Printf(" Failure: %v\n", v)
}
fmt.Printf(" Duration: %v\n", stats.Duration)
fmt.Printf(" Requests/sec: %.2f\n", float64(stats.Total)/stats.Duration.Seconds())

Expand Down
26 changes: 14 additions & 12 deletions metrics/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,29 @@ import (
"math"
"sort"
"sync"
"sync/atomic"
)

// ResponseMetric is a measurement related to http response.
type ResponseMetric interface {
// ObserveLatency observes latency.
ObserveLatency(seconds float64)
// ObserveFailure observes failure response.
ObserveFailure()
ObserveFailure(err error)
// Gather returns the summary.
Gather() (latencies []float64, percentileLatencies map[float64]float64, failure int)
Gather() (latencies []float64, percentileLatencies map[float64]float64, failureList []error)
}

type responseMetricImpl struct {
mu sync.Mutex
failureCount int64
latencies *list.List
mu sync.Mutex
failureList []error
latencies *list.List
}

func NewResponseMetric() ResponseMetric {
errList := make([]error, 0, 1024)
return &responseMetricImpl{
latencies: list.New(),
latencies: list.New(),
failureList: errList,
}
}

Expand All @@ -38,15 +39,16 @@ func (m *responseMetricImpl) ObserveLatency(seconds float64) {
}

// ObserveFailure implements ResponseMetric.
func (m *responseMetricImpl) ObserveFailure() {
atomic.AddInt64(&m.failureCount, 1)
func (m *responseMetricImpl) ObserveFailure(err error) {
m.mu.Lock()
defer m.mu.Unlock()
m.failureList = append(m.failureList, err)
}

// Gather implements ResponseMetric.
func (m *responseMetricImpl) Gather() ([]float64, map[float64]float64, int) {
func (m *responseMetricImpl) Gather() ([]float64, map[float64]float64, []error) {
latencies := m.dumpLatencies()

return latencies, buildPercentileLatencies(latencies), int(atomic.LoadInt64(&m.failureCount))
return latencies, buildPercentileLatencies(latencies), m.failureList
}

func (m *responseMetricImpl) dumpLatencies() []float64 {
Expand Down
7 changes: 4 additions & 3 deletions request/schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ func Schedule(ctx context.Context, spec *types.LoadProfileSpec, restCli []rest.I
// we don't need that unmarshal object.
_, err = io.Copy(io.Discard, respBody)
}

if err != nil {
respMetric.ObserveFailure()
respMetric.ObserveFailure(err)
}
}()
}
Expand All @@ -80,10 +81,10 @@ func Schedule(ctx context.Context, spec *types.LoadProfileSpec, restCli []rest.I

totalDuration := time.Since(start)

_, percentileLatencies, failures := respMetric.Gather()
_, percentileLatencies, failureList := respMetric.Gather()
return &types.ResponseStats{
Total: spec.Total,
Failures: failures,
FailureList: failureList,
Duration: totalDuration,
PercentileLatencies: percentileLatencies,
}, nil
Expand Down
Loading