8
8
"io"
9
9
"net"
10
10
"net/http"
11
+ "os"
11
12
"strconv"
13
+ "strings"
12
14
"time"
13
15
14
16
"github.com/google/uuid"
@@ -17,6 +19,7 @@ import (
17
19
"golang.org/x/xerrors"
18
20
"inet.af/netaddr"
19
21
"nhooyr.io/websocket"
22
+ "nhooyr.io/websocket/wsjson"
20
23
"tailscale.com/types/key"
21
24
22
25
"cdr.dev/slog"
@@ -152,6 +155,80 @@ func (api *API) workspaceAgentMetadata(rw http.ResponseWriter, r *http.Request)
152
155
})
153
156
}
154
157
158
+ var inTest = strings .HasSuffix (os .Args [0 ], ".test" )
159
+
160
+ func (api * API ) workspaceAgentReportStats (rw http.ResponseWriter , r * http.Request ) {
161
+ api .websocketWaitMutex .Lock ()
162
+ api .websocketWaitGroup .Add (1 )
163
+ api .websocketWaitMutex .Unlock ()
164
+ defer api .websocketWaitGroup .Done ()
165
+
166
+ workspaceAgent := httpmw .WorkspaceAgent (r )
167
+ workspace , err := api .Database .GetWorkspaceResourceByID (r .Context (), workspaceAgent .ResourceID )
168
+ if err != nil {
169
+ httpapi .Write (rw , http .StatusBadRequest , codersdk.Response {
170
+ Message : "Failed to accept websocket." ,
171
+ Detail : err .Error (),
172
+ })
173
+ return
174
+ }
175
+
176
+ conn , err := websocket .Accept (rw , r , & websocket.AcceptOptions {
177
+ CompressionMode : websocket .CompressionDisabled ,
178
+ })
179
+ if err != nil {
180
+ httpapi .Write (rw , http .StatusBadRequest , codersdk.Response {
181
+ Message : "Failed to accept websocket." ,
182
+ Detail : err .Error (),
183
+ })
184
+ return
185
+ }
186
+ defer conn .Close (websocket .StatusAbnormalClosure , "" )
187
+
188
+ var interval = time .Minute
189
+ if inTest {
190
+ interval = 100 * time .Millisecond
191
+ }
192
+
193
+ ctx := r .Context ()
194
+ timer := time .NewTimer (interval )
195
+ for {
196
+ err := wsjson .Write (ctx , conn , codersdk.AgentStatsReportRequest {})
197
+ if err != nil {
198
+ httpapi .Write (rw , http .StatusBadRequest , codersdk.Response {
199
+ Message : "Failed to write report request." ,
200
+ Detail : err .Error (),
201
+ })
202
+ return
203
+ }
204
+ var rep codersdk.AgentStatsReportResponse
205
+
206
+ err = wsjson .Read (ctx , conn , & rep )
207
+ if err != nil {
208
+ httpapi .Write (rw , http .StatusBadRequest , codersdk.Response {
209
+ Message : "Failed to read report response." ,
210
+ Detail : err .Error (),
211
+ })
212
+ return
213
+ }
214
+
215
+ api .Logger .Debug (ctx , "read stats report" ,
216
+ slog .F ("agent" , workspaceAgent .ID ),
217
+ slog .F ("workspace" , workspace .ID ),
218
+ slog .F ("report" , rep ),
219
+ )
220
+
221
+ select {
222
+ case <- timer .C :
223
+ continue
224
+ case <- ctx .Done ():
225
+ conn .Close (websocket .StatusNormalClosure , "" )
226
+ return
227
+ }
228
+ }
229
+
230
+ }
231
+
155
232
func (api * API ) workspaceAgentListen (rw http.ResponseWriter , r * http.Request ) {
156
233
api .websocketWaitMutex .Lock ()
157
234
api .websocketWaitGroup .Add (1 )
0 commit comments