Skip to content

Commit

Permalink
plot: HTMLPlotOpts
Browse files Browse the repository at this point in the history
  • Loading branch information
tsenart committed Aug 12, 2018
1 parent eacb7a8 commit f63b43a
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 21 deletions.
52 changes: 44 additions & 8 deletions lib/plot.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,24 @@ type HTMLPlot struct {
title string
threshold int
series map[string]*labeledSeries
label func(*Result) string
label HTMLPlotLabeler
}

// An HTMLPlotLabeler is a function that returns a label
// to partition and represent Results in separate (but overlaid) line charts
// in the rendered plot.
type HTMLPlotLabeler func(*Result) (label string)

// ErrorLabeler is an HTMLPlotLabeler which
// labels a result with an OK or ERROR label
// based on whether it has an error set.
func ErrorLabeler(r *Result) (label string) {
switch r.Error {
case "":
return "OK"
default:
return "ERROR"
}
}

// labeledSeries groups timeSeries by a label function applied to
Expand All @@ -29,7 +46,7 @@ type labeledSeries struct {
seq uint64
buf map[uint64]point
series map[string]*timeSeries
label func(*Result) string
label HTMLPlotLabeler
}

// a point to be added to a timeSeries.
Expand Down Expand Up @@ -88,15 +105,34 @@ func (ls *labeledSeries) add(r *Result) (err error) {
}
}

// HTMLPlotOpt is a functional option type for HTMLPlot.
type HTMLPlotOpt func(*HTMLPlot)

// Downsample returns an HTMLPlotOpt that enables downsampling
// to the given threshold number of data points.
func Downsample(threshold int) HTMLPlotOpt {
return func(p *HTMLPlot) { p.threshold = threshold }
}

// Labeler returns an HTMLPlotOpt that sets the given HTMLPlotLabeler
// to be used to partition results into multiple overlaid line charts.
func Labeler(l HTMLPlotLabeler) HTMLPlotOpt {
return func(p *HTMLPlot) { p.label = l }
}

// NewHTMLPlot returns an HTMLPlot with the given title,
// downsampling threshold, and result labeling function.
func NewHTMLPlot(title string, threshold int, label func(*Result) string) *HTMLPlot {
return &HTMLPlot{
title: title,
threshold: threshold,
series: map[string]*labeledSeries{},
label: label,
func NewHTMLPlot(title string, opts ...HTMLPlotOpt) *HTMLPlot {
p := &HTMLPlot{
title: title,
series: map[string]*labeledSeries{},
}

for _, opt := range opts {
opt(p)
}

return p
}

// Add adds the given Result to the HTMLPlot time series.
Expand Down
15 changes: 9 additions & 6 deletions lib/plot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ func BenchmarkHTMLPlot(b *testing.B) {
}
}

plot := NewHTMLPlot("Vegeta Plot", 5000, func(r *Result) string {
if r.Code >= 200 && r.Code < 300 {
return "OK"
}
return "Error"
})
plot := NewHTMLPlot("Vegeta Plot",
Downsample(5000),
Labeler(func(r *Result) string {
if r.Code >= 200 && r.Code < 300 {
return "OK"
}
return "Error"
}),
)

b.Run("Add", func(b *testing.B) {
for i := 0; i < b.N; i++ {
Expand Down
11 changes: 4 additions & 7 deletions plot.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,10 @@ func plot(files []string, threshold int, title, output string) error {
sigch := make(chan os.Signal, 1)
signal.Notify(sigch, os.Interrupt)

plot := vegeta.NewHTMLPlot(title, threshold, func(r *vegeta.Result) string {
if r.Error == "" {
return "OK"
} else {
return "Error"
}
})
plot := vegeta.NewHTMLPlot(title,
vegeta.Downsample(threshold),
vegeta.Labeler(vegeta.ErrorLabeler),
)

decode:
for {
Expand Down

0 comments on commit f63b43a

Please sign in to comment.