Skip to content

Commit adb06ea

Browse files
committed
Improve bulk log performance
1 parent 54c30be commit adb06ea

File tree

3 files changed

+42
-40
lines changed

3 files changed

+42
-40
lines changed

coderd/workspaceagents.go

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,6 @@ func (api *API) patchWorkspaceAgentStartupLogs(rw http.ResponseWriter, r *http.R
274274
CreatedAfter: lowestID - 1,
275275
})
276276
if err != nil {
277-
278277
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
279278
Message: "Failed to marshal startup logs notify message",
280279
Detail: err.Error(),
@@ -374,32 +373,28 @@ func (api *API) workspaceAgentStartupLogs(rw http.ResponseWriter, r *http.Reques
374373
ctx, wsNetConn := websocketNetConn(ctx, conn, websocket.MessageText)
375374
defer wsNetConn.Close() // Also closes conn.
376375

377-
logIdsDone := make(map[int64]bool)
378-
379376
// The Go stdlib JSON encoder appends a newline character after message write.
380377
encoder := json.NewEncoder(wsNetConn)
381-
for _, provisionerJobLog := range logs {
382-
logIdsDone[provisionerJobLog.ID] = true
383-
err = encoder.Encode(convertWorkspaceAgentStartupLog(provisionerJobLog))
384-
if err != nil {
385-
return
386-
}
378+
err = encoder.Encode(convertWorkspaceAgentStartupLogs(logs))
379+
if err != nil {
380+
return
387381
}
388382
if agent.LifecycleState == database.WorkspaceAgentLifecycleStateReady {
389383
// The startup script has finished running, so we can close the connection.
390384
return
391385
}
392386

393387
var (
394-
bufferedLogs = make(chan *database.WorkspaceAgentStartupLog, 128)
388+
// It's not impossible that
389+
bufferedLogs = make(chan []database.WorkspaceAgentStartupLog, 128)
395390
endOfLogs atomic.Bool
396391
lastSentLogID atomic.Int64
397392
)
398393

399-
sendLog := func(log *database.WorkspaceAgentStartupLog) {
394+
sendLogs := func(logs []database.WorkspaceAgentStartupLog) {
400395
select {
401-
case bufferedLogs <- log:
402-
lastSentLogID.Store(log.ID)
396+
case bufferedLogs <- logs:
397+
lastSentLogID.Store(logs[len(logs)-1].ID)
403398
default:
404399
logger.Warn(ctx, "workspace agent startup log overflowing channel")
405400
}
@@ -427,13 +422,7 @@ func (api *API) workspaceAgentStartupLogs(rw http.ResponseWriter, r *http.Reques
427422
logger.Warn(ctx, "failed to get workspace agent startup logs after", slog.Error(err))
428423
return
429424
}
430-
for _, log := range logs {
431-
if endOfLogs.Load() {
432-
return
433-
}
434-
log := log
435-
sendLog(&log)
436-
}
425+
sendLogs(logs)
437426
}
438427

439428
if jlMsg.EndOfLogs {
@@ -446,10 +435,7 @@ func (api *API) workspaceAgentStartupLogs(rw http.ResponseWriter, r *http.Reques
446435
logger.Warn(ctx, "get workspace agent startup logs after", slog.Error(err))
447436
return
448437
}
449-
for _, log := range logs {
450-
log := log
451-
sendLog(&log)
452-
}
438+
sendLogs(logs)
453439
bufferedLogs <- nil
454440
}
455441
},
@@ -468,19 +454,15 @@ func (api *API) workspaceAgentStartupLogs(rw http.ResponseWriter, r *http.Reques
468454
case <-ctx.Done():
469455
logger.Debug(context.Background(), "job logs context canceled")
470456
return
471-
case log, ok := <-bufferedLogs:
457+
case logs, ok := <-bufferedLogs:
472458
// A nil log is sent when complete!
473-
if !ok || log == nil {
459+
if !ok || logs == nil {
474460
logger.Debug(context.Background(), "reached the end of published logs")
475461
return
476462
}
477-
if logIdsDone[log.ID] {
478-
logger.Debug(ctx, "subscribe duplicated log")
479-
} else {
480-
err = encoder.Encode(convertWorkspaceAgentStartupLog(*log))
481-
if err != nil {
482-
return
483-
}
463+
err = encoder.Encode(convertWorkspaceAgentStartupLogs(logs))
464+
if err != nil {
465+
return
484466
}
485467
}
486468
}

site/src/components/Resources/AgentRow.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { VSCodeDesktopButton } from "components/VSCodeDesktopButton/VSCodeDeskto
1717
import { useMachine } from "@xstate/react"
1818
import { workspaceAgentLogsMachine } from "xServices/workspaceAgentLogs/workspaceAgentLogsXService"
1919
import { Line, Logs } from "components/Logs/Logs"
20+
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
21+
import { darcula } from "react-syntax-highlighter/dist/cjs/styles/prism"
2022

2123
export interface AgentRowProps {
2224
agent: WorkspaceAgent
@@ -45,6 +47,8 @@ export const AgentRow: FC<AgentRowProps> = ({
4547
context: { agentID: agent.id },
4648
})
4749

50+
console.log("drac", darcula)
51+
4852
return (
4953
<Stack direction="column" key={agent.id} spacing={0}>
5054
<Stack
@@ -149,8 +153,18 @@ export const AgentRow: FC<AgentRowProps> = ({
149153
</Stack>
150154

151155
<div>
156+
Startup Script
157+
<SyntaxHighlighter
158+
style={darcula}
159+
language="bash"
160+
useInlineStyles={false}
161+
codeTagProps={{ style: {} }}
162+
>
163+
{String(agent.startup_script)}
164+
</SyntaxHighlighter>
152165
{logsMachine.context.startupLogs && (
153166
<Logs
167+
className={styles.agentStartupLogs}
154168
lines={logsMachine.context.startupLogs.map(
155169
(log): Line => ({
156170
level: "info",
@@ -195,4 +209,10 @@ const useStyles = makeStyles((theme) => ({
195209
color: theme.palette.text.secondary,
196210
marginTop: theme.spacing(0.5),
197211
},
212+
213+
agentStartupLogs: {
214+
maxHeight: 200,
215+
display: "flex",
216+
flexDirection: "column-reverse",
217+
},
198218
}))

site/src/xServices/workspaceAgentLogs/workspaceAgentLogsXService.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ export const workspaceAgentLogsMachine = createMachine(
88
id: "workspaceAgentLogsMachine",
99
schema: {
1010
events: {} as {
11-
type: "ADD_STARTUP_LOG"
12-
log: TypesGen.WorkspaceAgentStartupLog
11+
type: "ADD_STARTUP_LOGS"
12+
logs: TypesGen.WorkspaceAgentStartupLog[]
1313
},
1414
context: {} as {
1515
agentID: string
@@ -45,8 +45,8 @@ export const workspaceAgentLogsMachine = createMachine(
4545
},
4646
},
4747
on: {
48-
ADD_STARTUP_LOG: {
49-
actions: "addStartupLog",
48+
ADD_STARTUP_LOGS: {
49+
actions: "addStartupLogs",
5050
},
5151
},
5252
},
@@ -65,7 +65,7 @@ export const workspaceAgentLogsMachine = createMachine(
6565
)
6666
socket.binaryType = "blob"
6767
socket.addEventListener("message", (event) => {
68-
callback({ type: "ADD_STARTUP_LOG", log: JSON.parse(event.data) })
68+
callback({ type: "ADD_STARTUP_LOGS", logs: JSON.parse(event.data) })
6969
})
7070
socket.addEventListener("error", () => {
7171
reject(new Error("socket errored"))
@@ -80,10 +80,10 @@ export const workspaceAgentLogsMachine = createMachine(
8080
assignStartupLogs: assign({
8181
startupLogs: (_, { data }) => data,
8282
}),
83-
addStartupLog: assign({
83+
addStartupLogs: assign({
8484
startupLogs: (context, event) => {
8585
const previousLogs = context.startupLogs ?? []
86-
return [...previousLogs, event.log]
86+
return [...previousLogs, ...event.logs]
8787
},
8888
}),
8989
},

0 commit comments

Comments
 (0)