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