workspaceAgentLogs returns the logs associated with a workspace agent @Summary Get logs by workspace agent @ID get-logs-by-workspace-agent @Security CoderSessionToken @Produce json @Tags Agents @Param workspaceagent path string true "Workspace agent ID" format(uuid) @Param before query int false "B
(rw http.ResponseWriter, r *http.Request)
| 381 | // @Success 200 {array} codersdk.WorkspaceAgentLog |
| 382 | // @Router /api/v2/workspaceagents/{workspaceagent}/logs [get] |
| 383 | func (api *API) workspaceAgentLogs(rw http.ResponseWriter, r *http.Request) { |
| 384 | // This mostly copies how provisioner job logs are streamed! |
| 385 | var ( |
| 386 | ctx = r.Context() |
| 387 | waws = httpmw.WorkspaceAgentAndWorkspaceParam(r) |
| 388 | logger = api.Logger.With(slog.F("workspace_agent_id", waws.WorkspaceAgent.ID)) |
| 389 | follow = r.URL.Query().Has("follow") |
| 390 | afterRaw = r.URL.Query().Get("after") |
| 391 | noCompression = r.URL.Query().Has("no_compression") |
| 392 | format = r.URL.Query().Get("format") |
| 393 | ) |
| 394 | |
| 395 | // Validate format parameter. |
| 396 | if format == "" { |
| 397 | format = "json" |
| 398 | } |
| 399 | if format != "json" && format != "text" { |
| 400 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 401 | Message: "Invalid format parameter.", |
| 402 | Detail: "Allowed values are \"json\" and \"text\".", |
| 403 | }) |
| 404 | return |
| 405 | } |
| 406 | |
| 407 | // Text format is not supported with streaming. |
| 408 | if format == "text" && follow { |
| 409 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 410 | Message: "Text format is not supported with follow mode.", |
| 411 | Detail: "Use format=json or omit the follow parameter.", |
| 412 | }) |
| 413 | return |
| 414 | } |
| 415 | |
| 416 | var after int64 |
| 417 | // Only fetch logs created after the time provided. |
| 418 | if afterRaw != "" { |
| 419 | var err error |
| 420 | after, err = strconv.ParseInt(afterRaw, 10, 64) |
| 421 | if err != nil || after < 0 { |
| 422 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 423 | Message: "Query param \"after\" must be an integer greater than or equal to zero.", |
| 424 | Validations: []codersdk.ValidationError{ |
| 425 | {Field: "after", Detail: "Must be an integer greater than or equal to zero"}, |
| 426 | }, |
| 427 | }) |
| 428 | return |
| 429 | } |
| 430 | } |
| 431 | |
| 432 | logs, err := api.Database.GetWorkspaceAgentLogsAfter(ctx, database.GetWorkspaceAgentLogsAfterParams{ |
| 433 | AgentID: waws.WorkspaceAgent.ID, |
| 434 | CreatedAfter: after, |
| 435 | }) |
| 436 | if errors.Is(err, sql.ErrNoRows) { |
| 437 | err = nil |
| 438 | } |
| 439 | if err != nil { |
| 440 | httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
no test coverage detected