Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ COPY main.go main.go
COPY api/ api/
COPY controllers/ controllers/
COPY internal/ internal/
COPY pkg/ pkg/

# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -tags timetzdata -o manager main.go
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ kubebuilder-assets: $(KUBEBUILDER_ASSETS)

.PHONY: unit-tests
unit-tests: install-tools $(KUBEBUILDER_ASSETS) generate fmt vet manifests ## Run unit tests
ginkgo -r --randomize-all api/ internal/
ginkgo -r --randomize-all api/ internal/ pkg/

.PHONY: integration-tests
integration-tests: install-tools $(KUBEBUILDER_ASSETS) generate fmt vet manifests ## Run integration tests
Expand Down
12 changes: 12 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package main
import (
"flag"
"fmt"
"github.com/rabbitmq/cluster-operator/pkg/profiling"
"os"
"strconv"
"time"
Expand Down Expand Up @@ -113,6 +114,17 @@ func main() {
os.Exit(1)
}

if enableDebugPprof, ok := os.LookupEnv("ENABLE_DEBUG_PPROF"); ok {
pprofEnabled, err := strconv.ParseBool(enableDebugPprof)
if err == nil && pprofEnabled {
mgr, err = profiling.AddDebugPprofEndpoints(mgr)
if err != nil {
log.Error(err, "unable to add debug endpoints to manager")
os.Exit(1)
}
}
}

clusterConfig := config.GetConfigOrDie()

err = (&controllers.RabbitmqClusterReconciler{
Expand Down
28 changes: 28 additions & 0 deletions pkg/profiling/pprof.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package profiling

import (
"net/http"
"net/http/pprof"
ctrl "sigs.k8s.io/controller-runtime"
)

func AddDebugPprofEndpoints(mgr ctrl.Manager) (ctrl.Manager, error) {
pprofEndpoints := map[string]http.HandlerFunc{
"/debug/pprof": http.HandlerFunc(pprof.Index),
"/debug/pprof/heap": http.HandlerFunc(pprof.Index),
"/debug/pprof/mutex": http.HandlerFunc(pprof.Index),
"/debug/pprof/block": http.HandlerFunc(pprof.Index),
"/debug/pprof/goroutine": http.HandlerFunc(pprof.Index),
"/debug/pprof/cmdline": http.HandlerFunc(pprof.Cmdline),
"/debug/pprof/profile": http.HandlerFunc(pprof.Profile),
"/debug/pprof/symbol": http.HandlerFunc(pprof.Symbol),
"/debug/pprof/trace": http.HandlerFunc(pprof.Trace),
}
for path, handler := range pprofEndpoints {
err := mgr.AddMetricsExtraHandler(path, handler)
if err != nil {
return mgr, err
}
}
return mgr, nil
}
53 changes: 53 additions & 0 deletions pkg/profiling/pprof_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package profiling_test

import (
"context"
"fmt"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/rabbitmq/cluster-operator/pkg/profiling"
"io"
"net/http"
ctrl "sigs.k8s.io/controller-runtime"
)

var _ = Describe("Pprof", func() {

var (
opts ctrl.Options
mgr ctrl.Manager
err error
metricsEndpoint string
)

BeforeEach(func() {
metricsEndpoint, err = getFreePort()
opts = ctrl.Options{
MetricsBindAddress: metricsEndpoint,
}
mgr, err = ctrl.NewManager(cfg, opts)
Expect(err).NotTo(HaveOccurred())
mgr, err = profiling.AddDebugPprofEndpoints(mgr)
Expect(err).NotTo(HaveOccurred())

})

It("should serve extra endpoints", func() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
defer GinkgoRecover()
Expect(mgr.Start(ctx)).NotTo(HaveOccurred())
}()
<-mgr.Elected()
endpoint := fmt.Sprintf("http://%s/debug/pprof", metricsEndpoint)
resp, err := http.Get(endpoint)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
Expect(resp.StatusCode).To(Equal(http.StatusOK))

body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(string(body)).NotTo(BeEmpty())
})
})
48 changes: 48 additions & 0 deletions pkg/profiling/profiling_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package profiling_test

import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"net"
"sigs.k8s.io/controller-runtime/pkg/envtest"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var testenv *envtest.Environment
var cfg *rest.Config
var clientset *kubernetes.Clientset

func TestProfiling(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Profiling Suite")
}

var _ = BeforeSuite(func() {
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))

testenv = &envtest.Environment{}

var err error
cfg, err = testenv.Start()
Expect(err).NotTo(HaveOccurred())

})

func getFreePort() (string, error) {
addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0")
if err != nil {
return "", err
}

l, err := net.ListenTCP("tcp", addr)
if err != nil {
return "", err
}
defer l.Close()
return l.Addr().String(), nil
}