Add call trace command
This commit is contained in:
		@@ -34,8 +34,6 @@ import (
 | 
				
			|||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	gob.Register(map[string]interface{}{})
 | 
						gob.Register(map[string]interface{}{})
 | 
				
			||||||
	gob.Register([]interface{}{})
 | 
						gob.Register([]interface{}{})
 | 
				
			||||||
	gob.Register(&Room{})
 | 
					 | 
				
			||||||
	gob.Register(0)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type RoomNameSource int
 | 
					type RoomNameSource int
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,6 +109,7 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor {
 | 
				
			|||||||
			"invite":          cmdInvite,
 | 
								"invite":          cmdInvite,
 | 
				
			||||||
			"hprof":           cmdHeapProfile,
 | 
								"hprof":           cmdHeapProfile,
 | 
				
			||||||
			"cprof":           cmdCPUProfile,
 | 
								"cprof":           cmdCPUProfile,
 | 
				
			||||||
 | 
								"trace":           cmdTrace,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,10 +19,12 @@ package ui
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"runtime"
 | 
						"runtime"
 | 
				
			||||||
	dbg "runtime/debug"
 | 
						dbg "runtime/debug"
 | 
				
			||||||
	"runtime/pprof"
 | 
						"runtime/pprof"
 | 
				
			||||||
 | 
						"runtime/trace"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
@@ -92,38 +94,37 @@ func cmdHeapProfile(cmd *Command) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func cmdCPUProfile(cmd *Command) {
 | 
					func runTimedProfile(cmd *Command, start func(writer io.Writer) error, stop func(), task, file string) {
 | 
				
			||||||
	if len(cmd.Args) == 0 {
 | 
						if len(cmd.Args) == 0 {
 | 
				
			||||||
		cmd.Reply("Usage: /cprof <seconds>")
 | 
							cmd.Reply("Usage: /%s <seconds>", cmd.Command)
 | 
				
			||||||
		return
 | 
						} else if dur, err := strconv.Atoi(cmd.Args[0]); err != nil || dur < 0 {
 | 
				
			||||||
	}
 | 
							cmd.Reply("Usage: /%s <seconds>", cmd.Command)
 | 
				
			||||||
	dur, err := strconv.Atoi(cmd.Args[0])
 | 
						} else if cpuProfile, err := os.Create(file); err != nil {
 | 
				
			||||||
	if err != nil || dur < 0 {
 | 
							debug.Printf("Failed to open %s: %v", file, err)
 | 
				
			||||||
		cmd.Reply("Usage: /cprof <seconds>")
 | 
						} else if err = start(cpuProfile); err != nil {
 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cpuProfile, err := os.Create("gomuks.cpu.prof")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		debug.Print("Failed to open gomuks.cpu.prof:", err)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	err = pprof.StartCPUProfile(cpuProfile)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		_ = cpuProfile.Close()
 | 
							_ = cpuProfile.Close()
 | 
				
			||||||
		debug.Print("CPU profile error:", err)
 | 
							debug.Print(task, "error:", err)
 | 
				
			||||||
		return
 | 
						} else {
 | 
				
			||||||
	}
 | 
							cmd.Reply("Started %s for %d seconds", task, dur)
 | 
				
			||||||
	cmd.Reply("Started CPU profiling for %d seconds", dur)
 | 
							go func() {
 | 
				
			||||||
	go func() {
 | 
								time.Sleep(time.Duration(dur) * time.Second)
 | 
				
			||||||
		time.Sleep(time.Duration(dur) * time.Second)
 | 
								stop()
 | 
				
			||||||
		pprof.StopCPUProfile()
 | 
								cmd.Reply("%s finished.", task)
 | 
				
			||||||
		cmd.Reply("CPU profiling finished.")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err := cpuProfile.Close()
 | 
								err := cpuProfile.Close()
 | 
				
			||||||
		if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
			debug.Print("Failed to close gomuks.cpu.prof:", err)
 | 
									debug.Print("Failed to close gomuks.cpu.prof:", err)
 | 
				
			||||||
		}
 | 
								}
 | 
				
			||||||
	}()
 | 
							}()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdCPUProfile(cmd *Command) {
 | 
				
			||||||
 | 
						runTimedProfile(cmd, pprof.StartCPUProfile, pprof.StopCPUProfile, "CPU profiling", "gomuks.cpu.prof")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdTrace(cmd *Command) {
 | 
				
			||||||
 | 
						runTimedProfile(cmd, trace.Start, trace.Stop, "Call tracing", "gomuks.trace")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO this command definitely belongs in a plugin once we have a plugin system.
 | 
					// TODO this command definitely belongs in a plugin once we have a plugin system.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user