MCPcopy Index your code
hub / github.com/coder/coder / streamLogs

Method streamLogs

cli/cliui/agent.go:271–326  ·  view source on GitHub ↗

streamLogs handles streaming or fetching startup logs. nolint:revive // Control flag is acceptable for internal method.

(ctx context.Context, agent codersdk.WorkspaceAgent, follow bool, fetchedAgent chan fetchAgentResult)

Source from the content-addressed store, hash-verified

269//
270//nolint:revive // Control flag is acceptable for internal method.
271func (aw *agentWaiter) streamLogs(ctx context.Context, agent codersdk.WorkspaceAgent, follow bool, fetchedAgent chan fetchAgentResult) (codersdk.WorkspaceAgent, error) {
272 logStream, logsCloser, err := aw.opts.FetchLogs(ctx, agent.ID, 0, follow)
273 if err != nil {
274 return agent, xerrors.Errorf("fetch workspace agent startup logs: %w", err)
275 }
276 defer logsCloser.Close()
277
278 var lastLog codersdk.WorkspaceAgentLog
279
280 // If not following, we don't need to watch for agent state changes.
281 var fetchedAgentWhileFollowing chan fetchAgentResult
282 if follow {
283 fetchedAgentWhileFollowing = fetchedAgent
284 }
285
286 for {
287 select {
288 case <-ctx.Done():
289 return agent, ctx.Err()
290 case f := <-fetchedAgentWhileFollowing:
291 if f.err != nil {
292 return agent, xerrors.Errorf("fetch: %w", f.err)
293 }
294 agent = f.agent
295
296 // If the agent is no longer starting, stop following
297 // logs because FetchLogs will keep streaming forever.
298 // We do one last non-follow request to ensure we have
299 // fetched all logs.
300 if !agent.LifecycleState.Starting() {
301 _ = logsCloser.Close()
302 fetchedAgentWhileFollowing = nil
303
304 logStream, logsCloser, err = aw.opts.FetchLogs(ctx, agent.ID, lastLog.ID, false)
305 if err != nil {
306 return agent, xerrors.Errorf("fetch workspace agent startup logs: %w", err)
307 }
308 // Logs are already primed, so we can call close.
309 _ = logsCloser.Close()
310 }
311 case logs, ok := <-logStream:
312 if !ok {
313 return agent, nil
314 }
315 for _, log := range logs {
316 source, hasSource := aw.logSources[log.SourceID]
317 output := log.Output
318 if hasSource && source.DisplayName != "" {
319 output = source.DisplayName + ": " + output
320 }
321 aw.sw.Log(log.CreatedAt, log.Level, output)
322 lastLog = log
323 }
324 }
325 }
326}
327
328// waitForReconnection handles the Disconnected state.

Callers 1

handleConnectedMethod · 0.95

Calls 6

ErrMethod · 0.80
LogMethod · 0.80
CloseMethod · 0.65
ErrorfMethod · 0.45
DoneMethod · 0.45
StartingMethod · 0.45

Tested by

no test coverage detected