mirror of https://github.com/divan/expvarmon.git
Moved sparklines data (stacks) to UI data structure
This commit is contained in:
parent
93da8b7853
commit
555bff1b9d
12
data.go
12
data.go
|
@ -7,11 +7,21 @@ type UIData struct {
|
||||||
Services []*Service
|
Services []*Service
|
||||||
Vars []VarName
|
Vars []VarName
|
||||||
LastTimestamp time.Time
|
LastTimestamp time.Time
|
||||||
|
Stacks map[VarName]*Stack
|
||||||
|
Stats map[VarName]*Stat
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUIData inits and return new data object.
|
// NewUIData inits and return new data object.
|
||||||
func NewUIData(vars []VarName) *UIData {
|
func NewUIData(vars []VarName) *UIData {
|
||||||
|
stacks := make(map[VarName]*Stack)
|
||||||
|
stats := make(map[VarName]*Stat)
|
||||||
|
for _, v := range vars {
|
||||||
|
stacks[v] = NewStack()
|
||||||
|
stats[v] = NewStat()
|
||||||
|
}
|
||||||
return &UIData{
|
return &UIData{
|
||||||
Vars: vars,
|
Vars: vars,
|
||||||
|
Stacks: stacks,
|
||||||
|
Stats: stats,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
79
stack.go
79
stack.go
|
@ -8,9 +8,8 @@ const DefaultSize = 1200
|
||||||
|
|
||||||
// Stack is a limited FIFO for holding sparkline values.
|
// Stack is a limited FIFO for holding sparkline values.
|
||||||
type Stack struct {
|
type Stack struct {
|
||||||
Values []Var
|
Values []int
|
||||||
Len int
|
Len int
|
||||||
Max Var
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStack inits new Stack with default size limit.
|
// NewStack inits new Stack with default size limit.
|
||||||
|
@ -21,88 +20,26 @@ func NewStack() *Stack {
|
||||||
// NewStackWithSize inits new Stack with size limit.
|
// NewStackWithSize inits new Stack with size limit.
|
||||||
func NewStackWithSize(size int) *Stack {
|
func NewStackWithSize(size int) *Stack {
|
||||||
return &Stack{
|
return &Stack{
|
||||||
Values: make([]Var, size),
|
Values: make([]int, size),
|
||||||
Len: size,
|
Len: size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
TODO: FIXME: review or remove this code
|
|
||||||
// Push inserts data to stack, preserving constant length.
|
// Push inserts data to stack, preserving constant length.
|
||||||
func (s *Stack) Push(val Var) {
|
func (s *Stack) Push(v IntVar) {
|
||||||
|
val := v.Value()
|
||||||
s.Values = append(s.Values, val)
|
s.Values = append(s.Values, val)
|
||||||
if len(s.Values) > s.Len {
|
if len(s.Values) > s.Len {
|
||||||
|
// TODO: check if underlying array is growing constantly
|
||||||
s.Values = s.Values[1:]
|
s.Values = s.Values[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Max == nil {
|
|
||||||
s.Max = val
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val.(type) {
|
|
||||||
case int64:
|
|
||||||
switch s.Max.(type) {
|
|
||||||
case int64:
|
|
||||||
if val.(int64) > s.Max.(int64) {
|
|
||||||
s.Max = val
|
|
||||||
}
|
|
||||||
case float64:
|
|
||||||
if float64(val.(int64)) > s.Max.(float64) {
|
|
||||||
s.Max = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case float64:
|
|
||||||
switch s.Max.(type) {
|
|
||||||
case int64:
|
|
||||||
if val.(float64) > float64(s.Max.(int64)) {
|
|
||||||
s.Max = val
|
|
||||||
}
|
|
||||||
case float64:
|
|
||||||
if val.(float64) > s.Max.(float64) {
|
|
||||||
s.Max = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Front returns front value.
|
|
||||||
func (s *Stack) Front() Var {
|
|
||||||
if len(s.Values) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return s.Values[len(s.Values)-1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntValues returns stack values explicitly casted to int.
|
// IntValues returns stack values explicitly casted to int.
|
||||||
//
|
//
|
||||||
// Main case is to use with termui.Sparklines.
|
// Main case is to use with termui.Sparklines.
|
||||||
func (s *Stack) IntValues() []int {
|
func (s *Stack) IntValues() []int {
|
||||||
ret := make([]int, s.Len)
|
return s.Values
|
||||||
for i, v := range s.Values {
|
|
||||||
n, ok := v.(int64)
|
|
||||||
if ok {
|
|
||||||
ret[i] = int(n)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
f, ok := v.(float64)
|
|
||||||
if ok {
|
|
||||||
// 12.34 (float) -> 1234 (int)
|
|
||||||
ret[i] = int(f * 100)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
b, ok := v.(bool)
|
|
||||||
if ok {
|
|
||||||
// false => 0, true = 1
|
|
||||||
if b {
|
|
||||||
ret[i] = 1
|
|
||||||
} else {
|
|
||||||
ret[i] = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
// TODO: implement trim and resize
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
// Stat holds basic statistics data for
|
||||||
|
// integer data used for sparklines.
|
||||||
|
type Stat struct {
|
||||||
|
max IntVar
|
||||||
|
// TODO: implement running median
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStat inits new Stat object.
|
||||||
|
func NewStat() *Stat {
|
||||||
|
return &Stat{
|
||||||
|
max: &Number{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update updates stats on each push.
|
||||||
|
func (s *Stat) Update(v IntVar) {
|
||||||
|
if v.Value() > s.max.Value() {
|
||||||
|
s.max = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max returns maximum recorded value.
|
||||||
|
func (s *Stat) Max() IntVar {
|
||||||
|
return s.max
|
||||||
|
}
|
30
ui_multi.go
30
ui_multi.go
|
@ -68,7 +68,7 @@ func (t *TermUI) Init(data UIData) error {
|
||||||
var sparklines []termui.Sparkline
|
var sparklines []termui.Sparkline
|
||||||
for _, service := range data.Services {
|
for _, service := range data.Services {
|
||||||
spl := termui.NewSparkline()
|
spl := termui.NewSparkline()
|
||||||
spl.Height = 1
|
spl.Height = 1 // TODO: set height to th/len(services)
|
||||||
spl.LineColor = termui.ColorGreen
|
spl.LineColor = termui.ColorGreen
|
||||||
spl.Title = service.Name
|
spl.Title = service.Name
|
||||||
sparklines = append(sparklines, spl)
|
sparklines = append(sparklines, spl)
|
||||||
|
@ -113,14 +113,28 @@ func (t *TermUI) Update(data UIData) {
|
||||||
|
|
||||||
// Sparklines
|
// Sparklines
|
||||||
for i, service := range data.Services {
|
for i, service := range data.Services {
|
||||||
max := "MAX" // TODO: FIXME: formatMax(service.Max(data.Vars[0]))
|
name := data.Vars[0]
|
||||||
t.Sparkline1.Lines[i].Title = fmt.Sprintf("%s%s", service.Name, max)
|
v, ok := service.Vars[name].(IntVar)
|
||||||
t.Sparkline1.Lines[i].Data = []int{} // TODO: service.Values(data.Vars[0])
|
if ok {
|
||||||
|
data.Stacks[name].Push(v)
|
||||||
|
data.Stats[name].Update(v)
|
||||||
|
max := data.Stats[name].Max().String()
|
||||||
|
t.Sparkline1.Lines[i].Title = fmt.Sprintf("%s (max: %s)", service.Name, max)
|
||||||
|
t.Sparkline1.Lines[i].Data = data.Stacks[name].IntValues()
|
||||||
|
}
|
||||||
|
|
||||||
if len(data.Vars) > 1 {
|
if len(data.Vars) == 1 {
|
||||||
max = "MAX" // TODO: FIXME: formatMax(service.Max(data.Vars[1]))
|
continue
|
||||||
t.Sparkline2.Lines[i].Title = fmt.Sprintf("%s%s", service.Name, max)
|
}
|
||||||
t.Sparkline2.Lines[i].Data = []int{} // TODO: service.Values(data.Vars[1])
|
|
||||||
|
name = data.Vars[1]
|
||||||
|
v, ok = service.Vars[name].(IntVar)
|
||||||
|
if ok {
|
||||||
|
data.Stacks[name].Push(v)
|
||||||
|
data.Stats[name].Update(v)
|
||||||
|
max := data.Stats[name].Max().String()
|
||||||
|
t.Sparkline2.Lines[i].Title = fmt.Sprintf("%s (max: %s)", service.Name, max)
|
||||||
|
t.Sparkline2.Lines[i].Data = data.Stacks[name].IntValues()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
ui_single.go
16
ui_single.go
|
@ -92,17 +92,21 @@ func (t *TermUISingle) Update(data UIData) {
|
||||||
|
|
||||||
// Sparklines
|
// Sparklines
|
||||||
for i, name := range data.Vars {
|
for i, name := range data.Vars {
|
||||||
|
v, ok := service.Vars[name].(IntVar)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
data.Stacks[name].Push(v)
|
||||||
|
data.Stats[name].Update(v)
|
||||||
|
|
||||||
spl := &t.Sparkline.Lines[i]
|
spl := &t.Sparkline.Lines[i]
|
||||||
|
|
||||||
max := "MAX" // FIXME: formatMax(service.Max(name))
|
max := data.Stats[name].Max().String()
|
||||||
spl.Title = fmt.Sprintf("%s: %v%s", name.Long(), service.Value(name), max)
|
spl.Title = fmt.Sprintf("%s: %v (max: %v)", name.Long(), service.Value(name), max)
|
||||||
spl.TitleColor = colorByKind(name.Kind())
|
spl.TitleColor = colorByKind(name.Kind())
|
||||||
spl.LineColor = colorByKind(name.Kind())
|
spl.LineColor = colorByKind(name.Kind())
|
||||||
|
|
||||||
if name.Kind() == KindString {
|
spl.Data = data.Stacks[name].IntValues()
|
||||||
continue
|
|
||||||
}
|
|
||||||
spl.Data = []int{} // FIXME: service.Values(name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Relayout()
|
t.Relayout()
|
||||||
|
|
24
var.go
24
var.go
|
@ -27,6 +27,13 @@ type Var interface {
|
||||||
Set(*jason.Value)
|
Set(*jason.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IntVar represents variable which value can be represented as integer,
|
||||||
|
// and suitable for displaying with sparklines.
|
||||||
|
type IntVar interface {
|
||||||
|
Var
|
||||||
|
Value() int
|
||||||
|
}
|
||||||
|
|
||||||
type Number struct {
|
type Number struct {
|
||||||
// TODO: add mutex here or level above, in service?
|
// TODO: add mutex here or level above, in service?
|
||||||
val float64
|
val float64
|
||||||
|
@ -46,6 +53,11 @@ func (v *Number) Set(j *jason.Value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Value implements IntVar for Number type.
|
||||||
|
func (v *Number) Value() int {
|
||||||
|
return int(v.val)
|
||||||
|
}
|
||||||
|
|
||||||
type Memory struct {
|
type Memory struct {
|
||||||
bytes int64
|
bytes int64
|
||||||
}
|
}
|
||||||
|
@ -62,6 +74,12 @@ func (v *Memory) Set(j *jason.Value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Value implements IntVar for Memory type.
|
||||||
|
func (v *Memory) Value() int {
|
||||||
|
// TODO: check for possible overflows
|
||||||
|
return int(v.bytes)
|
||||||
|
}
|
||||||
|
|
||||||
type Duration struct {
|
type Duration struct {
|
||||||
dur time.Duration
|
dur time.Duration
|
||||||
}
|
}
|
||||||
|
@ -81,6 +99,12 @@ func (v *Duration) Set(j *jason.Value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Value implements IntVar for Duration type.
|
||||||
|
func (v *Duration) Value() int {
|
||||||
|
// TODO: check for possible overflows
|
||||||
|
return int(v.dur)
|
||||||
|
}
|
||||||
|
|
||||||
type String struct {
|
type String struct {
|
||||||
str string
|
str string
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue