Skip to content

Commit adbcc02

Browse files
http: add trace2 logging for retry operations
Add trace2 instrumentation to HTTP 429 retry operations to enable monitoring and debugging of rate limit scenarios in production environments. The trace2 logging captures: * Retry attempt numbers (http/429-retry-attempt) to track retry progression and identify how many attempts were needed * Retry-After header values (http/429-retry-after) from server responses to understand server-requested delays * Actual sleep durations (http/retry-sleep-seconds) within trace2 regions (http/retry-sleep) to measure time spent waiting * Error conditions (http/429-error) such as "retries-exhausted", "exceeds-max-retry-time", "no-retry-after-config", and "config-exceeds-max-retry-time" for diagnosing failures * Retry source (http/429-retry-source) indicating whether delay came from server header or config default This instrumentation provides complete visibility into retry behavior, enabling operators to monitor rate limiting patterns, diagnose retry failures, and optimize retry configuration based on real-world data. Signed-off-by: Vaidas Pilkauskas <vaidas.pilkauskas@shopify.com>
1 parent 4382237 commit adbcc02

File tree

1 file changed

+31
-9
lines changed

1 file changed

+31
-9
lines changed

http.c

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "odb.h"
2424
#include "tempfile.h"
2525
#include "date.h"
26+
#include "trace2.h"
2627

2728
static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
2829
static int trace_curl_data = 1;
@@ -1944,6 +1945,8 @@ static int handle_curl_result(struct slot_results *results)
19441945
} else if (results->http_code == 429) {
19451946
/* Store the retry_after value for use in retry logic */
19461947
last_retry_after = results->retry_after;
1948+
trace2_data_intmax("http", the_repository, "http/429-retry-after",
1949+
last_retry_after);
19471950
return HTTP_RATE_LIMITED;
19481951
} else {
19491952
if (results->http_connectcode == 407)
@@ -2338,11 +2341,15 @@ static void sleep_for_retry(long retry_after)
23382341
if (retry_after > 0) {
23392342
unsigned int remaining;
23402343
warning(_("rate limited, waiting %ld seconds before retry"), retry_after);
2344+
trace2_region_enter("http", "retry-sleep", the_repository);
2345+
trace2_data_intmax("http", the_repository, "http/retry-sleep-seconds",
2346+
retry_after);
23412347
remaining = sleep(retry_after);
23422348
while (remaining > 0) {
23432349
/* Sleep was interrupted, continue sleeping */
23442350
remaining = sleep(remaining);
23452351
}
2352+
trace2_region_leave("http", "retry-sleep", the_repository);
23462353
}
23472354
}
23482355

@@ -2400,10 +2407,15 @@ static int http_request_reauth(const char *url,
24002407
/* Handle rate limiting with retry logic */
24012408
int retry_attempt = http_max_retries - rate_limit_retries + 1;
24022409

2410+
trace2_data_intmax("http", the_repository, "http/429-retry-attempt",
2411+
retry_attempt);
2412+
24032413
if (rate_limit_retries <= 0) {
24042414
/* Retries are disabled or exhausted */
24052415
if (http_max_retries > 0) {
24062416
error(_("too many rate limit retries, giving up"));
2417+
trace2_data_string("http", the_repository,
2418+
"http/429-error", "retries-exhausted");
24072419
}
24082420
return HTTP_ERROR;
24092421
}
@@ -2418,6 +2430,10 @@ static int http_request_reauth(const char *url,
24182430
error(_("rate limited (HTTP 429) requested %ld second delay, "
24192431
"exceeds http.maxRetryTime of %ld seconds"),
24202432
last_retry_after, http_max_retry_time);
2433+
trace2_data_string("http", the_repository,
2434+
"http/429-error", "exceeds-max-retry-time");
2435+
trace2_data_intmax("http", the_repository,
2436+
"http/429-requested-delay", last_retry_after);
24212437
last_retry_after = -1; /* Reset after use */
24222438
return HTTP_ERROR;
24232439
}
@@ -2429,17 +2445,23 @@ static int http_request_reauth(const char *url,
24292445
/* Not configured - exit with error */
24302446
error(_("rate limited (HTTP 429) and no Retry-After header provided. "
24312447
"Configure http.retryAfter or set GIT_HTTP_RETRY_AFTER."));
2448+
trace2_data_string("http", the_repository,
2449+
"http/429-error", "no-retry-after-config");
24322450
return HTTP_ERROR;
24332451
}
2434-
/* Check if configured default exceeds maximum allowed */
2435-
if (http_retry_after > http_max_retry_time) {
2436-
error(_("configured http.retryAfter (%ld seconds) exceeds "
2437-
"http.maxRetryTime (%ld seconds)"),
2438-
http_retry_after, http_max_retry_time);
2439-
return HTTP_ERROR;
2440-
}
2441-
/* Use configured default retry-after value */
2442-
sleep_for_retry(http_retry_after);
2452+
/* Check if configured default exceeds maximum allowed */
2453+
if (http_retry_after > http_max_retry_time) {
2454+
error(_("configured http.retryAfter (%ld seconds) exceeds "
2455+
"http.maxRetryTime (%ld seconds)"),
2456+
http_retry_after, http_max_retry_time);
2457+
trace2_data_string("http", the_repository,
2458+
"http/429-error", "config-exceeds-max-retry-time");
2459+
return HTTP_ERROR;
2460+
}
2461+
/* Use configured default retry-after value */
2462+
trace2_data_string("http", the_repository,
2463+
"http/429-retry-source", "config-default");
2464+
sleep_for_retry(http_retry_after);
24432465
}
24442466
} else if (ret == HTTP_REAUTH) {
24452467
credential_fill(the_repository, &http_auth, 1);

0 commit comments

Comments
 (0)