55
66#include <aws/http/private/h2_stream.h>
77
8+ #include <aws/common/clock.h>
89#include <aws/http/private/h2_connection.h>
910#include <aws/http/private/strutil.h>
1011#include <aws/http/status_code.h>
@@ -240,10 +241,17 @@ struct aws_h2_stream *aws_h2_stream_new_request(
240241 stream -> base .on_incoming_headers = options -> on_response_headers ;
241242 stream -> base .on_incoming_header_block_done = options -> on_response_header_block_done ;
242243 stream -> base .on_incoming_body = options -> on_response_body ;
244+ stream -> base .on_metrics = options -> on_metrics ;
243245 stream -> base .on_complete = options -> on_complete ;
244246 stream -> base .on_destroy = options -> on_destroy ;
245247 stream -> base .client_data = & stream -> base .client_or_server_data .client ;
246248 stream -> base .client_data -> response_status = AWS_HTTP_STATUS_CODE_UNKNOWN ;
249+ stream -> base .metrics .send_start_timestamp_ns = -1 ;
250+ stream -> base .metrics .send_end_timestamp_ns = -1 ;
251+ stream -> base .metrics .sending_duration_ns = -1 ;
252+ stream -> base .metrics .receive_start_timestamp_ns = -1 ;
253+ stream -> base .metrics .receive_end_timestamp_ns = -1 ;
254+ stream -> base .metrics .receiving_duration_ns = -1 ;
247255 aws_linked_list_init (& stream -> thread_data .outgoing_writes );
248256 aws_linked_list_init (& stream -> synced_data .pending_write_list );
249257
@@ -446,6 +454,9 @@ void aws_h2_stream_complete(struct aws_h2_stream *stream, int error_code) {
446454 s_h2_stream_destroy_pending_writes (stream );
447455
448456 /* Invoke callback */
457+ if (stream -> base .on_metrics ) {
458+ stream -> base .on_metrics (& stream -> base , & stream -> base .metrics , stream -> base .user_data );
459+ }
449460 if (stream -> base .on_complete ) {
450461 stream -> base .on_complete (& stream -> base , error_code , stream -> base .user_data );
451462 }
@@ -706,7 +717,8 @@ int aws_h2_stream_on_activated(struct aws_h2_stream *stream, enum aws_h2_stream_
706717 AWS_H2_STREAM_LOGF (ERROR , stream , "Failed to create HEADERS frame: %s" , aws_error_name (aws_last_error ()));
707718 goto error ;
708719 }
709-
720+ AWS_ASSERT (stream -> base .metrics .send_start_timestamp_ns == -1 );
721+ aws_high_res_clock_get_ticks ((uint64_t * )& stream -> base .metrics .send_start_timestamp_ns );
710722 /* Initialize the flow-control window size */
711723 stream -> thread_data .window_size_peer =
712724 connection -> thread_data .settings_peer [AWS_HTTP2_SETTINGS_INITIAL_WINDOW_SIZE ];
@@ -721,6 +733,11 @@ int aws_h2_stream_on_activated(struct aws_h2_stream *stream, enum aws_h2_stream_
721733 /* If stream has no body, then HEADERS frame marks the end of outgoing data */
722734 stream -> thread_data .state = AWS_H2_STREAM_STATE_HALF_CLOSED_LOCAL ;
723735 AWS_H2_STREAM_LOG (TRACE , stream , "Sending HEADERS with END_STREAM. State -> HALF_CLOSED_LOCAL" );
736+ /* There is no further frames to be sent, now is the end timestamp of sending. */
737+ AWS_ASSERT (stream -> base .metrics .send_end_timestamp_ns == -1 );
738+ aws_high_res_clock_get_ticks ((uint64_t * )& stream -> base .metrics .send_end_timestamp_ns );
739+ stream -> base .metrics .sending_duration_ns =
740+ stream -> base .metrics .send_end_timestamp_ns - stream -> base .metrics .send_start_timestamp_ns ;
724741 }
725742
726743 if (s_h2_stream_has_outgoing_writes (stream )) {
@@ -798,6 +815,11 @@ int aws_h2_stream_encode_data_frame(
798815 */
799816 if (input_stream_complete && ends_stream ) {
800817 /* Done sending data. No more data will be sent. */
818+ AWS_ASSERT (stream -> base .metrics .send_end_timestamp_ns == -1 );
819+ aws_high_res_clock_get_ticks ((uint64_t * )& stream -> base .metrics .send_end_timestamp_ns );
820+ stream -> base .metrics .sending_duration_ns =
821+ stream -> base .metrics .send_end_timestamp_ns - stream -> base .metrics .send_start_timestamp_ns ;
822+
801823 if (stream -> thread_data .state == AWS_H2_STREAM_STATE_HALF_CLOSED_REMOTE ) {
802824 /* Both sides have sent END_STREAM */
803825 stream -> thread_data .state = AWS_H2_STREAM_STATE_CLOSED ;
@@ -841,6 +863,7 @@ struct aws_h2err aws_h2_stream_on_decoder_headers_begin(struct aws_h2_stream *st
841863 if (aws_h2err_failed (stream_err )) {
842864 return s_send_rst_and_close_stream (stream , stream_err );
843865 }
866+ aws_high_res_clock_get_ticks ((uint64_t * )& stream -> base .metrics .receive_start_timestamp_ns );
844867
845868 return AWS_H2ERR_SUCCESS ;
846869}
@@ -1150,6 +1173,13 @@ struct aws_h2err aws_h2_stream_on_decoder_end_stream(struct aws_h2_stream *strea
11501173 * an actual frame type. It's a flag on DATA or HEADERS frames, and we
11511174 * already checked the legality of those frames in their respective callbacks. */
11521175
1176+ AWS_ASSERT (stream -> base .metrics .receive_start_timestamp_ns != -1 );
1177+ AWS_ASSERT (stream -> base .metrics .receive_end_timestamp_ns == -1 );
1178+ aws_high_res_clock_get_ticks ((uint64_t * )& stream -> base .metrics .receive_end_timestamp_ns );
1179+ AWS_ASSERT (stream -> base .metrics .receive_end_timestamp_ns >= stream -> base .metrics .receive_start_timestamp_ns );
1180+ stream -> base .metrics .receiving_duration_ns =
1181+ stream -> base .metrics .receive_end_timestamp_ns - stream -> base .metrics .receive_start_timestamp_ns ;
1182+
11531183 if (stream -> thread_data .content_length_received ) {
11541184 if (stream -> base .request_method != AWS_HTTP_METHOD_HEAD &&
11551185 stream -> base .client_data -> response_status != AWS_HTTP_STATUS_CODE_304_NOT_MODIFIED ) {
0 commit comments