From cf68e2a6540b941cc48fb5ce35e6b12d91bfad63 Mon Sep 17 00:00:00 2001 From: sqshq Date: Tue, 12 Mar 2019 23:15:55 -0400 Subject: [PATCH] visual alerter basic functionality --- component/alerter.go | 58 +++++++++++++++++++++++++++++++++++++++++--- component/menu.go | 2 +- config.yml | 2 +- data/consumer.go | 4 +++ data/sampler.go | 3 ++- data/trigger.go | 6 +++-- 6 files changed, 67 insertions(+), 8 deletions(-) diff --git a/component/alerter.go b/component/alerter.go index 8bc94da..64ef141 100644 --- a/component/alerter.go +++ b/component/alerter.go @@ -1,10 +1,12 @@ package component import ( + "fmt" "github.com/sqshq/sampler/console" "github.com/sqshq/sampler/data" ui "github.com/sqshq/termui" "image" + "strings" ) type Alerter struct { @@ -35,7 +37,57 @@ func (a *Alerter) RenderAlert(buffer *ui.Buffer, area image.Rectangle) { return } - buffer.Fill(ui.NewCell(' ', ui.NewStyle(console.ColorBlack)), area) - buffer.SetString(a.alert.Title, ui.NewStyle(console.ColorWhite), getMiddlePoint(area, a.alert.Title, -1)) - buffer.SetString(a.alert.Text, ui.NewStyle(console.ColorWhite), getMiddlePoint(area, a.alert.Text, 0)) + color := console.ColorWhite + + if a.alert.Color != nil { + color = *a.alert.Color + } + + width := max(len(a.alert.Title), len(a.alert.Text)) + 10 + + if width > area.Dx() { + width = area.Dx() + } + + cells := ui.WrapCells(ui.ParseText(fmt.Sprintf("%s\n%s\n", + strings.ToUpper(a.alert.Title), a.alert.Text), ui.NewStyle(console.ColorWhite)), uint(width)) + + var lines []string + line := "" + + for i := 0; i < len(cells); i++ { + if cells[i].Rune == '\n' { + lines = append(lines, line) + line = "" + } else { + line += string(cells[i].Rune) + } + } + + block := *ui.NewBlock() + block.SetRect(getRectCoordinates(area, width, len(lines))) + block.BorderStyle = ui.Style{Fg: color} + block.Draw(buffer) + + buffer.Fill(ui.NewCell(' ', ui.NewStyle(console.ColorBlack)), block.Inner) + + for i := 0; i < len(lines); i++ { + buffer.SetString(lines[i], + ui.NewStyle(color), getMiddlePoint(block.Inner, lines[i], i-1)) + } +} + +//TODO move to utils +func max(a int, b int) int { + if a > b { + return a + } else { + return b + } +} + +func getRectCoordinates(area image.Rectangle, width int, height int) (int, int, int, int) { + x1 := area.Min.X + area.Dx()/2 - width/2 + y1 := area.Min.Y + area.Dy()/2 - height + return x1, y1, x1 + width, y1 + height + 2 } diff --git a/component/menu.go b/component/menu.go index 081428a..33c4fd1 100644 --- a/component/menu.go +++ b/component/menu.go @@ -198,7 +198,7 @@ func (m *Menu) printAllDirectionsArrowSign(buffer *ui.Buffer, y int) { func (m *Menu) renderOptions(buffer *ui.Buffer) { // TODO extract styles to console.Palette - highlightedStyle := ui.NewStyle(console.ColorOlive, console.ColorBlack, ui.ModifierReverse) + highlightedStyle := ui.NewStyle(console.ColorBlack, console.ColorOlive) regularStyle := ui.NewStyle(console.ColorWhite, console.ColorBlack) offset := 1 diff --git a/config.yml b/config.yml index 736b93b..043c33f 100644 --- a/config.yml +++ b/config.yml @@ -7,7 +7,7 @@ runcharts: w: 53 h: 16 triggers: - - title: LATENCY + - title: Latency threshold exceeded condition: echo "$prev < 0.2 && $cur > 0.2" |bc -l actions: terminal-bell: true diff --git a/data/consumer.go b/data/consumer.go index 5f13946..e96a6b6 100644 --- a/data/consumer.go +++ b/data/consumer.go @@ -1,5 +1,7 @@ package data +import ui "github.com/sqshq/termui" + type Consumer struct { SampleChannel chan Sample AlertChannel chan Alert @@ -8,11 +10,13 @@ type Consumer struct { type Sample struct { Label string Value string + Color *ui.Color } type Alert struct { Title string Text string + Color *ui.Color } func NewConsumer() Consumer { diff --git a/data/sampler.go b/data/sampler.go index a0168ab..0e70e92 100644 --- a/data/sampler.go +++ b/data/sampler.go @@ -51,13 +51,14 @@ func (s *Sampler) sample(item Item) { val, err := item.nextValue() if err == nil { - sample := Sample{Label: item.Label, Value: val} + sample := Sample{Label: item.Label, Value: val, Color: item.Color} s.consumer.SampleChannel <- sample s.triggersChannel <- sample } else { s.consumer.AlertChannel <- Alert{ Title: "SAMPLING FAILURE", Text: err.Error(), + Color: item.Color, } } } diff --git a/data/trigger.go b/data/trigger.go index b43bc38..f4dd6e3 100644 --- a/data/trigger.go +++ b/data/trigger.go @@ -78,7 +78,9 @@ func (t *Trigger) Execute(sample Sample) { if t.actions.visual { t.consumer.AlertChannel <- Alert{ - Title: t.title, Text: fmt.Sprintf("%s: %v", sample.Label, sample.Value), + Title: t.title, + Text: fmt.Sprintf("%s: %v", sample.Label, sample.Value), + Color: sample.Color, } } @@ -101,7 +103,7 @@ func (t *Trigger) evaluate(sample Sample) bool { output, err := runScript(t.condition, sample.Label, t.valuesByLabel[sample.Label]) if err != nil { - //t.consumer.AlertChannel <- Alert{Title: "TRIGGER CONDITION FAILURE", Text: err.Error()} + t.consumer.AlertChannel <- Alert{Title: "TRIGGER CONDITION FAILURE", Text: err.Error()} } return t.digitsRegexp.ReplaceAllString(string(output), "") == TrueIndicator