kubeshark/cmd/pprofRunner.go
M. Mert Yildiran 1c883c73e4
Add hub to the list of containers in pprof command and add flags to pprof command (#1603)
* Add hub to the list of containers in `pprof` command and add flags to `pprof` command

* Reduce duplication

---------

Co-authored-by: Alon Girmonsky <1990761+alongir@users.noreply.github.com>
2024-09-09 14:41:01 -07:00

177 lines
4.5 KiB
Go

package cmd
import (
"context"
"fmt"
"github.com/go-cmd/cmd"
"github.com/kubeshark/kubeshark/config"
"github.com/kubeshark/kubeshark/kubernetes"
"github.com/kubeshark/kubeshark/utils"
"github.com/rivo/tview"
"github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1"
)
func runPprof() {
runProxy(false, true)
provider, err := getKubernetesProviderForCli(false, false)
if err != nil {
return
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
hubPods, err := provider.ListPodsByAppLabel(ctx, config.Config.Tap.Release.Namespace, map[string]string{kubernetes.AppLabelKey: "hub"})
if err != nil {
log.Error().
Err(err).
Msg("Failed to list hub pods!")
cancel()
return
}
workerPods, err := provider.ListPodsByAppLabel(ctx, config.Config.Tap.Release.Namespace, map[string]string{kubernetes.AppLabelKey: "worker"})
if err != nil {
log.Error().
Err(err).
Msg("Failed to list worker pods!")
cancel()
return
}
fullscreen := true
app := tview.NewApplication()
list := tview.NewList()
var currentCmd *cmd.Cmd
i := 48
for _, pod := range hubPods {
for _, container := range pod.Spec.Containers {
log.Info().Str("pod", pod.Name).Str("container", container.Name).Send()
homeUrl := fmt.Sprintf("%s/debug/pprof/", kubernetes.GetHubUrl())
modal := buildNewModal(
pod,
container,
homeUrl,
app,
list,
fullscreen,
currentCmd,
)
list.AddItem(fmt.Sprintf("pod: %s container: %s", pod.Name, container.Name), pod.Spec.NodeName, rune(i), func() {
app.SetRoot(modal, fullscreen)
})
i++
}
}
for _, pod := range workerPods {
for _, container := range pod.Spec.Containers {
log.Info().Str("pod", pod.Name).Str("container", container.Name).Send()
homeUrl := fmt.Sprintf("%s/pprof/%s/%s/", kubernetes.GetHubUrl(), pod.Status.HostIP, container.Name)
modal := buildNewModal(
pod,
container,
homeUrl,
app,
list,
fullscreen,
currentCmd,
)
list.AddItem(fmt.Sprintf("pod: %s container: %s", pod.Name, container.Name), pod.Spec.NodeName, rune(i), func() {
app.SetRoot(modal, fullscreen)
})
i++
}
}
list.AddItem("Quit", "Press to exit", 'q', func() {
if currentCmd != nil {
err = currentCmd.Stop()
if err != nil {
log.Error().Err(err).Str("name", currentCmd.Name).Msg("Failed to stop process!")
}
}
app.Stop()
})
if err := app.SetRoot(list, fullscreen).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
func buildNewModal(
pod v1.Pod,
container v1.Container,
homeUrl string,
app *tview.Application,
list *tview.List,
fullscreen bool,
currentCmd *cmd.Cmd,
) *tview.Modal {
return tview.NewModal().
SetText(fmt.Sprintf("pod: %s container: %s", pod.Name, container.Name)).
AddButtons([]string{
"Open Debug Home Page",
"Profile: CPU",
"Profile: Memory",
"Profile: Goroutine",
"Cancel",
}).
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
var err error
port := fmt.Sprintf(":%d", config.Config.Tap.Pprof.Port)
view := fmt.Sprintf("http://localhost%s/ui/%s", port, config.Config.Tap.Pprof.View)
switch buttonLabel {
case "Open Debug Home Page":
utils.OpenBrowser(homeUrl)
case "Profile: CPU":
if currentCmd != nil {
err = currentCmd.Stop()
if err != nil {
log.Error().Err(err).Str("name", currentCmd.Name).Msg("Failed to stop process!")
}
}
currentCmd = cmd.NewCmd("go", "tool", "pprof", "-http", port, "-no_browser", fmt.Sprintf("%sprofile", homeUrl))
currentCmd.Start()
utils.OpenBrowser(view)
case "Profile: Memory":
if currentCmd != nil {
err = currentCmd.Stop()
if err != nil {
log.Error().Err(err).Str("name", currentCmd.Name).Msg("Failed to stop process!")
}
}
currentCmd = cmd.NewCmd("go", "tool", "pprof", "-http", port, "-no_browser", fmt.Sprintf("%sheap", homeUrl))
currentCmd.Start()
utils.OpenBrowser(view)
case "Profile: Goroutine":
if currentCmd != nil {
err = currentCmd.Stop()
if err != nil {
log.Error().Err(err).Str("name", currentCmd.Name).Msg("Failed to stop process!")
}
}
currentCmd = cmd.NewCmd("go", "tool", "pprof", "-http", port, "-no_browser", fmt.Sprintf("%sgoroutine", homeUrl))
currentCmd.Start()
utils.OpenBrowser(view)
case "Cancel":
if currentCmd != nil {
err = currentCmd.Stop()
if err != nil {
log.Error().Err(err).Str("name", currentCmd.Name).Msg("Failed to stop process!")
}
}
fallthrough
default:
app.SetRoot(list, fullscreen)
}
})
}