@@ -6,168 +6,38 @@ package supervisor
6
6
7
7
import (
8
8
"context"
9
- "io/ioutil"
10
- "strconv"
11
- "strings"
12
- "time"
13
9
14
10
"golang.org/x/xerrors"
15
11
16
- linuxproc "github.com/c9s/goprocinfo/linux"
17
12
"github.com/gitpod-io/gitpod/supervisor/api"
13
+ daemonapi "github.com/gitpod-io/gitpod/ws-daemon/api"
14
+ "google.golang.org/grpc"
15
+ "google.golang.org/grpc/credentials/insecure"
18
16
)
19
17
20
18
// Top provides workspace resources status information.
21
19
func Top (ctx context.Context ) (* api.ResourcesStatusResponse , error ) {
22
- memory , err := resolveMemoryStatus ()
23
- if err != nil {
24
- return nil , err
25
- }
26
- cpu , err := resolveCPUStatus ()
27
- if err != nil {
28
- return nil , err
29
- }
30
- return & api.ResourcesStatusResponse {
31
- Memory : memory ,
32
- Cpu : cpu ,
33
- }, nil
34
- }
35
-
36
- func resolveMemoryStatus () (* api.ResourceStatus , error ) {
37
- content , err := ioutil .ReadFile ("/sys/fs/cgroup/memory/memory.limit_in_bytes" )
38
- if err != nil {
39
- return nil , xerrors .Errorf ("failed to read memory.limit_in_bytes: %w" , err )
40
- }
41
- limit , err := strconv .Atoi (strings .TrimSpace (string (content )))
42
- if err != nil {
43
- return nil , xerrors .Errorf ("failed to parse memory.limit_in_bytes: %w" , err )
44
- }
45
- memInfo , err := linuxproc .ReadMemInfo ("/proc/meminfo" )
46
- if err != nil {
47
- return nil , xerrors .Errorf ("failed to read meminfo: %w" , err )
48
- }
49
- memTotal := int (memInfo .MemTotal ) * 1024
50
- if limit > memTotal && memTotal > 0 {
51
- limit = memTotal
52
- }
20
+ const socketFN = "/.supervisor/info.sock"
53
21
54
- content , err = ioutil .ReadFile ("/sys/fs/cgroup/memory/memory.usage_in_bytes" )
55
- if err != nil {
56
- return nil , xerrors .Errorf ("failed to read memory.usage_in_bytes: %w" , err )
57
- }
58
- used , err := strconv .Atoi (strings .TrimSpace (string (content )))
22
+ conn , err := grpc .DialContext (ctx , "unix://" + socketFN , grpc .WithTransportCredentials (insecure .NewCredentials ()))
59
23
if err != nil {
60
- return nil , xerrors .Errorf ("failed to parse memory.usage_in_bytes : %w" , err )
24
+ return nil , xerrors .Errorf ("could not dial context : %w" , err )
61
25
}
62
26
63
- content , err = ioutil .ReadFile ("/sys/fs/cgroup/memory/memory.stat" )
27
+ client := daemonapi .NewWorkspaceInfoServiceClient (conn )
28
+ resp , err := client .WorkspaceInfo (ctx , & daemonapi.WorkspaceInfoRequest {})
64
29
if err != nil {
65
- return nil , xerrors .Errorf ("failed to read memory.stat : %w" , err )
30
+ return nil , xerrors .Errorf ("could not retrieve workspace info : %w" , err )
66
31
}
67
- statLines := strings .Split (strings .TrimSpace (string (content )), "\n " )
68
- stat := make (map [string ]string , len (statLines ))
69
- for _ , line := range statLines {
70
- tokens := strings .Split (line , " " )
71
- stat [tokens [0 ]] = tokens [1 ]
72
- }
73
- // substract evictable memory
74
- value , ok := stat ["total_inactive_file" ]
75
- if ok {
76
- totalInactiveFile , err := strconv .Atoi (value )
77
- if err != nil {
78
- return nil , xerrors .Errorf ("failed to parse total_inactive_file: %w" , err )
79
- }
80
- if used < totalInactiveFile {
81
- used = 0
82
- } else {
83
- used -= totalInactiveFile
84
- }
85
- }
86
- return & api.ResourceStatus {
87
- Limit : int64 (limit ),
88
- Used : int64 (used ),
89
- }, nil
90
- }
91
-
92
- func resolveCPUStatus () (* api.ResourceStatus , error ) {
93
- t , err := resolveCPUStat ()
94
- if err != nil {
95
- return nil , err
96
- }
97
-
98
- time .Sleep (time .Second )
99
32
100
- t2 , err := resolveCPUStat ()
101
- if err != nil {
102
- return nil , err
103
- }
104
-
105
- cpuUsage := t2 .usage - t .usage
106
- totalTime := t2 .uptime - t .uptime
107
- used := cpuUsage / totalTime * 1000
108
-
109
- content , err := ioutil .ReadFile ("/sys/fs/cgroup/cpu/cpu.cfs_quota_us" )
110
- if err != nil {
111
- return nil , xerrors .Errorf ("failed to read cpu.cfs_quota_us: %w" , err )
112
- }
113
- quota , err := strconv .Atoi (strings .TrimSpace (string (content )))
114
- if err != nil {
115
- return nil , xerrors .Errorf ("failed to parse cpu.cfs_quota_us: %w" , err )
116
- }
117
-
118
- var limit int
119
- if quota > 0 {
120
- content , err = ioutil .ReadFile ("/sys/fs/cgroup/cpu/cpu.cfs_period_us" )
121
- if err != nil {
122
- return nil , xerrors .Errorf ("failed to read cpu.cfs_period_us: %w" , err )
123
- }
124
- period , err := strconv .Atoi (strings .TrimSpace (string (content )))
125
- if err != nil {
126
- return nil , xerrors .Errorf ("failed to parse cpu.cfs_period_us: %w" , err )
127
- }
128
-
129
- limit = quota / period * 1000
130
- } else {
131
- content , err = ioutil .ReadFile ("/sys/fs/cgroup/cpu/cpuacct.usage_percpu" )
132
- if err != nil {
133
- return nil , xerrors .Errorf ("failed to read cpuacct.usage_percpu: %w" , err )
134
- }
135
- limit = len (strings .Split (strings .TrimSpace (string (content )), " " )) * 1000
136
- }
137
-
138
- return & api.ResourceStatus {
139
- Limit : int64 (limit ),
140
- Used : int64 (used ),
141
- }, nil
142
- }
143
-
144
- type cpuStat struct {
145
- usage float64
146
- uptime float64
147
- }
148
-
149
- func resolveCPUStat () (* cpuStat , error ) {
150
- content , err := ioutil .ReadFile ("/sys/fs/cgroup/cpu/cpuacct.usage" )
151
- if err != nil {
152
- return nil , xerrors .Errorf ("failed to read cpuacct.usage: %w" , err )
153
- }
154
- usage , err := strconv .ParseFloat (strings .TrimSpace (string (content )), 64 )
155
- if err != nil {
156
- return nil , xerrors .Errorf ("failed to parse cpuacct.usage: %w" , err )
157
- }
158
- // convert from nanoseconds to seconds
159
- usage *= 1e-9
160
- content , err = ioutil .ReadFile ("/proc/uptime" )
161
- if err != nil {
162
- return nil , xerrors .Errorf ("failed to read uptime: %w" , err )
163
- }
164
- values := strings .Split (strings .TrimSpace (string (content )), " " )
165
- uptime , err := strconv .ParseFloat (values [0 ], 64 )
166
- if err != nil {
167
- return nil , xerrors .Errorf ("failed to parse uptime: %w" , err )
168
- }
169
- return & cpuStat {
170
- usage : usage ,
171
- uptime : uptime ,
33
+ return & api.ResourcesStatusResponse {
34
+ Memory : & api.ResourceStatus {
35
+ Limit : resp .Resources .Memory .Limit ,
36
+ Used : resp .Resources .Memory .Used ,
37
+ },
38
+ Cpu : & api.ResourceStatus {
39
+ Limit : resp .Resources .Cpu .Limit ,
40
+ Used : resp .Resources .Cpu .Used ,
41
+ },
172
42
}, nil
173
43
}
0 commit comments