diff --git a/service.go b/service.go index 474e7d6..297d9fd 100644 --- a/service.go +++ b/service.go @@ -6,6 +6,8 @@ import ( "strconv" "strings" "sync" + + "github.com/antonholmquist/jason" ) // Service represents constantly updating info about single service. @@ -52,14 +54,31 @@ func (s *Service) Update(wg *sync.WaitGroup) { // For all vars, fetch desired value from Json and push to it's own stack. for name, stack := range s.values { - value, err := expvar.GetInt64(name.ToSlice()...) + value, err := expvar.GetValue(name.ToSlice()...) if err != nil { continue } - stack.Push(int(value)) + v := guessValue(value) + if v != nil { + stack.Push(v) + } } } +func guessValue(value *jason.Value) interface{} { + if v, err := value.Int64(); err == nil { + return v + } else if v, err := value.Float64(); err == nil { + return v + } else if v, err := value.Boolean(); err == nil { + return v + } else if v, err := value.String(); err == nil { + return v + } + + return nil +} + // Addr returns fully qualified host:port pair for service. // // If host is not specified, 'localhost' is used. @@ -96,23 +115,23 @@ func (s Service) Value(name VarName) string { if !ok { return "N/A" } - if val.Front() == 0 { + if val.Front() == nil { return "N/A" } - return fmt.Sprintf("%d", val.Front()) + return fmt.Sprintf("%v", val.Front()) } -// Values returns slice of ints with recent values of the given var, -// to be used with sparkline. +// Values returns slice of ints with recent +// values of the given var, to be used with sparkline. func (s Service) Values(name VarName) []int { if s.Err != nil { return nil } - val, ok := s.values[name] + stack, ok := s.values[name] if !ok { return nil } - return val.Values + return stack.IntValues() } diff --git a/stack.go b/stack.go index a1e55a8..3d924fa 100644 --- a/stack.go +++ b/stack.go @@ -8,7 +8,7 @@ const DefaultSize = 1200 // Stack is a limited FIFO for holding sparkline values. type Stack struct { - Values []int + Values []interface{} Len int } @@ -20,13 +20,13 @@ func NewStack() *Stack { // NewStackWithSize inits new Stack with size limit. func NewStackWithSize(size int) *Stack { return &Stack{ - Values: make([]int, size), + Values: make([]interface{}, size), Len: size, } } // Push inserts data to stack, preserving constant length. -func (s *Stack) Push(val int) { +func (s *Stack) Push(val interface{}) { s.Values = append(s.Values, val) if len(s.Values) > s.Len { s.Values = s.Values[1:] @@ -34,9 +34,33 @@ func (s *Stack) Push(val int) { } // Front returns front value. -func (s *Stack) Front() int { +func (s *Stack) Front() interface{} { if len(s.Values) == 0 { - return 0 + return nil } return s.Values[len(s.Values)-1] } + +// IntValues returns stack values explicitly casted to int. +// +// Main case is to use with termui.Sparklines. +func (s *Stack) IntValues() []int { + ret := make([]int, s.Len) + for i, v := range s.Values { + n, ok := v.(int64) + if ok { + ret[i] = int(n) + continue + } + + b, ok := v.(bool) + if ok { + if b { + ret[i] = 1 + } else { + ret[i] = 0 + } + } + } + return ret +} diff --git a/stack_test.go b/stack_test.go index 4837ea9..092d8dc 100644 --- a/stack_test.go +++ b/stack_test.go @@ -21,7 +21,7 @@ func TestStack(t *testing.T) { } } - if s.Front() != 14 { + if s.Front().(int) != 14 { t.Fatalf("Front returns wrong value: expecting %d, got %d", 14, s.Front()) } } diff --git a/ui_termui.go b/ui_termui.go index 2ff8602..43a20cc 100644 --- a/ui_termui.go +++ b/ui_termui.go @@ -104,12 +104,14 @@ func (t *TermUI) Update(data UIData) { t.Title.Text = fmt.Sprintf("monitoring %d services, press q to quit", len(data.Services)) t.Status.Text = fmt.Sprintf("Last update: %v", data.LastTimestamp.Format("15:04:05 02/Jan/06")) + // List with service names var services []string for _, service := range data.Services { services = append(services, service.StatusLine()) } t.Services.Items = services + // Lists with values for _, name := range data.Vars { var lines []string for _, service := range data.Services { @@ -119,9 +121,10 @@ func (t *TermUI) Update(data UIData) { } // Sparklines + topVar := data.Vars[0] for i, service := range data.Services { t.MemSparkline.Lines[i].Title = service.Name - t.MemSparkline.Lines[i].Data = service.Values(data.Vars[0]) + t.MemSparkline.Lines[i].Data = service.Values(topVar) } termui.Body.Width = termui.TermWidth()