added config variables support

This commit is contained in:
sqshq 2019-04-08 22:04:08 -04:00
parent 19f2d028a6
commit 1017a0cd3c
9 changed files with 93 additions and 64 deletions

View File

@ -9,6 +9,7 @@ import (
"github.com/sqshq/sampler/console"
"github.com/sqshq/sampler/data"
"image"
"strings"
)
type AsciiBox struct {
@ -56,8 +57,8 @@ func NewAsciiBox(c config.AsciiBoxConfig, palette console.Palette) *AsciiBox {
for {
select {
case sample := <-box.SampleChannel:
box.text = sample.Value
box.ascii, _ = box.render.RenderOpts(sample.Value, box.options)
box.text = strings.TrimSpace(sample.Value)
box.ascii, _ = box.render.RenderOpts(box.text, box.options)
case alert := <-box.AlertChannel:
box.alert = alert
}

View File

@ -8,6 +8,8 @@ import (
"time"
)
const DefaultValueLength = 4
type ChartGrid struct {
timeRange TimeRange
timePerPoint time.Duration
@ -136,3 +138,24 @@ func getLocalExtrema(items []TimeLine, timeRange TimeRange) ValueExtrema {
func (r *TimeRange) isInRange(time time.Time) bool {
return time.After(r.min) && time.Before(r.max)
}
// TODO add boundaries for values in range
func (c *RunChart) getMaxValueLength() int {
maxValueLength := -1
for _, line := range c.lines {
for _, point := range line.points {
l := len(util.FormatValue(point.value, c.scale))
if l > maxValueLength {
maxValueLength = l
}
}
}
if maxValueLength < 0 {
return DefaultValueLength
}
return maxValueLength
}

View File

@ -315,23 +315,6 @@ func (c *RunChart) calculateTimeCoordinate(t time.Time) int {
return c.grid.maxTimeWidth - int(math.Ceil(float64(xAxisGridWidth)*timeDeltaToPaddingRelation))
}
// TODO add boundaries for values in range
func (c *RunChart) getMaxValueLength() int {
maxValueLength := 0
for _, line := range c.lines {
for _, point := range line.points {
l := len(util.FormatValue(point.value, c.scale))
if l > maxValueLength {
maxValueLength = l
}
}
}
return maxValueLength
}
func (c *RunChart) moveSelection(shift int) {
if c.mode == ModeDefault {

View File

@ -114,8 +114,10 @@ func (s *SparkLine) Draw(buffer *ui.Buffer) {
buffer.SetCell(ui.NewCell(console.SymbolVerticalBar, ui.NewStyle(console.GetGradientColor(s.gradient, j-1, height))), image.Pt(s.Inner.Max.X-n-indent, s.Inner.Max.Y-j))
if i == len(s.values)-1 && j == top {
buffer.SetString(curValue, textStyle, image.Pt(s.Inner.Max.X-n-indent+2, s.Inner.Max.Y-j))
buffer.SetString(minValue, textStyle, image.Pt(s.Inner.Max.X-n-indent+2, s.Max.Y-2))
buffer.SetString(maxValue, textStyle, image.Pt(s.Inner.Max.X-n-indent+2, s.Min.Y+1))
if s.maxValue != s.minValue {
buffer.SetString(minValue, textStyle, image.Pt(s.Inner.Max.X-n-indent+2, s.Max.Y-2))
buffer.SetString(maxValue, textStyle, image.Pt(s.Inner.Max.X-n-indent+2, s.Min.Y+1))
}
}
}
}

View File

@ -1,22 +1,24 @@
variables:
mongoconnection: mongo --quiet --host=localhost blog
runcharts:
- title: SEARCH ENGINE RESPONSE TIME (sec)
position: [[0, 0], [52, 16]]
triggers:
- title: Latency threshold exceeded
condition: echo "$prev < 0.8 && $cur > 0.8" |bc -l
actions:
terminal-bell: true
sound: true
visual: true
script: 'say alert: ${label} latency exceeded ${cur} second'
- title: Latency threshold exceeded
condition: echo "$prev < 0.8 && $cur > 0.8" |bc -l
actions:
terminal-bell: true
sound: true
visual: true
script: 'say alert: ${label} latency exceeded ${cur} second'
scale: 3
items:
- label: GOOGLE
sample: curl -o /dev/null -s -w '%{time_total}' https://www.google.com
- label: YAHOO
sample: curl -o /dev/null -s -w '%{time_total}' https://search.yahoo.com
- label: BING
sample: curl -o /dev/null -s -w '%{time_total}' https://www.bing.com
- label: GOOGLE
sample: curl -o /dev/null -s -w '%{time_total}' https://www.google.com
- label: YAHOO
sample: curl -o /dev/null -s -w '%{time_total}' https://search.yahoo.com
- label: BING
sample: curl -o /dev/null -s -w '%{time_total}' https://www.bing.com
- title: MONGO COLLECTIONS COUNT
position: [[53, 0], [27, 8]]
legend:
@ -24,32 +26,32 @@ runcharts:
details: false
scale: 0
items:
- label: ACTIVE
init: mongo --quiet --host=localhost blog
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
transform: $sample | grep cpu
- label: INACTIVE
sample: mongo --quiet --host=localhost blog --eval "db.getCollection('posts').find({status:'INACTIVE'}).itcount()"
- label: ACTIVE
init: ${mongoconnection}
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
- label: INACTIVE
init: ${mongoconnection}
sample: db.getCollection('posts').find({status:'INACTIVE'}).itcount()
barcharts:
- title: EVENTS BY STATUS
position: [[0, 17], [27, 12]]
rate-ms: 300
scale: 0
items:
- label: NEW
init: mongo --quiet --host=localhost blog
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
- label: TRIGGERED
init: mongo --quiet --host=localhost blog
sample: db.getCollection('posts').find({status:'INACTIVE'}).itcount()
- label: IN_PROCESS
sample: echo 0
- label: FAILED
init: mongo --quiet --host=localhost blog
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
- label: FINISHED
init: mongo --quiet --host=localhost blog
sample: db.getCollection('posts').find({status:'INACTIVE'}).itcount()
- label: NEW
init: ${mongoconnection}
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
- label: TRIGGERED
init: ${mongoconnection}
sample: db.getCollection('posts').find({status:'INACTIVE'}).itcount()
- label: IN_PROCESS
sample: echo 0
- label: FAILED
init: ${mongoconnection}
sample: db.getCollection('posts').find({status:'ACTIVE'}).itcount()
- label: FINISHED
init: ${mongoconnection}
sample: db.getCollection('posts').find({status:'INACTIVE'}).itcount()
gauges:
- title: YEAR PROGRESS
position: [[53, 8], [27, 2]]
@ -78,11 +80,11 @@ gauges:
- title: MINUTE PROGRESS
position: [[53, 14], [27, 2]]
triggers:
- title: CLOCK BELL EVERY MINUTE
condition: '[ $label == "cur" ] && [ $cur -eq 0 ] && echo 1 || echo 0'
actions:
sound: true
script: say -v samantha `date +%I:%M%p`
- title: CLOCK BELL EVERY MINUTE
condition: '[ $label == "cur" ] && [ $cur -eq 0 ] && echo 1 || echo 0'
actions:
sound: true
script: say -v samantha `date +%I:%M%p`
cur:
sample: date +%S
max:

View File

@ -12,6 +12,7 @@ import (
type Config struct {
Theme *console.Theme `yaml:"theme,omitempty"`
Variables map[string]string `yaml:"variables,omitempty"`
RunCharts []RunChartConfig `yaml:"runcharts,omitempty"`
BarCharts []BarChartConfig `yaml:"barcharts,omitempty"`
Gauges []GaugeConfig `yaml:"gauges,omitempty"`

View File

@ -2,6 +2,6 @@ package config
type Options struct {
ConfigFile string `short:"c" long:"config" required:"true" description:"path to YAML config file"`
Variables []string `short:"v" long:"variable" required:"false" description:"specify name=value variable to use in script placeholder as $name" long-description:"one or more variables can be specified as flags, in order to replace repeated patterns in the scripts, which can be replaced with {$variable-name} placeholder" `
Variables []string `short:"v" long:"variable" required:"false" description:"specify name=value variable to use in script placeholder as $name. This flag takes precedence over the same name variables, specified in config yml" long-description:"one or more variables can be specified as flags, in order to replace repeated patterns in the scripts, which can be replaced with {$variable-name} placeholder" `
Examples []string `short:"e" long:"example" required:"false" choice:"runchart" choice:"barchart" choice:"asciibox" choice:"textbox" choice:"gauge" choice:"sparkline" description:"add an example component to the specified config file" long-description:"one or more example component types can be added to the specified config file, in order to jump-start the configuration"`
}

View File

@ -1,6 +1,7 @@
package data
import (
"fmt"
"github.com/sqshq/sampler/config"
"time"
)
@ -10,9 +11,10 @@ type Sampler struct {
items []*Item
triggers []*Trigger
triggersChannel chan *Sample
variables []string
}
func NewSampler(consumer *Consumer, items []*Item, triggers []*Trigger, options config.Options, rateMs int) Sampler {
func NewSampler(consumer *Consumer, items []*Item, triggers []*Trigger, options config.Options, fileVariables map[string]string, rateMs int) Sampler {
ticker := time.NewTicker(time.Duration(rateMs * int(time.Millisecond)))
@ -21,6 +23,7 @@ func NewSampler(consumer *Consumer, items []*Item, triggers []*Trigger, options
items,
triggers,
make(chan *Sample),
mergeVariables(fileVariables, options.Variables),
}
go func() {
@ -47,7 +50,7 @@ func NewSampler(consumer *Consumer, items []*Item, triggers []*Trigger, options
func (s *Sampler) sample(item *Item, options config.Options) {
val, err := item.nextValue(options.Variables)
val, err := item.nextValue(s.variables)
if len(val) > 0 {
sample := &Sample{Label: item.Label, Value: val, Color: item.Color}
@ -61,3 +64,15 @@ func (s *Sampler) sample(item *Item, options config.Options) {
}
}
}
// option variables takes precedence over the file variables with the same name
func mergeVariables(fileVariables map[string]string, optionsVariables []string) []string {
result := optionsVariables
for key, value := range fileVariables {
result = append([]string{fmt.Sprintf("%s=%s", key, value)}, result...)
}
return result
}

View File

@ -20,12 +20,14 @@ type Starter struct {
lout *layout.Layout
player *asset.AudioPlayer
opt config.Options
cfg config.Config
}
func (s *Starter) start(drawable ui.Drawable, consumer *data.Consumer, componentConfig config.ComponentConfig, itemsConfig []config.Item, triggersConfig []config.TriggerConfig) {
cpt := component.NewComponent(drawable, consumer, componentConfig)
triggers := data.NewTriggers(triggersConfig, consumer, s.opt, s.player)
data.NewSampler(consumer, data.NewItems(itemsConfig, *componentConfig.RateMs), triggers, s.opt, *componentConfig.RateMs)
items := data.NewItems(itemsConfig, *componentConfig.RateMs)
data.NewSampler(consumer, items, triggers, s.opt, s.cfg.Variables, *componentConfig.RateMs)
s.lout.AddComponent(cpt)
}
@ -44,7 +46,7 @@ func main() {
lout := layout.NewLayout(width, height, component.NewStatusLine(opt.ConfigFile, palette), component.NewMenu(palette))
starter := &Starter{lout, player, opt}
starter := &Starter{lout, player, opt, cfg}
for _, c := range cfg.RunCharts {
cpt := runchart.NewRunChart(c, palette)