Coder establishes a connection to the Coder instance located at coderURL and authenticates using token. It then establishes a dRPC connection to the Agent API and begins sending logs. If the version of Coder does not support the Agent API, it will fall back to using the PatchLogs endpoint. The close
(ctx context.Context, coderURL *url.URL, token string)
| 36 | // be sent. Cancelling the context will close the logs immediately without |
| 37 | // waiting for logs to be sent. |
| 38 | func Coder(ctx context.Context, coderURL *url.URL, token string) (logger Func, closer func(), err error) { |
| 39 | // To troubleshoot issues, we need some way of logging. |
| 40 | metaLogger := slog.Make(sloghuman.Sink(os.Stderr)) |
| 41 | defer metaLogger.Sync() |
| 42 | client := initClient(coderURL, token) |
| 43 | bi, err := client.SDK.BuildInfo(ctx) |
| 44 | if err != nil { |
| 45 | return nil, nil, fmt.Errorf("get coder build version: %w", err) |
| 46 | } |
| 47 | if semver.Compare(semver.MajorMinor(bi.Version), minAgentAPIV2) < 0 { |
| 48 | metaLogger.Warn(ctx, "Detected Coder version incompatible with AgentAPI v2, falling back to deprecated API", slog.F("coder_version", bi.Version)) |
| 49 | logger, closer = sendLogsV1(ctx, client, metaLogger.Named("send_logs_v1")) |
| 50 | return logger, closer, nil |
| 51 | } |
| 52 | |
| 53 | // Create a new context so we can ensure the connection is torn down. |
| 54 | ctx, cancel := context.WithCancel(ctx) |
| 55 | defer func() { |
| 56 | if err != nil { |
| 57 | cancel() |
| 58 | } |
| 59 | }() |
| 60 | // Note that ctx passed to initRPC will be inherited by the |
| 61 | // underlying connection, nothing we can do about that here. |
| 62 | dac, err := initRPC(ctx, client, metaLogger.Named("init_rpc")) |
| 63 | if err != nil { |
| 64 | // Logged externally |
| 65 | return nil, nil, fmt.Errorf("init coder rpc client: %w", err) |
| 66 | } |
| 67 | ls := agentsdk.NewLogSender(metaLogger.Named("coder_log_sender")) |
| 68 | metaLogger.Warn(ctx, "Sending logs via AgentAPI v2", slog.F("coder_version", bi.Version)) |
| 69 | logger, loggerCloser := sendLogsV2(ctx, dac, ls, metaLogger.Named("send_logs_v2")) |
| 70 | var closeOnce sync.Once |
| 71 | closer = func() { |
| 72 | loggerCloser() |
| 73 | |
| 74 | closeOnce.Do(func() { |
| 75 | // Typically cancel would be after Close, but we want to be |
| 76 | // sure there's nothing that might block on Close. |
| 77 | cancel() |
| 78 | _ = dac.DRPCConn().Close() |
| 79 | }) |
| 80 | } |
| 81 | return logger, closer, nil |
| 82 | } |
| 83 | |
| 84 | type coderLogSender interface { |
| 85 | Enqueue(uuid.UUID, ...agentsdk.Log) |