99 "errors"
1010 "fmt"
1111 "io"
12+ "log/slog"
1213 "net/http"
1314 "net/url"
1415 "os"
@@ -233,23 +234,68 @@ func (i *Installer) install(ctx context.Context) (InstallStatus, error) {
233234 if err := os .MkdirAll (filepath .Dir (targetPath ), 0o755 ); err != nil {
234235 return InstallStatus {}, fmt .Errorf ("create Codex install directory: %w" , err )
235236 }
237+ started := time .Now ()
238+ logURL := downloadLogURL (downloadURL )
239+ slog .InfoContext (ctx , "Codex CLI download started" ,
240+ "url" , logURL ,
241+ "os" , i .goos ,
242+ "arch" , i .goarch ,
243+ "target_path" , targetPath ,
244+ "max_attempts" , defaultInstallAttempts ,
245+ )
236246 for attempt := 1 ; attempt <= defaultInstallAttempts ; attempt ++ {
237- status , err := i .installAttempt (ctx , platform , downloadURL , targetPath )
247+ attemptStarted := time .Now ()
248+ slog .InfoContext (ctx , "Codex CLI download attempt started" ,
249+ "url" , logURL ,
250+ "attempt" , attempt ,
251+ "max_attempts" , defaultInstallAttempts ,
252+ )
253+ status , err := i .installAttempt (ctx , platform , downloadURL , targetPath , attempt )
238254 if err == nil {
255+ slog .InfoContext (ctx , "Codex CLI download completed" ,
256+ "url" , logURL ,
257+ "attempt" , attempt ,
258+ "duration" , time .Since (started ),
259+ "installed_path" , status .Path ,
260+ )
239261 return status , nil
240262 }
241263 var retryable * retryableInstallError
242264 if ! errors .As (err , & retryable ) || attempt == defaultInstallAttempts {
265+ slog .InfoContext (ctx , "Codex CLI download failed" ,
266+ "url" , logURL ,
267+ "attempt" , attempt ,
268+ "max_attempts" , defaultInstallAttempts ,
269+ "attempt_duration" , time .Since (attemptStarted ),
270+ "duration" , time .Since (started ),
271+ "error" , err ,
272+ )
243273 return InstallStatus {}, err
244274 }
275+ retryDelay := installRetryDelay (attempt )
276+ slog .InfoContext (ctx , "Codex CLI download attempt failed; retrying" ,
277+ "url" , logURL ,
278+ "attempt" , attempt ,
279+ "max_attempts" , defaultInstallAttempts ,
280+ "attempt_duration" , time .Since (attemptStarted ),
281+ "retry_in" , retryDelay ,
282+ "error" , err ,
283+ )
245284 if err := waitForInstallRetry (ctx , attempt ); err != nil {
285+ slog .InfoContext (ctx , "Codex CLI download retry canceled" ,
286+ "url" , logURL ,
287+ "attempt" , attempt ,
288+ "duration" , time .Since (started ),
289+ "error" , err ,
290+ )
246291 return InstallStatus {}, fmt .Errorf ("retry Codex CLI download: %w" , err )
247292 }
248293 }
249294 return InstallStatus {}, errors .New ("install Codex CLI: exhausted download attempts" )
250295}
251296
252- func (i * Installer ) installAttempt (ctx context.Context , platform downloadPlatform , downloadURL , targetPath string ) (InstallStatus , error ) {
297+ func (i * Installer ) installAttempt (ctx context.Context , platform downloadPlatform , downloadURL , targetPath string , attempt int ) (InstallStatus , error ) {
298+ requestStarted := time .Now ()
253299 req , err := http .NewRequestWithContext (ctx , http .MethodGet , downloadURL , nil )
254300 if err != nil {
255301 return InstallStatus {}, fmt .Errorf ("create Codex download request: %w" , err )
@@ -259,12 +305,27 @@ func (i *Installer) installAttempt(ctx context.Context, platform downloadPlatfor
259305 resp , err := i .httpClient .Do (req )
260306 if err != nil {
261307 err = fmt .Errorf ("download Codex CLI: %w" , err )
308+ slog .InfoContext (ctx , "Codex CLI download request failed" ,
309+ "url" , downloadLogURL (downloadURL ),
310+ "attempt" , attempt ,
311+ "duration" , time .Since (requestStarted ),
312+ "error" , err ,
313+ )
262314 if ctx .Err () == nil {
263315 err = & retryableInstallError {err : err }
264316 }
265317 return InstallStatus {}, err
266318 }
267319 defer resp .Body .Close ()
320+ slog .InfoContext (ctx , "Codex CLI download response received" ,
321+ "url" , downloadLogURL (downloadURL ),
322+ "attempt" , attempt ,
323+ "status" , resp .StatusCode ,
324+ "protocol" , resp .Proto ,
325+ "content_length" , resp .ContentLength ,
326+ "accept_ranges" , resp .Header .Get ("Accept-Ranges" ),
327+ "duration" , time .Since (requestStarted ),
328+ )
268329 if resp .StatusCode != http .StatusOK {
269330 message , _ := io .ReadAll (io .LimitReader (resp .Body , 4096 ))
270331 detail := strings .TrimSpace (string (message ))
@@ -303,6 +364,14 @@ func (i *Installer) installAttempt(ctx context.Context, platform downloadPlatfor
303364 err = installUnixArchive (temp , limited , platform .archiveBinary )
304365 }
305366 if err != nil {
367+ downloaded := maxDownloadSize + 1 - limited .N
368+ slog .InfoContext (ctx , "Codex CLI download body failed" ,
369+ "url" , downloadLogURL (downloadURL ),
370+ "attempt" , attempt ,
371+ "bytes" , downloaded ,
372+ "duration" , time .Since (requestStarted ),
373+ "error" , err ,
374+ )
306375 if body .err != nil {
307376 err = & retryableInstallError {err : err }
308377 }
@@ -314,6 +383,12 @@ func (i *Installer) installAttempt(ctx context.Context, platform downloadPlatfor
314383 if limited .N <= 0 {
315384 return InstallStatus {}, fmt .Errorf ("download Codex CLI: package exceeds limit %d" , maxDownloadSize )
316385 }
386+ slog .InfoContext (ctx , "Codex CLI download body completed" ,
387+ "url" , downloadLogURL (downloadURL ),
388+ "attempt" , attempt ,
389+ "bytes" , maxDownloadSize + 1 - limited .N ,
390+ "duration" , time .Since (requestStarted ),
391+ )
317392 if err := temp .Chmod (0o755 ); err != nil {
318393 return InstallStatus {}, fmt .Errorf ("make Codex binary executable: %w" , err )
319394 }
@@ -342,8 +417,23 @@ func retryableHTTPStatus(status int) bool {
342417 status >= http .StatusInternalServerError && status < 600
343418}
344419
420+ func downloadLogURL (value string ) string {
421+ parsed , err := url .Parse (value )
422+ if err != nil {
423+ return ""
424+ }
425+ parsed .User = nil
426+ parsed .RawQuery = ""
427+ parsed .Fragment = ""
428+ return parsed .String ()
429+ }
430+
431+ func installRetryDelay (attempt int ) time.Duration {
432+ return installRetryBaseDelay << (attempt - 1 )
433+ }
434+
345435func waitForInstallRetry (ctx context.Context , attempt int ) error {
346- delay := installRetryBaseDelay << (attempt - 1 )
436+ delay := installRetryDelay (attempt )
347437 timer := time .NewTimer (delay )
348438 defer timer .Stop ()
349439 select {
0 commit comments