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