//initializes a test instance of MysqlStatDBs. // instance does not connect with a db func initMysqlStatDBs() *MysqlStatDBs { syscall.Dup2(int(logFile.Fd()), 2) s := new(MysqlStatDBs) s.Db = &testMysqlDB{ Logger: log.New(os.Stderr, "TESTING LOG: ", log.Lshortfile), } s.Metrics = MysqlStatMetricsNew(metrics.NewMetricContext("system")) return s }
func TestMemstat(t *testing.T) { root = "testdata/t0/" // Initialize a metric context m := metrics.NewMetricContext("system") mstat := New(m, time.Millisecond*50) time.Sleep(time.Millisecond * 100) var expected float64 = 1.779400704e+09 actual := mstat.Usage() if actual != expected { t.Errorf("Memstat Usage: %v expected: %v", actual, expected) } }
func initMysqlStatTable() *MysqlStatTables { syscall.Dup2(int(logFile.Fd()), 2) s := new(MysqlStatTables) s.Db = &testMysqlDB{ Logger: log.New(os.Stderr, "TESTING LOG: ", log.Lshortfile), } s.nLock = &sync.Mutex{} s.M = metrics.NewMetricContext("system") s.DBs = make(map[string]*DBStats) return s }
func TestTcpstat(t *testing.T) { root = "testdata/t0/" // Initialize a metric context m := metrics.NewMetricContext("system") tstat := New(m, time.Millisecond*50) time.Sleep(time.Millisecond * 200) var expected float64 = 45 actual := tstat.CurrEstab.Get() if actual != expected { t.Errorf("Tcpstat current estab: %v expected: %v", actual, expected) } }
func TestPidstatMem(t *testing.T) { root = "testdata/t0/" // Initialize a metric context m := metrics.NewMetricContext("system") pstat := NewProcessStat(m, time.Millisecond*50) time.Sleep(time.Millisecond * 1000) root = "testdata/t1/" time.Sleep(time.Millisecond * 1000) var expected float64 = 1.794048e+06 actual := pstat.ByMemUsage()[0].MemUsage() if math.Abs(actual-expected) > 0.01 { t.Errorf("Mem usage for top pid: %v expected: %v", actual, expected) } }
func TestLoadstat(t *testing.T) { root = "testdata/t0/" // Initialize a metric context m := metrics.NewMetricContext("system") lstat := New(m, time.Millisecond*50) time.Sleep(time.Millisecond * 1000) root = "testdata/t1/" time.Sleep(time.Millisecond * 200) var expected float64 = 0.13 actual := lstat.OneMinute.Get() if actual != expected { t.Errorf("OneMinute loadavg: %v expected: %v", actual, expected) } }
func TestDiskStat(t *testing.T) { root = "testdata/t0/" // Initialize a metric context m := metrics.NewMetricContext("system") dstat := New(m, time.Millisecond*50) time.Sleep(time.Millisecond * 1000) root = "testdata/t1/" time.Sleep(time.Millisecond * 100) var expected uint64 = 99609658 actual := dstat.Disks["sda"].IOSpentMsecs.Get() if actual != expected { t.Errorf("Diskstat: %v expected: %v", actual, expected) } }
func TestInterfaceStat(t *testing.T) { root = "testdata/t0/" // Initialize a metric context m := metrics.NewMetricContext("system") istat := New(m, time.Millisecond*50) time.Sleep(time.Millisecond * 1000) root = "testdata/t1/" time.Sleep(time.Millisecond * 100) var expected uint64 = 7070289382 actual := istat.Interfaces["eth0"].Metrics.TXbytes.Get() if actual != expected { t.Errorf("interfacestat txbytes: %v expected: %v", actual, expected) } }
func TestCPUUsage(t *testing.T) { root = "testdata/t0/" // Initialize a metric context m := metrics.NewMetricContext("system") cstat := New(m, time.Millisecond*50) time.Sleep(time.Millisecond * 1000) root = "testdata/t1/" time.Sleep(time.Millisecond * 100) var expected uint64 = 161584849 actual := cstat.All.User.Get() if actual != expected { t.Errorf("CPU user counter: %v expected: %v", actual, expected) } }
func initMetricsContext() *metrics.MetricContext { m := metrics.NewMetricContext("test") g1 := metrics.NewGauge() m.Register(g1, "testGauge1") g2 := metrics.NewGauge() m.Register(g2, "testGauge2") g3 := metrics.NewGauge() m.Register(g3, "testGauge3") g4 := metrics.NewGauge() m.Register(g4, "testGauge4") g5 := metrics.NewGauge() m.Register(g5, "testGauge5") g2.Set(float64(200)) g3.Set(float64(300)) g4.Set(float64(400)) g5.Set(float64(500)) return m }
func main() { var user, address, conf string var stepSec int var servermode, human, loop bool m := metrics.NewMetricContext("system") flag.StringVar(&user, "u", "postgres", "user using database") flag.BoolVar(&servermode, "server", false, "Runs continously and exposes metrics as JSON on HTTP") flag.StringVar(&address, "address", ":12345", "address to listen on for http if running in server mode") flag.IntVar(&stepSec, "step", 2, "metrics are collected every step seconds") flag.StringVar(&conf, "conf", "/root/.my.cnf", "configuration file") flag.BoolVar(&human, "h", false, "Makes output in MB for human readable sizes") flag.BoolVar(&loop, "loop", false, "loop") flag.Parse() if servermode { go func() { http.HandleFunc("/metrics.json", m.HttpJsonHandler) log.Fatal(http.ListenAndServe(address, nil)) }() } step := time.Millisecond * time.Duration(stepSec) * 1000 sqlstat, err := stat.New(m, user, conf) if err != nil { fmt.Println(err) return } defer sqlstat.Close() if loop { ticker := time.NewTicker(step * 2) for _ = range ticker.C { sqlstat.Collect() printAll(*sqlstat) //Print stats here, more stats than printed are actually collected/ stats con be removed from here } } else { sqlstat.Collect() printAll(*sqlstat) } }
func TestLoadstat(t *testing.T) { root = "testdata/t0/" // Initialize a metric context m := metrics.NewMetricContext("system") ustat := New(m, time.Millisecond*50) time.Sleep(time.Millisecond * 1000) root = "testdata/t1/" time.Sleep(time.Millisecond * 200) var expectedUp float64 = 1 var expectedIdle float64 = 4 actualUp := ustat.Uptime.Get() actualIdle := ustat.Idle.Get() if actualUp != expectedUp { t.Errorf("Uptime: %v expected: %v", actualUp, expectedUp) } if actualIdle != expectedIdle { t.Errorf("Uptime: %v expected: %v", actualIdle, expectedIdle) } }
//Initializes test instance of PostgresStat // Important to not connect to database func initPostgresStat() *PostgresStat { syscall.Dup2(int(logFile.Fd()), 2) s := new(PostgresStat) s.db = &testPostgresDB{ Logger: log.New(os.Stderr, "TESTING LOG: ", 0), } s.PGDATA = "/data/pgsql" s.m = metrics.NewMetricContext("system") s.Modes = make(map[string]*ModeMetrics) s.DBs = make(map[string]*DBMetrics) s.Metrics = PostgresStatMetricsNew(s.m) s.dbLock = &sync.Mutex{} s.modeLock = &sync.Mutex{} s.pidCol = "procpid" s.queryCol = "current_query" s.idleCol = s.queryCol s.idleStr = "<IDLE>" return s }
func main() { var user, password, host, address, cnf, form, checkConfigFile string var stepSec int var servermode, human, loop bool var checkConfig *conf.ConfigFile m := metrics.NewMetricContext("system") flag.StringVar(&user, "u", "root", "user using database") flag.StringVar(&password, "p", "", "password for database") flag.StringVar(&host, "h", "", "address and protocol of the database to connect to. leave blank for tcp(127.0.0.1:3306)") flag.BoolVar(&servermode, "server", false, "Runs continously and exposes metrics as JSON on HTTP") flag.StringVar(&address, "address", ":12345", "address to listen on for http if running in server mode") flag.IntVar(&stepSec, "step", 2, "metrics are collected every step seconds") flag.StringVar(&cnf, "cnf", "/root/.my.cnf", "configuration file") flag.StringVar(&form, "form", "graphite", "output format of metrics to stdout") flag.BoolVar(&human, "human", false, "Makes output in MB for human readable sizes") flag.BoolVar(&loop, "loop", false, "loop on collecting metrics") flag.StringVar(&checkConfigFile, "check", "", "config file to check metrics with") flag.Parse() if servermode { go func() { http.HandleFunc("/api/v1/metrics.json/", m.HttpJsonHandler) log.Fatal(http.ListenAndServe(address, nil)) }() } step := time.Millisecond * time.Duration(stepSec) * 1000 var err error var c metricchecks.Checker checkConfig = conf.NewConfigFile() if checkConfigFile != "" { cnf, err := metricchecks.FileToConfig(checkConfigFile) if err != nil { checkConfigFile = "" } else { checkConfig = cnf } } c, err = metricchecks.New("", checkConfig) if err != nil { checkConfigFile = "" } //initialize metrics collectors to not loop and collect sqlstatDBs, err := dbstat.New(m, user, password, host, cnf) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } sqlstatTables, err := tablestat.New(m, user, password, host, cnf) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } sqlstatUsers, err := userstat.New(m, user, password, host, cnf) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } sqlstatDBs.Collect() sqlstatTables.Collect() sqlstatUsers.Collect() if checkConfigFile != "" { checkMetrics(c, m) } outputTableMetrics(sqlstatDBs, sqlstatTables, m, form) outputUserMetrics(sqlstatUsers, m, form) if loop { ticker := time.NewTicker(step) for _ = range ticker.C { sqlstatDBs.Collect() sqlstatTables.Collect() sqlstatUsers.Collect() outputTableMetrics(sqlstatDBs, sqlstatTables, m, form) outputUserMetrics(sqlstatUsers, m, form) } } sqlstatDBs.Close() sqlstatTables.Close() sqlstatUsers.Close() }
func main() { // never use more than one process runtime.GOMAXPROCS(1) // wait group to let the main program run forever in batchmode var wg sync.WaitGroup // options var batchmode, servermode bool var address string var stepSec int var nIter int var evt <-chan termui.Event var widgets *osmain.DisplayWidgets var uiSummaryBody *termui.Grid var uiHelpBody *termui.Grid var uiDetailList *termui.List flag.BoolVar(&batchmode, "b", false, "Run in batch mode; suitable for parsing") flag.BoolVar(&batchmode, "batchmode", false, "Run in batch mode; suitable for parsing") flag.IntVar(&nIter, "n", 0, "Quit after these many iterations") flag.IntVar(&nIter, "iterations", 0, "Quit after these many iterations") flag.BoolVar(&servermode, "server", false, "Runs continously and exposes metrics as JSON on HTTP") flag.StringVar(&address, "address", ":19999", "address to listen on for http if running in server mode") flag.IntVar(&stepSec, "step", 2, "metrics are collected every step seconds") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Options \n") fmt.Fprintf(os.Stderr, "------- \n") flag.PrintDefaults() fmt.Fprintf(os.Stderr, "Notes \n") fmt.Fprintf(os.Stderr, "------- \n") fmt.Fprintf(os.Stderr, "All CPU percentages are normalized to total number of logical cpus \n") } flag.Parse() if servermode { batchmode = true } if !batchmode { err := termui.Init() termui.UseTheme("helloworld") if err != nil { log.Fatalf("Unable to initialize termui", err) } widgets = uiWidgets() uiSummaryBody = uiSummary(widgets) uiHelpBody = uiHelp() uiDetailList = termui.NewList() evt = termui.EventCh() // display summary view termui.Body = uiSummaryBody uiRefresh() } // Initialize a metric context m := metrics.NewMetricContext("system") // Default step for collectors step := time.Millisecond * time.Duration(stepSec) * 1000 // Register various stats we are interested in tracking stats := osmain.Register(m, step) // run http server if servermode { go func() { http.HandleFunc("/api/v1/metrics.json", m.HttpJsonHandler) log.Fatal(http.ListenAndServe(address, nil)) }() } iterationsRun := 0 // runs forever wg.Add(1) go func() { for { // Clear previous problems var problems []string stats.Problems = problems // Quit after n iterations if specified iterationsRun++ if nIter > 0 && iterationsRun > nIter { break } stats.Print(batchmode, widgets) if !batchmode { termui.Render(termui.Body) } time.Sleep(step) // be aggressive about reclaiming memory // tradeoff with CPU usage runtime.GC() debug.FreeOSMemory() } }() if !batchmode { for { e := <-evt if e.Type == termui.EventKey { switch e.Ch { case 'q': termui.Close() return case 'c': uiDetailList = widgets.ProcessesByCPU termui.Body = uiDetail(uiDetailList) case 'd': uiDetailList = widgets.DiskIOUsage termui.Body = uiDetail(uiDetailList) case 'C': uiDetailList = widgets.CgroupsCPU termui.Body = uiDetail(uiDetailList) case 'f': uiDetailList = widgets.FileSystemUsage termui.Body = uiDetail(uiDetailList) case 'm': uiDetailList = widgets.ProcessesByMemory termui.Body = uiDetail(uiDetailList) case 'p': uiDetailList = widgets.Problems termui.Body = uiDetail(uiDetailList) case 'M': uiDetailList = widgets.CgroupsMem termui.Body = uiDetail(uiDetailList) case 'n': uiDetailList = widgets.InterfaceUsage termui.Body = uiDetail(uiDetailList) case 'i': uiDetailList = widgets.ProcessesByIO termui.Body = uiDetail(uiDetailList) case 's': uiResetAttributes(widgets) termui.Body = uiSummaryBody case 'h': termui.Body = uiHelpBody } uiRefresh() } if e.Type == termui.EventResize { uiRefresh() } } } wg.Wait() }