Skip to content

Commit

Permalink
add pyroscope profiler support
Browse files Browse the repository at this point in the history
  • Loading branch information
floreks committed Jan 15, 2025
1 parent d4383d8 commit 0a389eb
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 7 deletions.
12 changes: 12 additions & 0 deletions cmd/agent/args/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ const (

defaultProfilerPath = "/debug/pprof/"
defaultProfilerAddress = ":7777"

defaultPyroscopeAddress = "http://pyroscope.monitoring.svc.cluster.local:4040"
)

var (
Expand All @@ -56,6 +58,7 @@ var (
argEnableLeaderElection = flag.Bool("leader-elect", false, "Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
argLocal = flag.Bool("local", false, "Whether you're running the operator locally.")
argProfiler = flag.Bool("profiler", false, "Enable pprof handler. By default it will be exposed on localhost:7777 under '/debug/pprof'")
argPyroscope = flag.Bool("pyroscope", true, "Enable pyroscope integration for detailed application profiling. By default it will push to http://pyroscope.monitoring.svc.cluster.local:4040")
argDisableResourceCache = flag.Bool("disable-resource-cache", false, "Control whether resource cache should be enabled or not.")
argEnableKubecostProxy = flag.Bool("enable-kubecost-proxy", false, "If set, will proxy a Kubecost API request through the K8s API server.")

Expand All @@ -77,6 +80,7 @@ var (
argControllerCacheTTL = flag.String("controller-cache-ttl", defaultControllerCacheTTL, "The time to live of console controller cache entries.")
argRestoreNamespace = flag.String("restore-namespace", defaultRestoreNamespace, "The namespace where Velero restores are located.")
argServices = flag.String("services", "", "A comma separated list of service ids to reconcile. Leave empty to reconcile all.")
argPyroscopeAddress = flag.String("pyroscope-address", defaultPyroscopeAddress, "The address of the Pyroscope server.")

serviceSet containers.Set[string]
)
Expand Down Expand Up @@ -268,6 +272,14 @@ func ResourceCacheEnabled() bool {
return !(*argDisableResourceCache)
}

func PyroscopeEnabled() bool {
return *argPyroscope
}

func PyroscopeAddress() string {
return *argPyroscopeAddress
}

func ensureOrDie(argName string, arg *string) {
if arg == nil || len(*arg) == 0 {
pflag.PrintDefaults()
Expand Down
49 changes: 49 additions & 0 deletions cmd/agent/args/pyroscope.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package args

import (
"os"
"runtime"

"github.com/grafana/pyroscope-go"

"k8s.io/klog/v2"
)

func InitPyroscope() (*pyroscope.Profiler, error) {
klog.Info("initializing pyroscope")

runtime.SetMutexProfileFraction(5)
runtime.SetBlockProfileRate(5)

return pyroscope.Start(pyroscope.Config{
ApplicationName: "deployment-operator",

// replace this with the address of pyroscope server
ServerAddress: PyroscopeAddress(),

// you can disable logging by setting this to nil
Logger: pyroscope.StandardLogger,

// optionally, if authentication is enabled, specify the API key:
// AuthToken: os.Getenv("PYROSCOPE_AUTH_TOKEN"),

// you can provide static tags via a map:
Tags: map[string]string{"hostname": os.Getenv("HOSTNAME")},

ProfileTypes: []pyroscope.ProfileType{
// these profile types are enabled by default:
pyroscope.ProfileCPU,
pyroscope.ProfileAllocObjects,
pyroscope.ProfileAllocSpace,
pyroscope.ProfileInuseObjects,
pyroscope.ProfileInuseSpace,

// these profile types are optional:
pyroscope.ProfileGoroutines,
pyroscope.ProfileMutexCount,
pyroscope.ProfileMutexDuration,
pyroscope.ProfileBlockCount,
pyroscope.ProfileBlockDuration,
},
})
}
23 changes: 17 additions & 6 deletions cmd/agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@ import (
certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
templatesv1 "github.com/open-policy-agent/frameworks/constraint/pkg/apis/templates/v1"
constraintstatusv1beta1 "github.com/open-policy-agent/gatekeeper/v3/apis/status/v1beta1"
deploymentsv1alpha1 "github.com/pluralsh/deployment-operator/api/v1alpha1"
"github.com/pluralsh/deployment-operator/cmd/agent/args"
"github.com/pluralsh/deployment-operator/pkg/cache"
"github.com/pluralsh/deployment-operator/pkg/client"
consolectrl "github.com/pluralsh/deployment-operator/pkg/controller"
"github.com/pluralsh/deployment-operator/pkg/scraper"
velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand All @@ -25,6 +19,13 @@ import (
"k8s.io/client-go/rest"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"

deploymentsv1alpha1 "github.com/pluralsh/deployment-operator/api/v1alpha1"
"github.com/pluralsh/deployment-operator/cmd/agent/args"
"github.com/pluralsh/deployment-operator/pkg/cache"
"github.com/pluralsh/deployment-operator/pkg/client"
consolectrl "github.com/pluralsh/deployment-operator/pkg/controller"
"github.com/pluralsh/deployment-operator/pkg/scraper"
)

var (
Expand Down Expand Up @@ -54,6 +55,16 @@ func main() {
config := ctrl.GetConfigOrDie()
ctx := ctrl.LoggerInto(ctrl.SetupSignalHandler(), setupLog)

if args.PyroscopeEnabled() {
profiler, err := args.InitPyroscope()
if err != nil {
setupLog.Error(err, "unable to initialize pyroscope")
os.Exit(1)
}

defer profiler.Stop()
}

extConsoleClient := client.New(args.ConsoleUrl(), args.DeployToken())
discoveryClient := initDiscoveryClientOrDie(config)
kubeManager := initKubeManagerOrDie(config)
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ require (
github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
github.com/gostaticanalysis/nilerr v0.1.1 // indirect
github.com/gosuri/uitable v0.0.4 // indirect
github.com/grafana/pyroscope-go v1.2.0 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,10 @@ github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoIS
github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU=
github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY=
github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=
github.com/grafana/pyroscope-go v1.2.0 h1:aILLKjTj8CS8f/24OPMGPewQSYlhmdQMBmol1d3KGj8=
github.com/grafana/pyroscope-go v1.2.0/go.mod h1:2GHr28Nr05bg2pElS+dDsc98f3JTUh2f6Fz1hWXrqwk=
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg=
github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
Expand Down
2 changes: 1 addition & 1 deletion internal/kubernetes/watcher/retry_lister_watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (in *RetryListerWatcher) listAndWatch() error {
}

resourceVersion := listMetaInterface.GetResourceVersion()
items, err := meta.ExtractListWithAlloc(list)
items, err := meta.ExtractList(list)
if err != nil {
return fmt.Errorf("unable to understand list result %#v (%w)", list, err)
}
Expand Down

0 comments on commit 0a389eb

Please sign in to comment.