1 // Top like progream which collects information from MySQL's
2 // performance_schema database.
16 _ "github.com/go-sql-driver/mysql"
17 "github.com/nsf/termbox-go"
19 "github.com/sjmudd/mysql_defaults_file"
20 "github.com/sjmudd/pstop/lib"
21 "github.com/sjmudd/pstop/state"
22 "github.com/sjmudd/pstop/version"
27 db = "performance_schema"
30 var flag_version = flag.Bool("version", false, "Show the version of "+lib.MyName())
31 var flag_debug = flag.Bool("debug", false, "Enabling debug logging")
32 var flag_help = flag.Bool("help", false, "Provide some help for "+lib.MyName())
33 var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
35 func get_db_handle() *sql.DB {
39 dbh, err = mysql_defaults_file.OpenUsingDefaultsFile(sql_driver, "", "performance_schema")
43 if err = dbh.Ping(); err != nil {
50 // make chan for termbox events and run a poller to send events to the channel
51 // - return the channel
52 func new_tb_chan() chan termbox.Event {
53 termboxChan := make(chan termbox.Event)
56 termboxChan <- termbox.PollEvent()
63 fmt.Println(lib.MyName() + " - " + lib.Copyright())
65 fmt.Println("Top-like program to show MySQL activity by using information collected")
66 fmt.Println("from performance_schema.")
68 fmt.Println("Usage: " + lib.MyName() + " <options>")
70 fmt.Println("Options:")
71 fmt.Println("-help show this help message")
72 fmt.Println("-version show the version")
79 if *cpuprofile != "" {
80 f, err := os.Create(*cpuprofile)
84 pprof.StartCPUProfile(f)
85 defer pprof.StopCPUProfile()
89 lib.Logger.EnableLogging(true)
92 fmt.Println(lib.MyName() + " version " + version.Version())
100 lib.Logger.Println("Starting " + lib.MyName())
101 var state state.State
103 interval := time.Second
104 sigChan := make(chan os.Signal, 1)
105 done := make(chan struct{})
107 termboxChan := new_tb_chan()
109 signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
111 ticker := time.NewTicker(interval) // generate a periodic signal
113 state.Setup(get_db_handle())
119 fmt.Println("exiting")
121 case sig := <-sigChan:
122 fmt.Println("Caught a signal", sig)
127 case event := <-termboxChan:
128 // switch on event type
130 case termbox.EventKey: // actions depend on key
132 case termbox.KeyCtrlZ, termbox.KeyCtrlC, termbox.KeyEsc:
134 case termbox.KeyTab: // tab - change display modes
139 case '-': // decrease the interval if > 1
140 if interval > time.Second {
142 interval -= time.Second
143 ticker = time.NewTicker(interval)
145 case '+': // increase interval by creating a new ticker
147 interval += time.Second
148 ticker = time.NewTicker(interval)
150 state.SetHelp(!state.Help())
153 case 't': // toggle between absolute/relative statistics
154 state.SetWantRelativeStats(!state.WantRelativeStats())
156 case 'z': // reset the statistics to now by taking a query of current values
157 state.ResetDBStatistics()
160 case termbox.EventResize: // set sizes
161 state.ScreenSetSize(event.Width, event.Height)
163 case termbox.EventError: // quit
164 log.Fatalf("Quitting because of termbox error: \n%s\n", event.Err)
170 lib.Logger.Println("Terminating " + lib.MyName())