mirror of
https://github.com/linka-cloud/grpc.git
synced 2026-01-09 19:44:04 +00:00
feat(pprof): add pyroscope profiler support
Signed-off-by: Adphi <philippe.adrien.nousse@gmail.com>
This commit is contained in:
2
go.mod
2
go.mod
@@ -15,6 +15,7 @@ require (
|
||||
github.com/go-logr/logr v1.4.2
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/grafana/pyroscope-go v1.2.7
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3
|
||||
@@ -77,6 +78,7 @@ require (
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/gobwas/ws v1.1.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
github.com/iancoleman/strcase v0.3.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
|
||||
6
go.sum
6
go.sum
@@ -272,6 +272,10 @@ github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grafana/pyroscope-go v1.2.7 h1:VWBBlqxjyR0Cwk2W6UrE8CdcdD80GOFNutj0Kb1T8ac=
|
||||
github.com/grafana/pyroscope-go v1.2.7/go.mod h1:o/bpSLiJYYP6HQtvcoVKiE9s5RiNgjYTj1DhiddP2Pc=
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og=
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
|
||||
@@ -492,6 +496,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
|
||||
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