From db3888e5408861564eecd61ca0d6935c3a0f6b93 Mon Sep 17 00:00:00 2001 From: sqshq Date: Sun, 24 Mar 2019 18:46:39 -0400 Subject: [PATCH] sparkline config and infrastructure added --- component/runchart/runchart.go | 2 +- component/sparkline/sparkline.go | 61 ++++++++++++++++++++++++++++++++ config.yml | 7 +++- config/component.go | 6 ++++ config/config.go | 17 ++++++--- config/default.go | 17 +++++++++ console/symbol.go | 2 +- main.go | 7 ++++ 8 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 component/sparkline/sparkline.go diff --git a/component/runchart/runchart.go b/component/runchart/runchart.go index 29ef3e3..9773773 100644 --- a/component/runchart/runchart.go +++ b/component/runchart/runchart.go @@ -16,10 +16,10 @@ import ( ) const ( + xAxisGridWidth = xAxisLabelsIndent + xAxisLabelsWidth xAxisLabelsHeight = 1 xAxisLabelsWidth = 8 xAxisLabelsIndent = 2 - xAxisGridWidth = xAxisLabelsIndent + xAxisLabelsWidth yAxisLabelsHeight = 1 yAxisLabelsIndent = 1 historyReserveMin = 20 diff --git a/component/sparkline/sparkline.go b/component/sparkline/sparkline.go new file mode 100644 index 0000000..d373eed --- /dev/null +++ b/component/sparkline/sparkline.go @@ -0,0 +1,61 @@ +package sparkline + +import ( + ui "github.com/gizak/termui/v3" + "github.com/sqshq/sampler/component" + "github.com/sqshq/sampler/config" + "github.com/sqshq/sampler/console" + "github.com/sqshq/sampler/data" + "strconv" +) + +type SparkLine struct { + *ui.Block + *data.Consumer + alert *data.Alert + values []float64 + palette console.Palette +} + +func NewSparkLine(c config.SparkLineConfig, palette console.Palette) *SparkLine { + + line := &SparkLine{ + Block: component.NewBlock(c.Title, true, palette), + Consumer: data.NewConsumer(), + values: []float64{}, + palette: palette, + } + + go func() { + for { + select { + case sample := <-line.SampleChannel: + line.consumeSample(sample) + case alert := <-line.AlertChannel: + line.alert = alert + } + } + }() + + return line +} + +func (s *SparkLine) consumeSample(sample *data.Sample) { + float, err := strconv.ParseFloat(sample.Value, 64) + + if err != nil { + s.AlertChannel <- &data.Alert{ + Title: "FAILED TO PARSE NUMBER", + Text: err.Error(), + Color: sample.Color, + } + return + } + + s.values = append(s.values, float) + // TODO cleanup old ones +} + +func (s *SparkLine) Draw(buffer *ui.Buffer) { + s.Block.Draw(buffer) +} diff --git a/config.yml b/config.yml index 7a16454..af117d4 100644 --- a/config.yml +++ b/config.yml @@ -80,6 +80,11 @@ asciiboxes: position: [[53, 17], [27, 5]] value: date +%r - title: UTC TIME - position: [[53, 22], [27, 6]] + position: [[53, 22], [27, 7]] value: env TZ=UTC date +%r font: 3d +sparklines: +- title: CPU usage + position: [[28, 17], [25, 12]] + scale: 0 + value: ps -A -o %cpu | awk '{s+=$1} END {print s}' diff --git a/config/component.go b/config/component.go index 1e06aa9..ef9de10 100644 --- a/config/component.go +++ b/config/component.go @@ -53,6 +53,12 @@ type GaugeConfig struct { Items []Item `yaml:",omitempty"` } +type SparkLineConfig struct { + ComponentConfig `yaml:",inline"` + Scale *int `yaml:"scale,omitempty"` + Item Item `yaml:",inline"` +} + type BarChartConfig struct { ComponentConfig `yaml:",inline"` Scale *int `yaml:"scale,omitempty"` diff --git a/config/config.go b/config/config.go index 433224f..8ff9454 100644 --- a/config/config.go +++ b/config/config.go @@ -11,11 +11,12 @@ import ( ) type Config struct { - Theme *console.Theme `yaml:"theme,omitempty"` - RunCharts []RunChartConfig `yaml:"runcharts,omitempty"` - BarCharts []BarChartConfig `yaml:"barcharts,omitempty"` - Gauges []GaugeConfig `yaml:"gauges,omitempty"` - AsciiBoxes []AsciiBoxConfig `yaml:"asciiboxes,omitempty"` + Theme *console.Theme `yaml:"theme,omitempty"` + RunCharts []RunChartConfig `yaml:"runcharts,omitempty"` + BarCharts []BarChartConfig `yaml:"barcharts,omitempty"` + Gauges []GaugeConfig `yaml:"gauges,omitempty"` + AsciiBoxes []AsciiBoxConfig `yaml:"asciiboxes,omitempty"` + SparkLines []SparkLineConfig `yaml:"sparklines,omitempty"` } func Load() (Config, Options) { @@ -70,6 +71,12 @@ func (c *Config) findComponent(componentType ComponentType, componentTitle strin return &c.AsciiBoxes[i].ComponentConfig } } + case TypeSparkLine: + for i, component := range c.SparkLines { + if component.Title == componentTitle { + return &c.SparkLines[i].ComponentConfig + } + } } panic(fmt.Sprintf( diff --git a/config/default.go b/config/default.go index 49f1be5..63bebf9 100644 --- a/config/default.go +++ b/config/default.go @@ -43,6 +43,23 @@ func (c *Config) setDefaultValues() { c.RunCharts[i] = chart } + for i, line := range c.SparkLines { + + setDefaultTriggersValues(line.Triggers) + line.ComponentConfig.Type = TypeSparkLine + line.Item.Label = &line.Title + + if line.RefreshRateMs == nil { + r := defaultRefreshRateMs + line.RefreshRateMs = &r + } + if line.Scale == nil { + p := defaultScale + line.Scale = &p + } + c.SparkLines[i] = line + } + for i, chart := range c.BarCharts { setDefaultTriggersValues(chart.Triggers) diff --git a/console/symbol.go b/console/symbol.go index d278539..b5bf093 100644 --- a/console/symbol.go +++ b/console/symbol.go @@ -3,5 +3,5 @@ package console const ( SymbolSelection rune = '▲' SymbolVerticalBar rune = '▎' - SymbolShade rune = '⠿' + SymbolShade rune = '═' ) diff --git a/main.go b/main.go index 4e90869..f5fbf24 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "github.com/sqshq/sampler/component/gauge" "github.com/sqshq/sampler/component/layout" "github.com/sqshq/sampler/component/runchart" + "github.com/sqshq/sampler/component/sparkline" "github.com/sqshq/sampler/config" "github.com/sqshq/sampler/console" "github.com/sqshq/sampler/data" @@ -50,6 +51,12 @@ func main() { starter.start(cpt, cpt.Consumer, c.ComponentConfig, c.Items, c.Triggers) } + for _, c := range cfg.SparkLines { + println(c.Title) + cpt := sparkline.NewSparkLine(c, palette) + starter.start(cpt, cpt.Consumer, c.ComponentConfig, []config.Item{c.Item}, c.Triggers) + } + for _, c := range cfg.AsciiBoxes { cpt := asciibox.NewAsciiBox(c, palette) starter.start(cpt, cpt.Consumer, c.ComponentConfig, []config.Item{c.Item}, c.Triggers)