mirror of
https://github.com/linka-cloud/grpc.git
synced 2026-01-25 11:05:05 +00:00
feat(pprof): add pyroscope profiler support
Signed-off-by: Adphi <philippe.adrien.nousse@gmail.com>
This commit is contained in:
127
pprof/options.go
Normal file
127
pprof/options.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package pprof
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/grafana/pyroscope-go"
|
||||
)
|
||||
|
||||
const (
|
||||
PyroscopeAddressEnv = "PYROSCOPE_ADDRESS"
|
||||
PyroscopeUserEnv = "PYROSCOPE_USER"
|
||||
PyroscopePasswordEnv = "PYROSCOPE_PASSWORD"
|
||||
)
|
||||
|
||||
type Option func(*options)
|
||||
|
||||
func WithAddress(address string) Option {
|
||||
return func(o *options) {
|
||||
if address != "" {
|
||||
o.address = address
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithUser(user string) Option {
|
||||
return func(o *options) {
|
||||
if user != "" {
|
||||
o.user = user
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithPassword(password string) Option {
|
||||
return func(o *options) {
|
||||
if password != "" {
|
||||
o.password = password
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithAddressEnv(env string) Option {
|
||||
return func(o *options) {
|
||||
if env != "" {
|
||||
o.addressEnv = env
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithUserEnv(env string) Option {
|
||||
return func(o *options) {
|
||||
if env != "" {
|
||||
o.userEnv = env
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithPasswordEnv(env string) Option {
|
||||
return func(o *options) {
|
||||
if env != "" {
|
||||
o.passwordEnv = env
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithMutexProfileFraction(fraction int) Option {
|
||||
return func(o *options) {
|
||||
o.mutexProfileFraction = fraction
|
||||
}
|
||||
}
|
||||
|
||||
func WithBlockProfileRate(rate int) Option {
|
||||
return func(o *options) {
|
||||
o.blockProfileRate = rate
|
||||
}
|
||||
}
|
||||
|
||||
func WithProfiles(profiles ...pyroscope.ProfileType) Option {
|
||||
return func(o *options) {
|
||||
if len(profiles) != 0 {
|
||||
o.profiles = profiles
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type options struct {
|
||||
address string
|
||||
user string
|
||||
password string
|
||||
|
||||
addressEnv string
|
||||
userEnv string
|
||||
passwordEnv string
|
||||
|
||||
mutexProfileFraction int
|
||||
blockProfileRate int
|
||||
|
||||
profiles []pyroscope.ProfileType
|
||||
}
|
||||
|
||||
var defaultOptions = options{
|
||||
addressEnv: PyroscopeAddressEnv,
|
||||
userEnv: PyroscopeUserEnv,
|
||||
passwordEnv: PyroscopePasswordEnv,
|
||||
|
||||
mutexProfileFraction: 5,
|
||||
blockProfileRate: 5,
|
||||
|
||||
profiles: []pyroscope.ProfileType{
|
||||
pyroscope.ProfileCPU,
|
||||
pyroscope.ProfileInuseObjects,
|
||||
pyroscope.ProfileAllocObjects,
|
||||
pyroscope.ProfileInuseSpace,
|
||||
pyroscope.ProfileAllocSpace,
|
||||
pyroscope.ProfileGoroutines,
|
||||
pyroscope.ProfileMutexCount,
|
||||
pyroscope.ProfileMutexDuration,
|
||||
pyroscope.ProfileBlockCount,
|
||||
pyroscope.ProfileBlockDuration,
|
||||
},
|
||||
}
|
||||
|
||||
func valueOrEnv(value, env string) string {
|
||||
if value != "" {
|
||||
return value
|
||||
}
|
||||
return os.Getenv(env)
|
||||
}
|
||||
38
pprof/pprof.go
Normal file
38
pprof/pprof.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package pprof
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
|
||||
"github.com/grafana/pyroscope-go"
|
||||
|
||||
"go.linka.cloud/grpc-toolkit/logger"
|
||||
)
|
||||
|
||||
func Init(ctx context.Context, app string, opts ...Option) {
|
||||
if app == "" {
|
||||
panic("application name is required to start pyroscope profiler")
|
||||
}
|
||||
o := defaultOptions
|
||||
for _, v := range opts {
|
||||
v(&o)
|
||||
}
|
||||
if valueOrEnv(o.address, o.addressEnv) == "" {
|
||||
return
|
||||
}
|
||||
runtime.SetMutexProfileFraction(o.mutexProfileFraction)
|
||||
runtime.SetBlockProfileRate(o.blockProfileRate)
|
||||
log := logger.C(ctx).WithFields("service", "pyroscope")
|
||||
log.Info("starting pyroscope profiler")
|
||||
_, err := pyroscope.Start(pyroscope.Config{
|
||||
ApplicationName: app,
|
||||
ServerAddress: valueOrEnv(o.address, o.addressEnv),
|
||||
BasicAuthUser: valueOrEnv(o.user, o.userEnv),
|
||||
BasicAuthPassword: valueOrEnv(o.password, o.passwordEnv),
|
||||
Logger: log,
|
||||
ProfileTypes: o.profiles,
|
||||
})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("failed to start pyroscope")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user