package main import ( "github.com/emicklei/go-restful" "io" "log" "os" "runtime/pprof" ) // ProfilingService is a WebService that can start/stop a CPU profile and write results to a file // GET /{rootPath}/start will activate CPU profiling // GET /{rootPath}/stop will stop profiling // // NewProfileService("/profiler", "ace.prof").AddWebServiceTo(restful.DefaultContainer) // type ProfilingService struct { rootPath string // the base (root) of the service, e.g. /profiler cpuprofile string // the output filename to write profile results, e.g. myservice.prof cpufile *os.File // if not nil, then profiling is active } func NewProfileService(rootPath string, outputFilename string) *ProfilingService { ps := new(ProfilingService) ps.rootPath = rootPath ps.cpuprofile = outputFilename return ps } // Add this ProfileService to a restful Container func (p ProfilingService) AddWebServiceTo(container *restful.Container) { ws := new(restful.WebService) ws.Path(p.rootPath).Consumes("*/*").Produces(restful.MIME_JSON) ws.Route(ws.GET("/start").To(p.startProfiler)) ws.Route(ws.GET("/stop").To(p.stopProfiler)) container.Add(ws) } func (p *ProfilingService) startProfiler(req *restful.Request, resp *restful.Response) { if p.cpufile != nil { io.WriteString(resp.ResponseWriter, "[restful] CPU profiling already running") return // error? } cpufile, err := os.Create(p.cpuprofile) if err != nil { log.Fatal(err) } // remember for close p.cpufile = cpufile pprof.StartCPUProfile(cpufile) io.WriteString(resp.ResponseWriter, "[restful] CPU profiling started, writing on:"+p.cpuprofile) } func (p *ProfilingService) stopProfiler(req *restful.Request, resp *restful.Response) { if p.cpufile == nil { io.WriteString(resp.ResponseWriter, "[restful] CPU profiling not active") return // error? } pprof.StopCPUProfile() p.cpufile.Close() p.cpufile = nil io.WriteString(resp.ResponseWriter, "[restful] CPU profiling stopped, closing:"+p.cpuprofile) } func main() {} // exists for example compilation only