2019-02-26 04:36:23 +00:00
|
|
|
package gauge
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-03-14 03:01:44 +00:00
|
|
|
ui "github.com/gizak/termui/v3"
|
2019-03-13 03:19:19 +00:00
|
|
|
"github.com/sqshq/sampler/component"
|
2019-04-07 18:26:20 +00:00
|
|
|
"github.com/sqshq/sampler/component/util"
|
2019-03-16 04:35:00 +00:00
|
|
|
"github.com/sqshq/sampler/config"
|
2019-02-26 04:36:23 +00:00
|
|
|
"github.com/sqshq/sampler/console"
|
|
|
|
"github.com/sqshq/sampler/data"
|
|
|
|
"image"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
MinValueLabel = "min"
|
|
|
|
MaxValueLabel = "max"
|
|
|
|
CurValueLabel = "cur"
|
|
|
|
)
|
|
|
|
|
2019-07-27 04:15:35 +00:00
|
|
|
// Gauge displays cur value between specified min and max values
|
2019-02-26 04:36:23 +00:00
|
|
|
type Gauge struct {
|
2019-03-16 23:59:28 +00:00
|
|
|
*ui.Block
|
|
|
|
*data.Consumer
|
2019-06-22 02:56:23 +00:00
|
|
|
minValue float64
|
|
|
|
maxValue float64
|
|
|
|
curValue float64
|
|
|
|
color ui.Color
|
|
|
|
scale int
|
|
|
|
percentOnly bool
|
|
|
|
palette console.Palette
|
2019-02-26 04:36:23 +00:00
|
|
|
}
|
|
|
|
|
2019-03-24 00:16:59 +00:00
|
|
|
func NewGauge(c config.GaugeConfig, palette console.Palette) *Gauge {
|
2019-03-16 04:35:00 +00:00
|
|
|
|
2019-06-06 03:07:34 +00:00
|
|
|
g := Gauge{
|
2019-06-22 02:56:23 +00:00
|
|
|
Block: component.NewBlock(c.Title, true, palette),
|
|
|
|
Consumer: data.NewConsumer(),
|
|
|
|
color: *c.Color,
|
|
|
|
scale: *c.Scale,
|
|
|
|
percentOnly: *c.PercentOnly,
|
|
|
|
palette: palette,
|
2019-03-08 04:04:46 +00:00
|
|
|
}
|
|
|
|
|
2019-03-16 04:35:00 +00:00
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
2019-06-06 03:07:34 +00:00
|
|
|
case sample := <-g.SampleChannel:
|
|
|
|
g.ConsumeSample(sample)
|
|
|
|
case alert := <-g.AlertChannel:
|
|
|
|
g.Alert = alert
|
2019-03-16 04:35:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
2019-03-08 04:04:46 +00:00
|
|
|
|
2019-06-06 03:07:34 +00:00
|
|
|
return &g
|
2019-03-08 04:04:46 +00:00
|
|
|
}
|
|
|
|
|
2019-03-16 23:59:28 +00:00
|
|
|
func (g *Gauge) ConsumeSample(sample *data.Sample) {
|
2019-02-26 04:36:23 +00:00
|
|
|
|
2019-04-07 18:26:20 +00:00
|
|
|
float, err := util.ParseFloat(sample.Value)
|
2019-02-26 04:36:23 +00:00
|
|
|
if err != nil {
|
2019-06-06 03:07:34 +00:00
|
|
|
g.HandleConsumeFailure("Failed to parse a number", err, sample)
|
2019-03-16 23:59:28 +00:00
|
|
|
return
|
2019-02-26 04:36:23 +00:00
|
|
|
}
|
|
|
|
|
2019-07-28 17:15:34 +00:00
|
|
|
g.HandleConsumeSuccess()
|
|
|
|
|
2019-02-26 04:36:23 +00:00
|
|
|
switch sample.Label {
|
|
|
|
case MinValueLabel:
|
|
|
|
g.minValue = float
|
|
|
|
break
|
|
|
|
case MaxValueLabel:
|
|
|
|
g.maxValue = float
|
|
|
|
break
|
|
|
|
case CurValueLabel:
|
|
|
|
g.curValue = float
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-16 23:59:28 +00:00
|
|
|
func (g *Gauge) Draw(buffer *ui.Buffer) {
|
2019-02-26 04:36:23 +00:00
|
|
|
|
2019-03-16 23:59:28 +00:00
|
|
|
g.Block.Draw(buffer)
|
2019-02-26 04:36:23 +00:00
|
|
|
|
|
|
|
percent := 0.0
|
2019-02-27 04:23:56 +00:00
|
|
|
if g.curValue != 0 && g.maxValue != g.minValue {
|
2019-02-26 04:36:23 +00:00
|
|
|
percent = (100 * g.curValue) / (g.maxValue - g.minValue)
|
|
|
|
}
|
|
|
|
|
2019-06-22 02:56:23 +00:00
|
|
|
var label string
|
|
|
|
if g.percentOnly {
|
|
|
|
label = fmt.Sprintf(" %v%% ", util.FormatValue(percent, g.scale))
|
|
|
|
} else {
|
|
|
|
label = fmt.Sprintf(" %v%% (%v) ", util.FormatValue(percent, g.scale), util.FormatValue(g.curValue, g.scale))
|
|
|
|
}
|
2019-02-26 04:36:23 +00:00
|
|
|
|
2019-03-16 04:35:00 +00:00
|
|
|
// draw bar
|
2019-02-26 04:36:23 +00:00
|
|
|
barWidth := int((percent / 100) * float64(g.Inner.Dx()))
|
|
|
|
if barWidth == 0 {
|
|
|
|
barWidth = 1
|
|
|
|
} else if barWidth > g.Dx()-2 {
|
|
|
|
barWidth = g.Dx() - 2
|
|
|
|
}
|
2019-03-16 23:59:28 +00:00
|
|
|
buffer.Fill(
|
2019-02-26 04:36:23 +00:00
|
|
|
ui.NewCell(console.SymbolVerticalBar, ui.NewStyle(g.color)),
|
|
|
|
image.Rect(g.Inner.Min.X+1, g.Inner.Min.Y, g.Inner.Min.X+barWidth, g.Inner.Max.Y),
|
|
|
|
)
|
|
|
|
|
2019-03-16 04:35:00 +00:00
|
|
|
// draw label
|
2019-02-26 04:36:23 +00:00
|
|
|
labelXCoordinate := g.Inner.Min.X + (g.Inner.Dx() / 2) - int(float64(len(label))/2)
|
|
|
|
labelYCoordinate := g.Inner.Min.Y + ((g.Inner.Dy() - 1) / 2)
|
|
|
|
if labelYCoordinate < g.Inner.Max.Y {
|
|
|
|
for i, char := range label {
|
2019-03-24 00:16:59 +00:00
|
|
|
style := ui.NewStyle(g.palette.BaseColor)
|
2019-02-26 04:36:23 +00:00
|
|
|
if labelXCoordinate+i+1 <= g.Inner.Min.X+barWidth {
|
2019-03-24 00:16:59 +00:00
|
|
|
style = ui.NewStyle(g.palette.BaseColor, ui.ColorClear)
|
2019-02-26 04:36:23 +00:00
|
|
|
}
|
2019-03-16 23:59:28 +00:00
|
|
|
buffer.SetCell(ui.NewCell(char, style), image.Pt(labelXCoordinate+i, labelYCoordinate))
|
2019-02-26 04:36:23 +00:00
|
|
|
}
|
|
|
|
}
|
2019-03-16 23:59:28 +00:00
|
|
|
|
2019-06-06 03:07:34 +00:00
|
|
|
component.RenderAlert(g.Alert, g.Rectangle, buffer)
|
2019-02-26 04:36:23 +00:00
|
|
|
}
|