github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/utils/pprof.go (about) 1 // Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0. 2 3 package utils 4 5 import ( 6 "fmt" 7 "net" 8 "net/http" 9 "os" 10 "sync" 11 12 tidbutils "github.com/pingcap/tidb-tools/pkg/utils" 13 14 berrors "github.com/pingcap/br/pkg/errors" 15 16 "github.com/pingcap/errors" 17 18 // #nosec 19 // register HTTP handler for /debug/pprof 20 _ "net/http/pprof" 21 22 "github.com/pingcap/failpoint" 23 "github.com/pingcap/log" 24 "go.uber.org/zap" 25 ) 26 27 var ( 28 startedPProf = "" 29 mu sync.Mutex 30 ) 31 32 func listen(statusAddr string) (net.Listener, error) { 33 mu.Lock() 34 defer mu.Unlock() 35 if startedPProf != "" { 36 log.Warn("Try to start pprof when it has been started, nothing will happen", zap.String("address", startedPProf)) 37 return nil, errors.Annotate(berrors.ErrUnknown, "try to start pprof when it has been started at "+startedPProf) 38 } 39 failpoint.Inject("determined-pprof-port", func(v failpoint.Value) { 40 port := v.(int) 41 statusAddr = fmt.Sprintf(":%d", port) 42 log.Info("injecting failpoint, pprof will start at determined port", zap.Int("port", port)) 43 }) 44 listener, err := net.Listen("tcp", statusAddr) 45 if err != nil { 46 log.Warn("failed to start pprof", zap.String("addr", statusAddr), zap.Error(err)) 47 return nil, errors.Trace(err) 48 } 49 startedPProf = listener.Addr().String() 50 log.Info("bound pprof to addr", zap.String("addr", startedPProf)) 51 _, _ = fmt.Fprintf(os.Stderr, "bound pprof to addr %s\n", startedPProf) 52 return listener, nil 53 } 54 55 // StartPProfListener forks a new goroutine listening on specified port and provide pprof info. 56 func StartPProfListener(statusAddr string, wrapper *tidbutils.TLS) error { 57 listener, err := listen(statusAddr) 58 if err != nil { 59 return err 60 } 61 62 go func() { 63 if e := http.Serve(wrapper.WrapListener(listener), nil); e != nil { 64 log.Warn("failed to serve pprof", zap.String("addr", startedPProf), zap.Error(e)) 65 mu.Lock() 66 startedPProf = "" 67 mu.Unlock() 68 return 69 } 70 }() 71 return nil 72 }