expvarmon/service.go

113 lines
2.2 KiB
Go
Raw Normal View History

2015-04-21 17:51:01 +08:00
package main
import (
2015-04-25 20:54:17 +08:00
"fmt"
"strings"
2015-04-29 05:07:46 +08:00
2015-05-01 04:54:54 +08:00
//"github.com/pyk/byten"
2015-04-21 17:51:01 +08:00
)
2015-05-02 00:13:23 +08:00
// Services is just a slice of Service.
2015-04-21 17:51:01 +08:00
type Services []*Service
// Service represents constantly updating info about single service.
type Service struct {
2015-05-01 04:54:54 +08:00
Port string
Name string
Cmdline string
2015-04-25 20:54:17 +08:00
2015-05-01 23:48:34 +08:00
values map[VarName]*Stack
2015-04-21 17:51:01 +08:00
Err error
}
// NewService returns new Service object.
2015-05-01 23:48:34 +08:00
func NewService(port string, vars []VarName) *Service {
values := make(map[VarName]*Stack)
2015-05-01 21:49:19 +08:00
for _, name := range vars {
2015-05-01 23:48:34 +08:00
values[VarName(name)] = NewStack()
2015-05-01 21:49:19 +08:00
}
2015-04-21 17:51:01 +08:00
return &Service{
Name: port, // we have only port on start, so use it as name until resolved
Port: port,
2015-04-25 21:29:19 +08:00
2015-05-01 21:49:19 +08:00
values: values,
2015-04-21 17:51:01 +08:00
}
2015-04-29 05:07:46 +08:00
}
// Update updates Service info from Expvar variable.
func (s *Service) Update() {
2015-05-01 04:54:54 +08:00
expvar, err := FetchExpvar(s.Addr())
2015-05-01 18:20:06 +08:00
s.Err = err
2015-04-21 17:51:01 +08:00
2015-05-01 05:47:11 +08:00
cmdline, err := expvar.GetStringArray("cmdline")
if err != nil {
s.Err = err
} else {
s.updateCmdline(cmdline)
}
2015-04-25 20:54:17 +08:00
2015-05-01 21:49:19 +08:00
for name, stack := range s.values {
2015-05-01 23:48:34 +08:00
value, err := expvar.GetInt64(name.ToSlice()...)
2015-05-01 21:49:19 +08:00
if err != nil {
continue
}
stack.Push(int(value))
2015-05-01 05:47:11 +08:00
}
2015-05-01 04:54:54 +08:00
}
func (s *Service) updateCmdline(cmdline []string) {
2015-04-25 20:54:17 +08:00
// Update name and cmdline only if empty
2015-05-01 21:49:19 +08:00
// TODO: move it to Update() with sync.Once
2015-04-25 20:54:17 +08:00
if len(s.Cmdline) == 0 {
2015-05-01 04:54:54 +08:00
s.Cmdline = strings.Join(cmdline, " ")
s.Name = BaseCommand(cmdline)
2015-04-25 20:54:17 +08:00
}
2015-05-01 04:54:54 +08:00
}
2015-04-25 21:29:19 +08:00
2015-04-25 20:54:17 +08:00
// Addr returns fully qualified host:port pair for service.
//
// If host is not specified, 'localhost' is used.
func (s Service) Addr() string {
2015-05-02 00:13:23 +08:00
return fmt.Sprintf("http://localhost:%s%s", s.Port, ExpvarsURL)
2015-04-21 17:51:01 +08:00
}
2015-04-26 03:46:16 +08:00
// StatusLine returns status line for services with it's name and status.
func (s Service) StatusLine() string {
if s.Err != nil {
return fmt.Sprintf("[ERR] %s failed", s.Name)
}
return fmt.Sprintf("[R] %s", s.Name)
}
2015-05-02 00:13:23 +08:00
// Value returns current value for the given var of this service.
2015-05-01 23:48:34 +08:00
func (s Service) Value(name VarName) string {
2015-05-01 04:54:54 +08:00
if s.Err != nil {
2015-04-26 03:46:16 +08:00
return "N/A"
}
2015-05-01 23:48:34 +08:00
val, ok := s.values[name]
2015-05-01 04:54:54 +08:00
if !ok {
return "N/A"
}
if val.Front() == 0 {
return "N/A"
}
return fmt.Sprintf("%d", val.Front())
}
2015-05-02 00:13:23 +08:00
// Values returns slice of ints with recent values of the given var,
// to be used with sparkline.
2015-05-01 23:48:34 +08:00
func (s Service) Values(name VarName) []int {
2015-05-01 04:54:54 +08:00
if s.Err != nil {
return nil
}
2015-05-01 23:48:34 +08:00
val, ok := s.values[name]
2015-05-01 04:54:54 +08:00
if !ok {
return nil
}
2015-04-26 03:46:16 +08:00
2015-05-01 04:54:54 +08:00
return val.Values
2015-04-26 03:46:16 +08:00
}