Skip to content

Commit f0199da

Browse files
committed
merge
2 parents 64a6e5a + 6b38088 commit f0199da

File tree

12 files changed

+861
-163
lines changed

12 files changed

+861
-163
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,4 @@ benchmarks/dashboard-stack/package-lock.json
7171

7272
# virtual environment
7373
.venv/
74+
.cache/

include/aws/s3/private/s3_request.h

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,23 @@ struct aws_s3_request_metrics {
3131
struct aws_allocator *allocator;
3232

3333
struct {
34+
/* The time stamp when the request was first initiated by the client, including the very first attempt.
35+
* This timestamp is set once at the beginning and never updated during retries. Timestamps are from
36+
* `aws_high_res_clock_get_ticks`. This will always be available. */
37+
int64_t s3_request_first_attempt_start_timestamp_ns;
38+
39+
/* The time stamp when the request completely finished (success or final failure), including all retry
40+
* attempts. This is set when the request reaches its final state - either successful completion or
41+
* exhaustion of all retry attempts. Timestamps are from `aws_high_res_clock_get_ticks`. This will
42+
* be available with the last attempt. */
43+
int64_t s3_request_last_attempt_end_timestamp_ns;
44+
45+
/* The total time duration for the complete request lifecycle from initial start to final completion,
46+
* including all retry attempts, backoff delays, and connection establishment time
47+
* (s3_request_last_attempt_end_timestamp_ns - s3_request_first_attempt_start_timestamp_ns). This represents the
48+
* end-to-end user experience time. This will be available with the last attempt. */
49+
int64_t s3_request_total_duration_ns;
50+
3451
/* The time stamp when the request started by S3 client, which is prepared time by the client. Timestamps
3552
* are from `aws_high_res_clock_get_ticks`. This will always be available. */
3653
int64_t start_timestamp_ns;
@@ -90,6 +107,31 @@ struct aws_s3_request_metrics {
90107
/* The time duration for the request from start of delivery to finish of delivery (deliver_end_timestamp_ns -
91108
* deliver_start_timestamp_ns). When deliver_duration_ns is 0, means data not available. */
92109
int64_t deliver_duration_ns;
110+
111+
/* The time stamp when the request started to acquire connection. -1 means data not available. Timestamp
112+
* are from `aws_high_res_clock_get_ticks` */
113+
int64_t conn_acquire_start_timestamp_ns;
114+
/* The time stamp when the request finished to acquire connection. -1 means data not available.
115+
* Timestamp are from `aws_high_res_clock_get_ticks` */
116+
int64_t conn_acquire_end_timestamp_ns;
117+
/* The time duration for the request from start acquiring connection to finish acquiring connection
118+
* (conn_acquire_end_timestamp_ns - conn_acquire_start_timestamp_ns). When conn_acquire_end_timestamp_ns is -1,
119+
* means data not available. */
120+
int64_t conn_acquire_duration_ns;
121+
122+
/* The time stamp when the request started to delay for retry. -1 means data not available. Timestamp
123+
* are from `aws_high_res_clock_get_ticks` */
124+
int64_t retry_delay_start_timestamp_ns;
125+
/* The time stamp when the request finished to delay for retry. -1 means data not available.
126+
* Timestamp are from `aws_high_res_clock_get_ticks` */
127+
int64_t retry_delay_end_timestamp_ns;
128+
/* The time duration for the request from start retry delay to finish retry delay (retry_delay_end_timestamp_ns
129+
* - retry_delay_start_timestamp_ns). When retry_delay_end_timestamp_ns is -1, means data not available. */
130+
int64_t retry_delay_duration_ns;
131+
132+
/* The time duration for the service call from connection acquisition to first response byte. -1 means data not
133+
* available. */
134+
int64_t service_call_duration_ns;
93135
} time_metrics;
94136

95137
struct {
@@ -103,6 +145,8 @@ struct aws_s3_request_metrics {
103145
struct aws_string *host_address;
104146
/* The the request ID header value. */
105147
struct aws_string *request_id;
148+
/* The the extended request ID header value. */
149+
struct aws_string *extended_request_id;
106150
/* S3 operation name for the request */
107151
struct aws_string *operation_name;
108152
/* The type of request made */
@@ -113,7 +157,9 @@ struct aws_s3_request_metrics {
113157
/* The IP address of the request connected to */
114158
struct aws_string *ip_address;
115159
/* The pointer to the connection that request was made from */
116-
void *connection_id;
160+
void *connection_ptr;
161+
/* The pointer to the request that the request attempt was made from */
162+
void *request_ptr;
117163
/* The aws_thread_id_t to the thread that request ran on */
118164
aws_thread_id_t thread_id;
119165
/* The stream-id, which is the idex when the stream was activated. */
@@ -144,6 +190,13 @@ struct aws_s3_request {
144190
/* Linked list node used for queuing. */
145191
struct aws_linked_list_node node;
146192

193+
/* Timestamp when retry attempt started. Overwritten on each retry and copied to new attempt's setup data.
194+
* -1 means data not available. Timestamp from `aws_high_res_clock_get_ticks` */
195+
int64_t retry_start_timestamp_ns;
196+
/* Timestamp when retry attempt ended. Overwritten on each retry and copied to new attempt's setup data.
197+
* -1 means data not available. Timestamp from `aws_high_res_clock_get_ticks` */
198+
int64_t retry_end_timestamp_ns;
199+
147200
/* Linked list node used for tracking the request is active from HTTP level. */
148201
struct aws_linked_list_node cancellable_http_streams_list_node;
149202

@@ -261,7 +314,7 @@ struct aws_s3_request {
261314

262315
/* Returned request ID of this request. */
263316
struct aws_string *request_id;
264-
/* Returned amz ID 2 of this request. */
317+
/* Returned extended request id of this request. */
265318
struct aws_string *amz_id_2;
266319

267320
/* The metrics for the request telemetry */

include/aws/s3/s3_client.h

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,17 @@ int aws_s3_request_metrics_get_request_id(
14011401
const struct aws_s3_request_metrics *metrics,
14021402
const struct aws_string **out_request_id);
14031403

1404+
/**
1405+
* Get the extended request ID from aws_s3_request_metrics.
1406+
* If unavailable, AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised.
1407+
* If available, out_extended_request_id will be set to a string. Be warned this string's lifetime is tied to the
1408+
* metrics object.
1409+
**/
1410+
AWS_S3_API
1411+
int aws_s3_request_metrics_get_extended_request_id(
1412+
const struct aws_s3_request_metrics *metrics,
1413+
const struct aws_string **out_extended_request_id);
1414+
14041415
/* Get the start time from aws_s3_request_metrics, which is when S3 client prepare the request to be sent. Always
14051416
* available. Timestamp are from `aws_high_res_clock_get_ticks` */
14061417
AWS_S3_API
@@ -1574,10 +1585,14 @@ int aws_s3_request_metrics_get_ip_address(
15741585
const struct aws_s3_request_metrics *metrics,
15751586
const struct aws_string **out_ip_address);
15761587

1577-
/* Get the id of connection that request was made from. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised if data
1578-
* not available */
1588+
/* Get the ptr address of connection that request was made from. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised
1589+
* if data not available */
15791590
AWS_S3_API
1580-
int aws_s3_request_metrics_get_connection_id(const struct aws_s3_request_metrics *metrics, size_t *out_connection_id);
1591+
int aws_s3_request_metrics_get_connection_id(const struct aws_s3_request_metrics *metrics, size_t *out_connection_ptr);
1592+
1593+
/* Get the pointer to the request that attempt was made from. Always available. */
1594+
AWS_S3_API
1595+
int aws_s3_request_metrics_get_request_ptr(const struct aws_s3_request_metrics *metrics, size_t *out_request_ptr);
15811596

15821597
/* Get the thread ID of the thread that request was made from. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised if
15831598
* data not available */
@@ -1634,6 +1649,69 @@ void aws_s3_request_metrics_get_part_range_end(
16341649
/* Get the part number from request metrics. */
16351650
AWS_S3_API
16361651
void aws_s3_request_metrics_get_part_number(const struct aws_s3_request_metrics *metrics, uint32_t *out_part_number);
1652+
/* Get the request start timestamp from aws_s3_request_metrics. Always available. */
1653+
AWS_S3_API
1654+
void aws_s3_request_metrics_get_s3_request_first_attempt_start_timestamp_ns(
1655+
const struct aws_s3_request_metrics *metrics,
1656+
uint64_t *out_s3_request_first_attempt_start_time);
1657+
1658+
/* Get the request end timestamp. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised if data not
1659+
* available. */
1660+
AWS_S3_API
1661+
int aws_s3_request_metrics_get_s3_request_last_attempt_end_timestamp_ns(
1662+
const struct aws_s3_request_metrics *metrics,
1663+
uint64_t *out_s3_request_last_attempt_end_time);
1664+
1665+
/* Get the request duration. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised if data not
1666+
* available. */
1667+
AWS_S3_API
1668+
int aws_s3_request_metrics_get_s3_request_total_duration_ns(
1669+
const struct aws_s3_request_metrics *metrics,
1670+
uint64_t *out_request_duration);
1671+
1672+
/* Get the connection acquire start timestamp. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised if data not
1673+
* available. */
1674+
AWS_S3_API
1675+
int aws_s3_request_metrics_get_conn_acquire_start_timestamp_ns(
1676+
const struct aws_s3_request_metrics *metrics,
1677+
uint64_t *out_conn_acquire_start_time);
1678+
1679+
/* Get the connection acquire end timestamp. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised if data not
1680+
* available. */
1681+
AWS_S3_API
1682+
int aws_s3_request_metrics_get_conn_acquire_end_timestamp_ns(
1683+
const struct aws_s3_request_metrics *metrics,
1684+
uint64_t *out_conn_acquire_end_time);
1685+
1686+
/* Get the connection acquire duration. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised if data not available. */
1687+
AWS_S3_API
1688+
int aws_s3_request_metrics_get_conn_acquire_duration_ns(
1689+
const struct aws_s3_request_metrics *metrics,
1690+
uint64_t *out_conn_acquire_duration);
1691+
1692+
/* Get the retry delay start timestamp. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised if data not available. */
1693+
AWS_S3_API
1694+
int aws_s3_request_metrics_get_retry_delay_start_timestamp_ns(
1695+
const struct aws_s3_request_metrics *metrics,
1696+
uint64_t *out_retry_delay_start_time);
1697+
1698+
/* Get the retry delay end timestamp. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised if data not available. */
1699+
AWS_S3_API
1700+
int aws_s3_request_metrics_get_retry_delay_end_timestamp_ns(
1701+
const struct aws_s3_request_metrics *metrics,
1702+
uint64_t *out_retry_delay_end_time);
1703+
1704+
/* Get the retry delay duration. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised if data not available. */
1705+
AWS_S3_API
1706+
int aws_s3_request_metrics_get_retry_delay_duration_ns(
1707+
const struct aws_s3_request_metrics *metrics,
1708+
uint64_t *out_retry_delay_duration);
1709+
1710+
/* Get the service call duration. AWS_ERROR_S3_METRIC_DATA_NOT_AVAILABLE will be raised if data not available. */
1711+
AWS_S3_API
1712+
int aws_s3_request_metrics_get_service_call_duration_ns(
1713+
const struct aws_s3_request_metrics *metrics,
1714+
uint64_t *out_service_call_duration);
16371715

16381716
AWS_EXTERN_C_END
16391717
AWS_POP_SANE_WARNING_LEVEL

source/s3_client.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,6 +2189,16 @@ void aws_s3_client_update_connections_threaded(struct aws_s3_client *client) {
21892189
} else if (!request->always_send && aws_s3_meta_request_has_finish_result(request->meta_request)) {
21902190
/* Unless the request is marked "always send", if this meta request has a finish result, then finish the
21912191
* request now and release it. */
2192+
/* Update the error code for the metrics of the request here since we never acquire/release a connection */
2193+
request->send_data.metrics->crt_info_metrics.error_code = AWS_ERROR_S3_CANCELED;
2194+
2195+
/* Record end times as well */
2196+
aws_high_res_clock_get_ticks(
2197+
(uint64_t *)&request->send_data.metrics->time_metrics.s3_request_last_attempt_end_timestamp_ns);
2198+
request->send_data.metrics->time_metrics.s3_request_total_duration_ns =
2199+
request->send_data.metrics->time_metrics.s3_request_last_attempt_end_timestamp_ns -
2200+
request->send_data.metrics->time_metrics.s3_request_first_attempt_start_timestamp_ns;
2201+
21922202
s_s3_client_meta_request_finished_request(client, request->meta_request, request, AWS_ERROR_S3_CANCELED);
21932203
request = aws_s3_request_release(request);
21942204
} else if (
@@ -2322,6 +2332,8 @@ static void s_s3_client_acquired_retry_token(
23222332
/* TODO: not a blocker, consider managing the life time of aws_s3_client from aws_s3_endpoint to simplify usage */
23232333
aws_s3_client_acquire(client);
23242334

2335+
aws_high_res_clock_get_ticks((uint64_t *)&request->send_data.metrics->time_metrics.conn_acquire_start_timestamp_ns);
2336+
23252337
client->vtable->acquire_http_connection(
23262338
endpoint->http_connection_manager, s_s3_client_on_acquire_http_connection, connection);
23272339

@@ -2379,6 +2391,11 @@ static void s_s3_client_on_acquire_http_connection(
23792391
goto error_retry;
23802392
}
23812393

2394+
aws_high_res_clock_get_ticks((uint64_t *)&request->send_data.metrics->time_metrics.conn_acquire_end_timestamp_ns);
2395+
request->send_data.metrics->time_metrics.conn_acquire_duration_ns =
2396+
request->send_data.metrics->time_metrics.conn_acquire_end_timestamp_ns -
2397+
request->send_data.metrics->time_metrics.conn_acquire_start_timestamp_ns;
2398+
23822399
connection->http_connection = incoming_http_connection;
23832400
aws_s3_meta_request_send_request(meta_request, connection);
23842401
aws_s3_client_release(client); /* kept since this callback was registered */
@@ -2478,6 +2495,7 @@ void aws_s3_client_notify_connection_finished(
24782495
}
24792496

24802497
/* Ask the retry strategy to schedule a retry of the request. */
2498+
aws_high_res_clock_get_ticks((uint64_t *)&request->retry_start_timestamp_ns);
24812499
if (aws_retry_strategy_schedule_retry(
24822500
connection->retry_token, error_type, s_s3_client_retry_ready, connection)) {
24832501

@@ -2499,6 +2517,12 @@ void aws_s3_client_notify_connection_finished(
24992517

25002518
reset_connection:
25012519

2520+
aws_high_res_clock_get_ticks(
2521+
(uint64_t *)&request->send_data.metrics->time_metrics.s3_request_last_attempt_end_timestamp_ns);
2522+
request->send_data.metrics->time_metrics.s3_request_total_duration_ns =
2523+
request->send_data.metrics->time_metrics.s3_request_last_attempt_end_timestamp_ns -
2524+
request->send_data.metrics->time_metrics.s3_request_first_attempt_start_timestamp_ns;
2525+
25022526
if (connection->retry_token != NULL) {
25032527
/* If we have a retry token and successfully finished, record that success. */
25042528
if (finish_code == AWS_S3_CONNECTION_FINISH_CODE_SUCCESS) {
@@ -2567,6 +2591,8 @@ static void s_s3_client_retry_ready(struct aws_retry_token *token, int error_cod
25672591
struct aws_s3_request *request = connection->request;
25682592
AWS_PRECONDITION(request);
25692593

2594+
aws_high_res_clock_get_ticks((uint64_t *)&request->retry_end_timestamp_ns);
2595+
25702596
struct aws_s3_meta_request *meta_request = request->meta_request;
25712597
AWS_PRECONDITION(meta_request);
25722598

0 commit comments

Comments
 (0)