Skip to content

Commit

Permalink
Add drawer
Browse files Browse the repository at this point in the history
  • Loading branch information
nakabonne committed Sep 13, 2020
1 parent b5f5c77 commit b71937a
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 35 deletions.
4 changes: 4 additions & 0 deletions attacker/attacker.go
Expand Up @@ -112,3 +112,7 @@ func newMetrics(m *vegeta.Metrics) *Metrics {
},
}
}

func (m *Metrics) String() string {
return "foo"
}
49 changes: 49 additions & 0 deletions gui/drawer.go
@@ -0,0 +1,49 @@
package gui

import (
"context"
"time"

"github.com/mum4k/termdash/widgets/text"

"github.com/mum4k/termdash/cell"
"github.com/mum4k/termdash/widgets/linechart"

"github.com/nakabonne/ali/attacker"
)

type drawer struct {
widgets *widgets
chartsCh chan *attacker.Result
reportCh chan string
}

// TODO: In the future, multiple charts including bytes-in/out etc will be re-drawn.
func (d *drawer) redrawChart(ctx context.Context, maxSize int) {
values := make([]float64, 0, maxSize)
for {
select {
case <-ctx.Done():
return
case res := <-d.chartsCh:
values = append(values, float64(res.Latency/time.Millisecond))
d.widgets.latencyChart.Series("latency", values,
linechart.SeriesCellOpts(cell.FgColor(cell.ColorNumber(87))),
linechart.SeriesXLabels(map[int]string{
0: "req",
}),
)
}
}
}

func (d *drawer) redrawReport(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
case report := <-d.reportCh:
d.widgets.reportText.Write(report, text.WriteReplace())
}
}
}
26 changes: 16 additions & 10 deletions gui/gui.go
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"time"

"github.com/k0kubun/pp"
"github.com/mum4k/termdash"
"github.com/mum4k/termdash/container"
"github.com/mum4k/termdash/container/grid"
Expand Down Expand Up @@ -46,21 +45,28 @@ func Run() error {
return fmt.Errorf("failed to update container: %w", err)
}

d := &drawer{
widgets: w,
chartsCh: make(chan *attacker.Result),
reportCh: make(chan string),
}
go d.redrawReport(ctx)

keybinds := func(k *terminalapi.Keyboard) {
switch k.Key {
case keyboard.KeyEsc, keyboard.KeyCtrlC:
cancel()
case keyboard.KeySpace:
resultCh := make(chan *attacker.Result)
// TODO: Enalble to poplulate from input
rate := 50
duration, _ := time.ParseDuration("10s")
duration, _ := time.ParseDuration("2s")
requestNum := rate * int(duration/time.Second)
go func() {
metrics := attacker.Attack(ctx, "http://34.84.111.163:9898", resultCh, attacker.Options{Rate: rate, Duration: duration})
pp.Println(metrics)
}()
go redrawChart(ctx, w.latencyChart, resultCh, requestNum)
go d.redrawChart(ctx, requestNum)
go func(ctx context.Context, d *drawer, r int, du time.Duration) {
metrics := attacker.Attack(ctx, "http://34.84.111.163:9898", d.chartsCh, attacker.Options{Rate: r, Duration: du})
//close(ch) TODO: Gracefully stop redrawChart goroutine.
d.reportCh <- metrics.String()
}(ctx, d, rate, duration)
}
}

Expand All @@ -71,11 +77,11 @@ func gridLayout(w *widgets) ([]container.Option, error) {
raw1 := grid.RowHeightPerc(50,
grid.ColWidthPerc(99, grid.Widget(w.latencyChart, container.Border(linestyle.Light), container.BorderTitle("Latency"))),
)
raw2 := grid.RowHeightPerc(47,
raw2 := grid.RowHeightPerc(45,
grid.ColWidthPerc(50, grid.Widget(w.urlInput, container.Border(linestyle.Light), container.BorderTitle("Input"))),
grid.ColWidthPerc(49, grid.Widget(w.reportText, container.Border(linestyle.Light), container.BorderTitle("Report"))),
)
raw3 := grid.RowHeightPerc(2,
raw3 := grid.RowHeightPerc(4,
grid.ColWidthPerc(99, grid.Widget(w.navi, container.Border(linestyle.Light))),
)

Expand Down
36 changes: 11 additions & 25 deletions gui/widgets.go
@@ -1,16 +1,13 @@
package gui

import (
"context"
"time"

"github.com/k0kubun/pp"
"github.com/mum4k/termdash/cell"
"github.com/mum4k/termdash/widgets/linechart"
"github.com/mum4k/termdash/widgets/text"
"github.com/mum4k/termdash/widgets/textinput"

"github.com/nakabonne/ali/attacker"
)

// redrawInterval is how often termdash redraws the screen.
Expand All @@ -30,11 +27,11 @@ func newWidgets() (*widgets, error) {
if err != nil {
return nil, err
}
rt, err := newRollText()
rt, err := newRollText("Give the target URL and press Space, then the attack will be launched.")
if err != nil {
return nil, err
}
wt, err := newWrapText("Ctrl-c: quit, Space: attack")
wt, err := newRollText("Ctrl-c: quit, Space: attack")
if err != nil {
return nil, err
}
Expand All @@ -59,8 +56,15 @@ func newLineChart() (*linechart.LineChart, error) {
)
}

func newRollText() (*text.Text, error) {
return text.New(text.RollContent())
func newRollText(s string) (*text.Text, error) {
t, err := text.New(text.RollContent())
if err != nil {
return nil, err
}
if err := t.Write(s); err != nil {
return nil, err
}
return t, nil
}

func newWrapText(s string) (*text.Text, error) {
Expand Down Expand Up @@ -90,21 +94,3 @@ func newTextInput() (*textinput.TextInput, error) {
}
return input, err
}

func redrawChart(ctx context.Context, latency *linechart.LineChart, resultCh chan *attacker.Result, maxSize int) {
values := make([]float64, 0, maxSize)
for {
select {
case <-ctx.Done():
return
case res := <-resultCh:
values = append(values, float64(res.Latency/time.Millisecond))
latency.Series("latency", values,
linechart.SeriesCellOpts(cell.FgColor(cell.ColorNumber(87))),
linechart.SeriesXLabels(map[int]string{
0: "req",
}),
)
}
}
}

0 comments on commit b71937a

Please sign in to comment.