Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/gitpod-cli/cmd/top.go
2498 views
1
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package cmd
6
7
import (
8
"context"
9
"encoding/json"
10
"fmt"
11
"os"
12
"time"
13
14
"github.com/gitpod-io/gitpod/gitpod-cli/pkg/supervisor"
15
"github.com/gitpod-io/gitpod/supervisor/api"
16
"golang.org/x/sync/errgroup"
17
18
"github.com/gitpod-io/gitpod/gitpod-cli/pkg/utils"
19
20
"github.com/spf13/cobra"
21
22
"github.com/olekukonko/tablewriter"
23
)
24
25
var topCmdOpts struct {
26
Json bool
27
}
28
29
type topData struct {
30
Resources *api.ResourcesStatusResponse `json:"resources"`
31
WorkspaceClass *api.WorkspaceInfoResponse_WorkspaceClass `json:"workspace_class"`
32
}
33
34
var topCmd = &cobra.Command{
35
Use: "top",
36
Short: "Display usage of workspace resources (CPU and memory)",
37
RunE: func(cmd *cobra.Command, args []string) error {
38
ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)
39
defer cancel()
40
41
client, err := supervisor.New(ctx)
42
if err != nil {
43
return err
44
}
45
defer client.Close()
46
47
data := &topData{}
48
49
g, ctx := errgroup.WithContext(ctx)
50
g.Go(func() error {
51
workspaceResources, err := client.Status.ResourcesStatus(ctx, &api.ResourcesStatuRequest{})
52
if err != nil {
53
return err
54
}
55
data.Resources = workspaceResources
56
return nil
57
})
58
59
g.Go(func() error {
60
wsInfo, err := client.Info.WorkspaceInfo(ctx, &api.WorkspaceInfoRequest{})
61
if err != nil {
62
return err
63
}
64
data.WorkspaceClass = wsInfo.WorkspaceClass
65
return nil
66
})
67
68
err = g.Wait()
69
if err != nil {
70
return err
71
}
72
73
if topCmdOpts.Json {
74
content, _ := json.Marshal(data)
75
fmt.Println(string(content))
76
return nil
77
}
78
outputTable(data.Resources, data.WorkspaceClass)
79
return nil
80
},
81
}
82
83
func formatWorkspaceClass(workspaceClass *api.WorkspaceInfoResponse_WorkspaceClass) string {
84
if workspaceClass == nil || workspaceClass.DisplayName == "" {
85
return ""
86
}
87
return fmt.Sprintf("%s: %s", workspaceClass.DisplayName, workspaceClass.Description)
88
}
89
90
func outputTable(workspaceResources *api.ResourcesStatusResponse, workspaceClass *api.WorkspaceInfoResponse_WorkspaceClass) {
91
table := tablewriter.NewWriter(os.Stdout)
92
table.SetBorder(false)
93
table.SetColWidth(50)
94
table.SetColumnSeparator(":")
95
96
cpuFraction := int64((float64(workspaceResources.Cpu.Used) / float64(workspaceResources.Cpu.Limit)) * 100)
97
memFraction := int64((float64(workspaceResources.Memory.Used) / float64(workspaceResources.Memory.Limit)) * 100)
98
cpu := fmt.Sprintf("%dm/%dm (%d%%)", workspaceResources.Cpu.Used, workspaceResources.Cpu.Limit, cpuFraction)
99
memory := fmt.Sprintf("%dMi/%dMi (%d%%)", workspaceResources.Memory.Used/(1024*1024), workspaceResources.Memory.Limit/(1024*1024), memFraction)
100
101
var cpuColors, memoryColors []tablewriter.Colors
102
if !noColor && utils.ColorsEnabled() {
103
cpuColors = []tablewriter.Colors{nil, {getColor(workspaceResources.Cpu.Severity)}}
104
memoryColors = []tablewriter.Colors{nil, {getColor(workspaceResources.Memory.Severity)}}
105
}
106
107
table.Append([]string{"Workspace class", formatWorkspaceClass(workspaceClass)})
108
table.Rich([]string{"CPU (millicores)", cpu}, cpuColors)
109
table.Rich([]string{"Memory (bytes)", memory}, memoryColors)
110
111
table.Render()
112
}
113
114
func getColor(severity api.ResourceStatusSeverity) int {
115
switch severity {
116
case api.ResourceStatusSeverity_danger:
117
return tablewriter.FgRedColor
118
case api.ResourceStatusSeverity_warning:
119
return tablewriter.FgYellowColor
120
default:
121
return tablewriter.FgHiGreenColor
122
}
123
}
124
125
func init() {
126
topCmd.Flags().BoolVarP(&noColor, "no-color", "", false, "Disable output colorization")
127
topCmd.Flags().BoolVarP(&topCmdOpts.Json, "json", "j", false, "Output in JSON format")
128
rootCmd.AddCommand(topCmd)
129
}
130
131