expvarmon/main.go

125 lines
2.7 KiB
Go
Raw Normal View History

2015-04-21 17:51:01 +08:00
package main
import (
"flag"
2015-05-04 01:21:19 +08:00
"fmt"
2015-04-21 17:51:01 +08:00
"log"
2015-05-04 01:21:19 +08:00
"os"
2015-05-02 01:12:23 +08:00
"sync"
2015-04-21 17:51:01 +08:00
"time"
2015-05-04 00:46:36 +08:00
"github.com/gizak/termui"
2015-04-21 17:51:01 +08:00
)
var (
urls = &StringArray{}
2015-05-02 01:12:23 +08:00
interval = flag.Duration("i", 5*time.Second, "Polling interval")
2015-05-04 01:21:19 +08:00
portsArg = flag.String("ports", "", "Ports for accessing services expvars (start-end,port2,port3)")
2015-05-03 21:52:38 +08:00
varsArg = flag.String("vars", "mem:memstats.Alloc,mem:memstats.Sys,mem:memstats.HeapAlloc,mem:memstats.HeapInuse,memstats.EnableGC,memstats.NumGC,duration:memstats.PauseTotalNs", "Vars to monitor (comma-separated)")
2015-05-02 01:12:23 +08:00
dummy = flag.Bool("dummy", false, "Use dummy (console) output")
2015-05-04 01:21:19 +08:00
self = flag.Bool("self", false, "Monitor itself")
2015-04-21 17:51:01 +08:00
)
func main() {
flag.Var(urls, "url", "urls to poll for expvars")
2015-05-04 01:21:19 +08:00
flag.Usage = Usage
2015-04-21 17:51:01 +08:00
flag.Parse()
2015-05-04 00:58:50 +08:00
2015-05-04 01:21:19 +08:00
// Process ports
ports, _ := ParsePorts(*portsArg)
if *self {
port, err := StartSelfMonitor()
if err == nil {
ports = append(ports, port)
}
2015-05-04 00:58:50 +08:00
}
ports = append(ports, *urls...)
2015-05-04 01:21:19 +08:00
if len(ports) == 0 {
fmt.Fprintln(os.Stderr, "no ports specified. Use -ports arg to specify ports of Go apps to monitor")
Usage()
os.Exit(1)
}
if *interval <= 0 {
fmt.Fprintln(os.Stderr, "update interval is not valid. Valid examples: 5s, 1m, 1h30m")
2015-05-04 01:21:19 +08:00
Usage()
os.Exit(1)
2015-04-21 17:51:01 +08:00
}
2015-05-04 01:21:19 +08:00
// Process vars
2015-05-02 01:12:23 +08:00
vars, err := ParseVars(*varsArg)
2015-05-01 21:49:19 +08:00
if err != nil {
log.Fatal(err)
}
2015-05-04 01:21:19 +08:00
// Init UIData
2015-05-01 21:49:19 +08:00
data := NewUIData(vars)
2015-04-21 17:51:01 +08:00
for _, port := range ports {
2015-05-01 21:49:19 +08:00
service := NewService(port, vars)
2015-04-21 17:51:01 +08:00
data.Services = append(data.Services, service)
}
2015-05-04 01:21:19 +08:00
// Start proper UI
2015-05-03 02:17:51 +08:00
var ui UI
if len(data.Services) > 1 {
ui = &TermUI{}
} else {
ui = &TermUISingle{}
}
2015-04-21 17:51:01 +08:00
if *dummy {
ui = &DummyUI{}
}
2015-05-03 02:17:51 +08:00
2015-05-02 00:13:23 +08:00
if err := ui.Init(*data); err != nil {
log.Fatal(err)
}
2015-04-21 17:51:01 +08:00
defer ui.Close()
tick := time.NewTicker(*interval)
evtCh := termui.EventCh()
2015-05-02 01:12:23 +08:00
UpdateAll(ui, data)
2015-04-21 17:51:01 +08:00
for {
select {
case <-tick.C:
2015-05-02 01:12:23 +08:00
UpdateAll(ui, data)
2015-04-21 17:51:01 +08:00
case e := <-evtCh:
if e.Type == termui.EventKey && e.Ch == 'q' {
return
}
2015-04-26 03:46:16 +08:00
if e.Type == termui.EventResize {
2015-05-03 22:54:56 +08:00
ui.Update(*data)
2015-04-26 03:46:16 +08:00
}
2015-04-21 17:51:01 +08:00
}
}
}
2015-05-02 01:12:23 +08:00
// UpdateAll collects data from expvars and refreshes UI.
func UpdateAll(ui UI, data *UIData) {
var wg sync.WaitGroup
for _, service := range data.Services {
wg.Add(1)
go service.Update(&wg)
}
wg.Wait()
data.LastTimestamp = time.Now()
ui.Update(*data)
}
2015-05-04 01:21:19 +08:00
// Usage reimplements flag.Usage
func Usage() {
progname := os.Args[0]
fmt.Fprintf(os.Stderr, "Usage of %s:\n", progname)
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, `
Examples:
%s -ports="80"
%s -ports="23000-23010,80" -i=1m
%s -ports="80,remoteapp:80" -vars="mem:memstats.Alloc,duration:Response.Mean,Counter"
%s -ports="1234-1236" -vars="Goroutines" -self
For more details and docs, see README: http://github.com/divan/expvarmon
`, progname, progname, progname, progname)
}