diff --git a/include/aws/s3/private/s3_meta_request_impl.h b/include/aws/s3/private/s3_meta_request_impl.h index 206f9e027..38d9a33c6 100644 --- a/include/aws/s3/private/s3_meta_request_impl.h +++ b/include/aws/s3/private/s3_meta_request_impl.h @@ -88,6 +88,9 @@ struct aws_s3_meta_request_vtable { /* Pause the given request */ int (*pause)(struct aws_s3_meta_request *meta_request, struct aws_s3_meta_request_resume_token **resume_token); + + /* Get the type of the aws_s3_request */ + int (*get_request_type)(struct aws_s3_request *request); }; /** diff --git a/include/aws/s3/private/s3_request.h b/include/aws/s3/private/s3_request.h index 8c42430c0..b88aa55ca 100644 --- a/include/aws/s3/private/s3_request.h +++ b/include/aws/s3/private/s3_request.h @@ -73,6 +73,8 @@ struct aws_s3_request_metrics { struct aws_string *host_address; /* The the request ID header value. */ struct aws_string *request_id; + /* The type of request made */ + enum aws_s3_request_type request_type; } req_resp_info_metrics; struct { diff --git a/include/aws/s3/s3_client.h b/include/aws/s3/s3_client.h index e9b761760..d7d905297 100644 --- a/include/aws/s3/s3_client.h +++ b/include/aws/s3/s3_client.h @@ -78,6 +78,26 @@ enum aws_s3_meta_request_type { AWS_S3_META_REQUEST_TYPE_MAX, }; +/** + * The type of S3 request made. Used by metrics. + */ +enum aws_s3_request_type { + /* Same as the original HTTP request passed to aws_s3_meta_request_options */ + AWS_S3_REQUEST_TYPE_DEFAULT, + + /* S3 APIs */ + AWS_S3_REQUEST_TYPE_HEAD_OBJECT, + AWS_S3_REQUEST_TYPE_GET_OBJECT, + AWS_S3_REQUEST_TYPE_LIST_PARTS, + AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD, + AWS_S3_REQUEST_TYPE_UPLOAD_PART, + AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD, + AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD, + AWS_S3_REQUEST_TYPE_UPLOAD_PART_COPY, + + AWS_S3_REQUEST_TYPE_MAX, +}; + /** * Invoked to provide response headers received during execution of the meta request, both for * success and error HTTP status codes. @@ -855,9 +875,15 @@ int aws_s3_request_metrics_get_thread_id(const struct aws_s3_request_metrics *me AWS_S3_API int aws_s3_request_metrics_get_request_stream_id(const struct aws_s3_request_metrics *metrics, uint32_t *out_stream_id); +/* Get the request type from request metrics. */ +AWS_S3_API +void aws_s3_request_metrics_get_request_type( + const struct aws_s3_request_metrics *metrics, + enum aws_s3_request_type *out_request_type); + /* Get the AWS CRT error code from request metrics. */ AWS_S3_API -int aws_s3_request_metrics_get_error_code(const struct aws_s3_request_metrics *out_metrics); +int aws_s3_request_metrics_get_error_code(const struct aws_s3_request_metrics *metrics); AWS_EXTERN_C_END AWS_POP_SANE_WARNING_LEVEL diff --git a/source/s3_auto_ranged_get.c b/source/s3_auto_ranged_get.c index 3f90578f2..adb9efd28 100644 --- a/source/s3_auto_ranged_get.c +++ b/source/s3_auto_ranged_get.c @@ -31,6 +31,8 @@ static void s_s3_auto_ranged_get_request_finished( struct aws_s3_request *request, int error_code); +static int s_s3_auto_ranged_get_request_type(struct aws_s3_request *request); + static struct aws_s3_meta_request_vtable s_s3_auto_ranged_get_vtable = { .update = s_s3_auto_ranged_get_update, .send_request_finish = aws_s3_meta_request_send_request_finish_default, @@ -40,8 +42,21 @@ static struct aws_s3_meta_request_vtable s_s3_auto_ranged_get_vtable = { .finished_request = s_s3_auto_ranged_get_request_finished, .destroy = s_s3_meta_request_auto_ranged_get_destroy, .finish = aws_s3_meta_request_finish_default, + .get_request_type = s_s3_auto_ranged_get_request_type, }; +static int s_s3_auto_ranged_get_request_type(struct aws_s3_request *request) { + switch (request->request_tag) { + case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_HEAD_OBJECT: + return AWS_S3_REQUEST_TYPE_HEAD_OBJECT; + case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_PART: + case AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_INITIAL_MESSAGE: + return AWS_S3_REQUEST_TYPE_GET_OBJECT; + } + AWS_ASSERT(false); + return AWS_S3_REQUEST_TYPE_MAX; +} + static int s_s3_auto_ranged_get_success_status(struct aws_s3_meta_request *meta_request) { AWS_PRECONDITION(meta_request); diff --git a/source/s3_auto_ranged_put.c b/source/s3_auto_ranged_put.c index 496c8fef2..c9ec2e1f6 100644 --- a/source/s3_auto_ranged_put.c +++ b/source/s3_auto_ranged_put.c @@ -244,6 +244,23 @@ static int s_try_init_resume_state_from_persisted_data( return AWS_OP_SUCCESS; } +static int s_s3_auto_ranged_put_request_type(struct aws_s3_request *request) { + switch (request->request_tag) { + case AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_LIST_PARTS: + return AWS_S3_REQUEST_TYPE_LIST_PARTS; + case AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_CREATE_MULTIPART_UPLOAD: + return AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD; + case AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_PART: + return AWS_S3_REQUEST_TYPE_UPLOAD_PART; + case AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_ABORT_MULTIPART_UPLOAD: + return AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD; + case AWS_S3_AUTO_RANGED_PUT_REQUEST_TAG_COMPLETE_MULTIPART_UPLOAD: + return AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD; + } + AWS_ASSERT(false); + return AWS_S3_REQUEST_TYPE_MAX; +} + static struct aws_s3_meta_request_vtable s_s3_auto_ranged_put_vtable = { .update = s_s3_auto_ranged_put_update, .send_request_finish = s_s3_auto_ranged_put_send_request_finish, @@ -254,6 +271,7 @@ static struct aws_s3_meta_request_vtable s_s3_auto_ranged_put_vtable = { .destroy = s_s3_meta_request_auto_ranged_put_destroy, .finish = aws_s3_meta_request_finish_default, .pause = s_s3_auto_ranged_put_pause, + .get_request_type = s_s3_auto_ranged_put_request_type, }; /* Allocate a new auto-ranged put meta request */ diff --git a/source/s3_copy_object.c b/source/s3_copy_object.c index 60c80d4b1..c6954e8dd 100644 --- a/source/s3_copy_object.c +++ b/source/s3_copy_object.c @@ -37,6 +37,27 @@ static void s_s3_copy_object_request_finished( struct aws_s3_request *request, int error_code); +static int s_s3_copy_object_request_type(struct aws_s3_request *request) { + switch (request->request_tag) { + case AWS_S3_COPY_OBJECT_REQUEST_TAG_GET_OBJECT_SIZE: + /* It's a HEAD request of GetObject call */ + return AWS_S3_REQUEST_TYPE_HEAD_OBJECT; + case AWS_S3_COPY_OBJECT_REQUEST_TAG_BYPASS: + /* A single copy object request, same as default */ + return AWS_S3_REQUEST_TYPE_DEFAULT; + case AWS_S3_COPY_OBJECT_REQUEST_TAG_CREATE_MULTIPART_UPLOAD: + return AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD; + case AWS_S3_COPY_OBJECT_REQUEST_TAG_MULTIPART_COPY: + return AWS_S3_REQUEST_TYPE_UPLOAD_PART_COPY; + case AWS_S3_COPY_OBJECT_REQUEST_TAG_ABORT_MULTIPART_UPLOAD: + return AWS_S3_REQUEST_TYPE_ABORT_MULTIPART_UPLOAD; + case AWS_S3_COPY_OBJECT_REQUEST_TAG_COMPLETE_MULTIPART_UPLOAD: + return AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD; + } + AWS_ASSERT(false); + return AWS_S3_REQUEST_TYPE_MAX; +} + static struct aws_s3_meta_request_vtable s_s3_copy_object_vtable = { .update = s_s3_copy_object_update, .send_request_finish = aws_s3_meta_request_send_request_finish_handle_async_error, @@ -46,6 +67,7 @@ static struct aws_s3_meta_request_vtable s_s3_copy_object_vtable = { .finished_request = s_s3_copy_object_request_finished, .destroy = s_s3_meta_request_copy_object_destroy, .finish = aws_s3_meta_request_finish_default, + .get_request_type = s_s3_copy_object_request_type, }; /* Allocate a new copy object meta request */ diff --git a/source/s3_request.c b/source/s3_request.c index 196581fda..e91229dbf 100644 --- a/source/s3_request.c +++ b/source/s3_request.c @@ -48,6 +48,12 @@ void aws_s3_request_setup_send_data(struct aws_s3_request *request, struct aws_h if (meta_request->telemetry_callback) { /* start the telemetry for the request to be sent */ request->send_data.metrics = aws_s3_request_metrics_new(request->allocator, message); + if (!meta_request->vtable->get_request_type) { + request->send_data.metrics->req_resp_info_metrics.request_type = AWS_S3_REQUEST_TYPE_DEFAULT; + } else { + request->send_data.metrics->req_resp_info_metrics.request_type = + meta_request->vtable->get_request_type(request); + } /* Start the timestamp */ aws_high_res_clock_get_ticks((uint64_t *)&request->send_data.metrics->time_metrics.start_timestamp_ns); } @@ -379,6 +385,14 @@ int aws_s3_request_metrics_get_request_stream_id(const struct aws_s3_request_met return AWS_OP_SUCCESS; } +void aws_s3_request_metrics_get_request_type( + const struct aws_s3_request_metrics *metrics, + enum aws_s3_request_type *out_request_type) { + AWS_PRECONDITION(metrics); + AWS_PRECONDITION(out_request_type); + *out_request_type = metrics->req_resp_info_metrics.request_type; +} + int aws_s3_request_metrics_get_error_code(const struct aws_s3_request_metrics *metrics) { AWS_PRECONDITION(metrics); return metrics->crt_info_metrics.error_code; diff --git a/tests/s3_mock_server_tests.c b/tests/s3_mock_server_tests.c index 2b225aa58..57d0bf4c1 100644 --- a/tests/s3_mock_server_tests.c +++ b/tests/s3_mock_server_tests.c @@ -81,6 +81,9 @@ static int s_validate_mpu_mock_server_metrics(struct aws_array_list *metrics_lis ASSERT_SUCCESS(aws_s3_request_metrics_get_receiving_duration_ns(metrics, &time_stamp)); ASSERT_FALSE(time_stamp == 0); time_stamp = 0; + enum aws_s3_request_type request_type = 0; + aws_s3_request_metrics_get_request_type(metrics, &request_type); + ASSERT_UINT_EQUALS(AWS_S3_REQUEST_TYPE_CREATE_MULTIPART_UPLOAD, request_type); /* Second metrics should be the Upload Part */ aws_array_list_get_at(metrics_list, (void **)&metrics, 1); @@ -92,6 +95,21 @@ static int s_validate_mpu_mock_server_metrics(struct aws_array_list *metrics_lis ASSERT_TRUE(aws_byte_cursor_eq_c_str(&header_value, "b54357faf0632cce46e942fa68356b38")); ASSERT_SUCCESS(aws_http_headers_get(response_headers, aws_byte_cursor_from_c_str("Connection"), &header_value)); ASSERT_TRUE(aws_byte_cursor_eq_c_str(&header_value, "keep-alive")); + request_type = 0; + aws_s3_request_metrics_get_request_type(metrics, &request_type); + ASSERT_UINT_EQUALS(AWS_S3_REQUEST_TYPE_UPLOAD_PART, request_type); + + /* Third metrics still be Upload Part */ + aws_array_list_get_at(metrics_list, (void **)&metrics, 2); + request_type = 0; + aws_s3_request_metrics_get_request_type(metrics, &request_type); + ASSERT_UINT_EQUALS(AWS_S3_REQUEST_TYPE_UPLOAD_PART, request_type); + + /* Fourth should be complete MPU */ + aws_array_list_get_at(metrics_list, (void **)&metrics, 3); + request_type = 0; + aws_s3_request_metrics_get_request_type(metrics, &request_type); + ASSERT_UINT_EQUALS(AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD, request_type); /* All the rest should be similar */ return AWS_OP_SUCCESS;