Skip to content

Commit

Permalink
Add split flag to show pods separately
Browse files Browse the repository at this point in the history
Signed-off-by: Piotr Zaniewski <piotr@upbound.io>
  • Loading branch information
Piotr1215 committed Jan 18, 2024
1 parent 9ef5e34 commit c865430
Showing 1 changed file with 95 additions and 56 deletions.
151 changes: 95 additions & 56 deletions cmd/crank/beta/top/top.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,14 @@ const (
)

// Cmd represents the top command.
type Cmd struct{}
type Cmd struct {
Split bool `short:"s" name:"split" help:"Show each category separately."`
}

// Help returns help instructions for the top command.
func (c *Cmd) Help() string {
return `Usage: crossplane top`
}

type topMetrics struct {
PodType string
Expand All @@ -58,10 +65,14 @@ type topMetrics struct {
MemoryUsage string
}

// Help returns help instructions for the top command.
func (c *Cmd) Help() string {
return `Usage: crossplane top`
type defaultPrinterRow struct {
podType string
namespace string
name string
cpu string
memory string
}

func (r *defaultPrinterRow) String() string {
return strings.Join([]string{
r.podType,
Expand All @@ -72,30 +83,12 @@ func (r *defaultPrinterRow) String() string {
}, "\t") + "\t"
}

type defaultPrinterRow struct {
podType string
namespace string
name string
cpu string
memory string
}

// Run runs the top command.
func (c *Cmd) Run(k *kong.Context, logger logging.Logger) error {
func (c *Cmd) Run(k *kong.Context, logger logging.Logger) error { //nolint:gocyclo // TODO:(piotr1215) refactor to use dedicated functions
logger = logger.WithValues("cmd", "top")

var w = k.Stdout
tw := printers.GetNewTabWriter(w)
headers := defaultPrinterRow{
podType: "TYPE",
namespace: "NAMESPACE",
name: "NAME",
cpu: "CPU(cores)",
memory: "MEMORY(bytes)",
}
if _, err := fmt.Fprintln(tw, headers.String()); err != nil {
return errors.Wrap(err, errWriteHeader)
}
logger.Debug("Tabwriter header created")

// Build the config from the kubeconfig path
Expand Down Expand Up @@ -128,22 +121,51 @@ func (c *Cmd) Run(k *kong.Context, logger logging.Logger) error {
crossplanePods := getCrossplanePods(pods.Items)
logger.Debug("Fetched all pods from all namespaces and filtered out Crossplane", "pods", crossplanePods)

_, err = addPodMetrics(crossplanePods, metricsClientset)
for i, pod := range crossplanePods {
podMetrics, err := metricsClientset.MetricsV1beta1().PodMetricses(pod.PodNamespace).Get(ctx, pod.PodName, metav1.GetOptions{})
if err != nil {
return errors.Wrap(err, errAddingPodMetrics)
}
var totalCPUUsage, totalMemoryUsage int64
for _, container := range podMetrics.Containers {
totalCPUUsage += container.Usage.Cpu().ScaledValue(resource.Milli)
totalMemoryUsage += container.Usage.Memory().ScaledValue(resource.Mega)
}

crossplanePods[i].CPUUsage = totalCPUUsage
crossplanePods[i].MemoryUsage = fmt.Sprintf("%dMi", totalMemoryUsage)
}
logger.Debug("Metrics added to Crossplane pods")

if err != nil {
return errors.Wrap(err, errGetPodMetrics)
}
logger.Debug("Added metrics to Crossplane pods")

for _, pod := range crossplanePods {
row := defaultPrinterRow{
podType: pod.PodType,
namespace: pod.PodNamespace,
name: pod.PodName,
cpu: fmt.Sprintf("%d", pod.CPUUsage),
memory: pod.MemoryUsage,
if c.Split {
printPodsByCategory(crossplanePods)
} else {
headers := defaultPrinterRow{
podType: "TYPE",
namespace: "NAMESPACE",
name: "NAME",
cpu: "CPU(cores)",
memory: "MEMORY(bytes)",
}
if _, err := fmt.Fprintln(tw, row.String()); err != nil {
return errors.Wrap(err, errWriteRow)
if _, err := fmt.Fprintln(tw, headers.String()); err != nil {
return errors.Wrap(err, errWriteHeader)
}

for _, pod := range crossplanePods {
row := defaultPrinterRow{
podType: pod.PodType,
namespace: pod.PodNamespace,
name: pod.PodName,
cpu: fmt.Sprintf("%d", pod.CPUUsage),
memory: pod.MemoryUsage,
}
if _, err := fmt.Fprintln(tw, row.String()); err != nil {
return errors.Wrap(err, errWriteRow)
}
}
}

Expand All @@ -152,7 +174,46 @@ func (c *Cmd) Run(k *kong.Context, logger logging.Logger) error {
}
return nil
}
func printPodsByCategory(pods []topMetrics) {
categorySummaries := make(map[string]struct {
Count int
TotalCPU int64
TotalMemory string
})

for _, pod := range pods {
summary := categorySummaries[pod.PodType]
summary.Count++
summary.TotalCPU += pod.CPUUsage

// Inline memory aggregation logic
if summary.TotalMemory == "" {
summary.TotalMemory = pod.MemoryUsage
} else {
// Concatenate for simplicity; replace with actual aggregation logic
summary.TotalMemory += "+" + pod.MemoryUsage
}

categorySummaries[pod.PodType] = summary
}

for category := range categorySummaries {
fmt.Printf("\n== %s Pods: ==\n\n", capitalizeFirst(category))
for _, pod := range pods {
if pod.PodType == category {
fmt.Printf("namespace: %s\nname: %s\ncpu: %d\nmemory: %s\n\n",
pod.PodNamespace, pod.PodName, pod.CPUUsage, pod.MemoryUsage)
}
}
}

}
func capitalizeFirst(s string) string {
if s == "" {
return ""
}
return strings.ToUpper(s[:1]) + s[1:]
}
func getCrossplanePods(pods []v1.Pod) []topMetrics {
metricsList := make([]topMetrics, 0)
for _, pod := range pods {
Expand Down Expand Up @@ -189,25 +250,3 @@ func getCrossplanePods(pods []v1.Pod) []topMetrics {
}
return metricsList
}

func addPodMetrics(metricsList []topMetrics, metricsClientset *versioned.Clientset) ([]topMetrics, error) {
for i, metric := range metricsList {
// TODO:(piotr1215) move this to the calling function
// TODO:(piotr1215) use the same context as the calling function
podMetrics, err := metricsClientset.MetricsV1beta1().PodMetricses(metric.PodNamespace).Get(context.TODO(), metric.PodName, metav1.GetOptions{})
if err != nil {
return nil, errors.Wrap(err, errAddingPodMetrics)
}

var totalCPUUsage int64
var totalMemoryUsage int64
for _, container := range podMetrics.Containers {
totalCPUUsage += container.Usage.Cpu().ScaledValue(resource.Milli)
totalMemoryUsage += container.Usage.Memory().ScaledValue(resource.Mega)
}

metricsList[i].CPUUsage = totalCPUUsage
metricsList[i].MemoryUsage = fmt.Sprintf("%dMi", totalMemoryUsage)
}
return metricsList, nil
}

0 comments on commit c865430

Please sign in to comment.