| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 9404573 commit 3cd2054
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3022,23 +3022,35 @@ The `name` property of the `PerformanceEntry` will be equal to either | |||
| 3022 | 3022 | If `name` is equal to `Http2Stream`, the `PerformanceEntry` will contain the | |
| 3023 | 3023 | following additional properties: | |
| 3024 | 3024 | ||
| 3025 | + * `bytesRead` {number} The number of DATA frame bytes received for this | ||
| 3026 | + `Http2Stream`. | ||
| 3027 | + * `bytesWritten` {number} The number of DATA frame bytes sent for this | ||
| 3028 | + `Http2Stream`. | ||
| 3029 | + * `id` {number} The identifier of the associated `Http2Stream` | ||
| 3025 | 3030 | * `timeToFirstByte` {number} The number of milliseconds elapsed between the | |
| 3026 | 3031 | `PerformanceEntry` `startTime` and the reception of the first `DATA` frame. | |
| 3032 | + * `timeToFirstByteSent` {number} The number of milliseconds elapsed between | ||
| 3033 | + the `PerformanceEntry` `startTime` and sending of the first `DATA` frame. | ||
| 3027 | 3034 | * `timeToFirstHeader` {number} The number of milliseconds elapsed between the | |
| 3028 | 3035 | `PerformanceEntry` `startTime` and the reception of the first header. | |
| 3029 | 3036 | ||
| 3030 | 3037 | If `name` is equal to `Http2Session`, the `PerformanceEntry` will contain the | |
| 3031 | 3038 | following additional properties: | |
| 3032 | 3039 | ||
| 3040 | + * `bytesRead` {number} The number of bytes received for this `Http2Session`. | ||
| 3041 | + * `bytesWritten` {number} The number of bytes sent for this `Http2Session`. | ||
| 3042 | + * `framesReceived` {number} The number of HTTP/2 frames received by the | ||
| 3043 | + `Http2Session`. | ||
| 3044 | + * `framesSent` {number} The number of HTTP/2 frames sent by the `Http2Session`. | ||
| 3045 | + * `maxConcurrentStreams` {number} The maximum number of streams concurrently | ||
| 3046 | + open during the lifetime of the `Http2Session`. | ||
| 3033 | 3047 | * `pingRTT` {number} The number of milliseconds elapsed since the transmission | |
| 3034 | 3048 | of a `PING` frame and the reception of its acknowledgment. Only present if | |
| 3035 | 3049 | a `PING` frame has been sent on the `Http2Session`. | |
| 3036 | - * `streamCount` {number} The number of `Http2Stream` instances processed by | ||
| 3037 | - the `Http2Session`. | ||
| 3038 | 3050 | * `streamAverageDuration` {number} The average duration (in milliseconds) for | |
| 3039 | 3051 | all `Http2Stream` instances. | |
| 3040 | - * `framesReceived` {number} The number of HTTP/2 frames received by the | ||
| 3041 | - `Http2Session`. | ||
| 3052 | + * `streamCount` {number} The number of `Http2Stream` instances processed by | ||
| 3053 | + the `Http2Session`. | ||
| 3042 | 3054 | * `type` {string} Either `'server'` or `'client'` to identify the type of | |
| 3043 | 3055 | `Http2Session`. | |
| 3044 | 3056 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -66,6 +66,70 @@ const observerableTypes = [ | |||
| 66 | 66 | 'http2' | |
| 67 | 67 | ]; | |
| 68 | 68 | ||
| 69 | + const IDX_STREAM_STATS_ID = 0; | ||
| 70 | + const IDX_STREAM_STATS_TIMETOFIRSTBYTE = 1; | ||
| 71 | + const IDX_STREAM_STATS_TIMETOFIRSTHEADER = 2; | ||
| 72 | + const IDX_STREAM_STATS_TIMETOFIRSTBYTESENT = 3; | ||
| 73 | + const IDX_STREAM_STATS_SENTBYTES = 4; | ||
| 74 | + const IDX_STREAM_STATS_RECEIVEDBYTES = 5; | ||
| 75 | + | ||
| 76 | + const IDX_SESSION_STATS_TYPE = 0; | ||
| 77 | + const IDX_SESSION_STATS_PINGRTT = 1; | ||
| 78 | + const IDX_SESSION_STATS_FRAMESRECEIVED = 2; | ||
| 79 | + const IDX_SESSION_STATS_FRAMESSENT = 3; | ||
| 80 | + const IDX_SESSION_STATS_STREAMCOUNT = 4; | ||
| 81 | + const IDX_SESSION_STATS_STREAMAVERAGEDURATION = 5; | ||
| 82 | + const IDX_SESSION_STATS_DATA_SENT = 6; | ||
| 83 | + const IDX_SESSION_STATS_DATA_RECEIVED = 7; | ||
| 84 | + const IDX_SESSION_STATS_MAX_CONCURRENT_STREAMS = 8; | ||
| 85 | + | ||
| 86 | + let sessionStats; | ||
| 87 | + let streamStats; | ||
| 88 | + | ||
| 89 | + function collectHttp2Stats(entry) { | ||
| 90 | + switch (entry.name) { | ||
| 91 | + case 'Http2Stream': | ||
| 92 | + if (streamStats === undefined) | ||
| 93 | + streamStats = process.binding('http2').streamStats; | ||
| 94 | + entry.id = | ||
| 95 | + streamStats[IDX_STREAM_STATS_ID] >>> 0; | ||
| 96 | + entry.timeToFirstByte = | ||
| 97 | + streamStats[IDX_STREAM_STATS_TIMETOFIRSTBYTE]; | ||
| 98 | + entry.timeToFirstHeader = | ||
| 99 | + streamStats[IDX_STREAM_STATS_TIMETOFIRSTHEADER]; | ||
| 100 | + entry.timeToFirstByteSent = | ||
| 101 | + streamStats[IDX_STREAM_STATS_TIMETOFIRSTBYTESENT]; | ||
| 102 | + entry.bytesWritten = | ||
| 103 | + streamStats[IDX_STREAM_STATS_SENTBYTES]; | ||
| 104 | + entry.bytesRead = | ||
| 105 | + streamStats[IDX_STREAM_STATS_RECEIVEDBYTES]; | ||
| 106 | + break; | ||
| 107 | + case 'Http2Session': | ||
| 108 | + if (sessionStats === undefined) | ||
| 109 | + sessionStats = process.binding('http2').sessionStats; | ||
| 110 | + entry.type = | ||
| 111 | + sessionStats[IDX_SESSION_STATS_TYPE] >>> 0 === 0 ? 'server' : 'client'; | ||
| 112 | + entry.pingRTT = | ||
| 113 | + sessionStats[IDX_SESSION_STATS_PINGRTT]; | ||
| 114 | + entry.framesReceived = | ||
| 115 | + sessionStats[IDX_SESSION_STATS_FRAMESRECEIVED]; | ||
| 116 | + entry.framesSent = | ||
| 117 | + sessionStats[IDX_SESSION_STATS_FRAMESSENT]; | ||
| 118 | + entry.streamCount = | ||
| 119 | + sessionStats[IDX_SESSION_STATS_STREAMCOUNT]; | ||
| 120 | + entry.streamAverageDuration = | ||
| 121 | + sessionStats[IDX_SESSION_STATS_STREAMAVERAGEDURATION]; | ||
| 122 | + entry.bytesWritten = | ||
| 123 | + sessionStats[IDX_SESSION_STATS_DATA_SENT]; | ||
| 124 | + entry.bytesRead = | ||
| 125 | + sessionStats[IDX_SESSION_STATS_DATA_RECEIVED]; | ||
| 126 | + entry.maxConcurrentStreams = | ||
| 127 | + sessionStats[IDX_SESSION_STATS_MAX_CONCURRENT_STREAMS]; | ||
| 128 | + break; | ||
| 129 | + } | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + | ||
| 69 | 133 | let errors; | |
| 70 | 134 | function lazyErrors() { | |
| 71 | 135 | if (errors === undefined) | |
@@ -467,6 +531,10 @@ function doNotify() { | |||
| 467 | 531 | // Set up the callback used to receive PerformanceObserver notifications | |
| 468 | 532 | function observersCallback(entry) { | |
| 469 | 533 | const type = mapTypes(entry.entryType); | |
| 534 | + | ||
| 535 | + if (type === NODE_PERFORMANCE_ENTRY_TYPE_HTTP2) | ||
| 536 | + collectHttp2Stats(entry); | ||
| 537 | + | ||
| 470 | 538 | performance[kInsertEntry](entry); | |
| 471 | 539 | const list = getObserversList(type); | |
| 472 | 540 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -471,6 +471,8 @@ Http2Session::Callbacks::Callbacks(bool kHasGetPaddingCallback) { | |||
| 471 | 471 | callbacks, OnSendData); | |
| 472 | 472 | nghttp2_session_callbacks_set_on_invalid_frame_recv_callback( | |
| 473 | 473 | callbacks, OnInvalidFrame); | |
| 474 | + nghttp2_session_callbacks_set_on_frame_send_callback( | ||
| 475 | + callbacks, OnFrameSent); | ||
| 474 | 476 | ||
| 475 | 477 | if (kHasGetPaddingCallback) { | |
| 476 | 478 | nghttp2_session_callbacks_set_select_padding_callback( | |
@@ -560,28 +562,35 @@ inline void Http2Stream::EmitStatistics() { | |||
| 560 | 562 | if (!HasHttp2Observer(env())) | |
| 561 | 563 | return; | |
| 562 | 564 | Http2StreamPerformanceEntry* entry = | |
| 563 | - new Http2StreamPerformanceEntry(env(), statistics_); | ||
| 565 | + new Http2StreamPerformanceEntry(env(), id_, statistics_); | ||
| 564 | 566 | env()->SetImmediate([](Environment* env, void* data) { | |
| 565 | - Local<Context> context = env->context(); | ||
| 566 | 567 | Http2StreamPerformanceEntry* entry = | |
| 567 | 568 | static_cast<Http2StreamPerformanceEntry*>(data); | |
| 568 | 569 | if (HasHttp2Observer(env)) { | |
| 569 | - Local<Object> obj = entry->ToObject(); | ||
| 570 | - v8::PropertyAttribute attr = | ||
| 571 | - static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete); | ||
| 572 | - obj->DefineOwnProperty( | ||
| 573 | - context, | ||
| 574 | - FIXED_ONE_BYTE_STRING(env->isolate(), "timeToFirstByte"), | ||
| 575 | - Number::New(env->isolate(), | ||
| 576 | - (entry->first_byte() - entry->startTimeNano()) / 1e6), | ||
| 577 | - attr).FromJust(); | ||
| 578 | - obj->DefineOwnProperty( | ||
| 579 | - context, | ||
| 580 | - FIXED_ONE_BYTE_STRING(env->isolate(), "timeToFirstHeader"), | ||
| 581 | - Number::New(env->isolate(), | ||
| 582 | - (entry->first_header() - entry->startTimeNano()) / 1e6), | ||
| 583 | - attr).FromJust(); | ||
| 584 | - entry->Notify(obj); | ||
| 570 | + AliasedBuffer<double, v8::Float64Array>& buffer = | ||
| 571 | + env->http2_state()->stream_stats_buffer; | ||
| 572 | + buffer[IDX_STREAM_STATS_ID] = entry->id(); | ||
| 573 | + if (entry->first_byte() != 0) { | ||
| 574 | + buffer[IDX_STREAM_STATS_TIMETOFIRSTBYTE] = | ||
| 575 | + (entry->first_byte() - entry->startTimeNano()) / 1e6; | ||
| 576 | + } else { | ||
| 577 | + buffer[IDX_STREAM_STATS_TIMETOFIRSTBYTE] = 0; | ||
| 578 | + } | ||
| 579 | + if (entry->first_header() != 0) { | ||
| 580 | + buffer[IDX_STREAM_STATS_TIMETOFIRSTHEADER] = | ||
| 581 | + (entry->first_header() - entry->startTimeNano()) / 1e6; | ||
| 582 | + } else { | ||
| 583 | + buffer[IDX_STREAM_STATS_TIMETOFIRSTHEADER] = 0; | ||
| 584 | + } | ||
| 585 | + if (entry->first_byte_sent() != 0) { | ||
| 586 | + buffer[IDX_STREAM_STATS_TIMETOFIRSTBYTESENT] = | ||
| 587 | + (entry->first_byte_sent() - entry->startTimeNano()) / 1e6; | ||
| 588 | + } else { | ||
| 589 | + buffer[IDX_STREAM_STATS_TIMETOFIRSTBYTESENT] = 0; | ||
| 590 | + } | ||
| 591 | + buffer[IDX_STREAM_STATS_SENTBYTES] = entry->sent_bytes(); | ||
| 592 | + buffer[IDX_STREAM_STATS_RECEIVEDBYTES] = entry->received_bytes(); | ||
| 593 | + entry->Notify(entry->ToObject()); | ||
| 585 | 594 | } | |
| 586 | 595 | delete entry; | |
| 587 | 596 | }, static_cast<void*>(entry)); | |
@@ -591,45 +600,25 @@ inline void Http2Session::EmitStatistics() { | |||
| 591 | 600 | if (!HasHttp2Observer(env())) | |
| 592 | 601 | return; | |
| 593 | 602 | Http2SessionPerformanceEntry* entry = | |
| 594 | - new Http2SessionPerformanceEntry(env(), statistics_, TypeName()); | ||
| 603 | + new Http2SessionPerformanceEntry(env(), statistics_, session_type_); | ||
| 595 | 604 | env()->SetImmediate([](Environment* env, void* data) { | |
| 596 | - Local<Context> context = env->context(); | ||
| 597 | 605 | Http2SessionPerformanceEntry* entry = | |
| 598 | 606 | static_cast<Http2SessionPerformanceEntry*>(data); | |
| 599 | 607 | if (HasHttp2Observer(env)) { | |
| 600 | - Local<Object> obj = entry->ToObject(); | ||
| 601 | - v8::PropertyAttribute attr = | ||
| 602 | - static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete); | ||
| 603 | - obj->DefineOwnProperty( | ||
| 604 | - context, | ||
| 605 | - FIXED_ONE_BYTE_STRING(env->isolate(), "type"), | ||
| 606 | - String::NewFromUtf8(env->isolate(), | ||
| 607 | - entry->typeName(), | ||
| 608 | - v8::NewStringType::kInternalized) | ||
| 609 | - .ToLocalChecked(), attr).FromJust(); | ||
| 610 | - if (entry->ping_rtt() != 0) { | ||
| 611 | - obj->DefineOwnProperty( | ||
| 612 | - context, | ||
| 613 | - FIXED_ONE_BYTE_STRING(env->isolate(), "pingRTT"), | ||
| 614 | - Number::New(env->isolate(), entry->ping_rtt() / 1e6), | ||
| 615 | - attr).FromJust(); | ||
| 616 | - } | ||
| 617 | - obj->DefineOwnProperty( | ||
| 618 | - context, | ||
| 619 | - FIXED_ONE_BYTE_STRING(env->isolate(), "framesReceived"), | ||
| 620 | - Integer::NewFromUnsigned(env->isolate(), entry->frame_count()), | ||
| 621 | - attr).FromJust(); | ||
| 622 | - obj->DefineOwnProperty( | ||
| 623 | - context, | ||
| 624 | - FIXED_ONE_BYTE_STRING(env->isolate(), "streamCount"), | ||
| 625 | - Integer::New(env->isolate(), entry->stream_count()), | ||
| 626 | - attr).FromJust(); | ||
| 627 | - obj->DefineOwnProperty( | ||
| 628 | - context, | ||
| 629 | - FIXED_ONE_BYTE_STRING(env->isolate(), "streamAverageDuration"), | ||
| 630 | - Number::New(env->isolate(), entry->stream_average_duration()), | ||
| 631 | - attr).FromJust(); | ||
| 632 | - entry->Notify(obj); | ||
| 608 | + AliasedBuffer<double, v8::Float64Array>& buffer = | ||
| 609 | + env->http2_state()->session_stats_buffer; | ||
| 610 | + buffer[IDX_SESSION_STATS_TYPE] = entry->type(); | ||
| 611 | + buffer[IDX_SESSION_STATS_PINGRTT] = entry->ping_rtt() / 1e6; | ||
| 612 | + buffer[IDX_SESSION_STATS_FRAMESRECEIVED] = entry->frame_count(); | ||
| 613 | + buffer[IDX_SESSION_STATS_FRAMESSENT] = entry->frame_sent(); | ||
| 614 | + buffer[IDX_SESSION_STATS_STREAMCOUNT] = entry->stream_count(); | ||
| 615 | + buffer[IDX_SESSION_STATS_STREAMAVERAGEDURATION] = | ||
| 616 | + entry->stream_average_duration(); | ||
| 617 | + buffer[IDX_SESSION_STATS_DATA_SENT] = entry->data_sent(); | ||
| 618 | + buffer[IDX_SESSION_STATS_DATA_RECEIVED] = entry->data_received(); | ||
| 619 | + buffer[IDX_SESSION_STATS_MAX_CONCURRENT_STREAMS] = | ||
| 620 | + entry->max_concurrent_streams(); | ||
| 621 | + entry->Notify(entry->ToObject()); | ||
| 633 | 622 | } | |
| 634 | 623 | delete entry; | |
| 635 | 624 | }, static_cast<void*>(entry)); | |
@@ -695,6 +684,9 @@ inline bool Http2Session::CanAddStream() { | |||
| 695 | 684 | inline void Http2Session::AddStream(Http2Stream* stream) { | |
| 696 | 685 | CHECK_GE(++statistics_.stream_count, 0); | |
| 697 | 686 | streams_[stream->id()] = stream; | |
| 687 | + size_t size = streams_.size(); | ||
| 688 | + if (size > statistics_.max_concurrent_streams) | ||
| 689 | + statistics_.max_concurrent_streams = size; | ||
| 698 | 690 | IncrementCurrentSessionMemory(stream->self_size()); | |
| 699 | 691 | } | |
| 700 | 692 | ||
@@ -963,6 +955,14 @@ inline int Http2Session::OnFrameNotSent(nghttp2_session* handle, | |||
| 963 | 955 | return 0; | |
| 964 | 956 | } | |
| 965 | 957 | ||
| 958 | + inline int Http2Session::OnFrameSent(nghttp2_session* handle, | ||
| 959 | + const nghttp2_frame* frame, | ||
| 960 | + void* user_data) { | ||
| 961 | + Http2Session* session = static_cast<Http2Session*>(user_data); | ||
| 962 | + session->statistics_.frame_sent += 1; | ||
| 963 | + return 0; | ||
| 964 | + } | ||
| 965 | + | ||
| 966 | 966 | // Called by nghttp2 when a stream closes. | |
| 967 | 967 | inline int Http2Session::OnStreamClose(nghttp2_session* handle, | |
| 968 | 968 | int32_t id, | |
@@ -1040,6 +1040,7 @@ inline int Http2Session::OnDataChunkReceived(nghttp2_session* handle, | |||
| 1040 | 1040 | // If the stream has been destroyed, ignore this chunk | |
| 1041 | 1041 | if (stream->IsDestroyed()) | |
| 1042 | 1042 | return 0; | |
| 1043 | + stream->statistics_.received_bytes += len; | ||
| 1043 | 1044 | stream->AddChunk(data, len); | |
| 1044 | 1045 | } | |
| 1045 | 1046 | return 0; | |
@@ -1494,6 +1495,7 @@ void Http2Session::SendPendingData() { | |||
| 1494 | 1495 | size_t offset = 0; | |
| 1495 | 1496 | size_t i = 0; | |
| 1496 | 1497 | for (const nghttp2_stream_write& write : outgoing_buffers_) { | |
| 1498 | + statistics_.data_sent += write.buf.len; | ||
| 1497 | 1499 | if (write.buf.base == nullptr) { | |
| 1498 | 1500 | bufs[i++] = uv_buf_init( | |
| 1499 | 1501 | reinterpret_cast<char*>(outgoing_storage_.data() + offset), | |
@@ -1643,6 +1645,7 @@ void Http2Session::OnStreamReadImpl(ssize_t nread, | |||
| 1643 | 1645 | if (bufs->len > 0) { | |
| 1644 | 1646 | // Only pass data on if nread > 0 | |
| 1645 | 1647 | uv_buf_t buf[] { uv_buf_init((*bufs).base, nread) }; | |
| 1648 | + session->statistics_.data_received += nread; | ||
| 1646 | 1649 | ssize_t ret = session->Write(buf, 1); | |
| 1647 | 1650 | ||
| 1648 | 1651 | // Note: if ssize_t is not defined (e.g. on Win32), nghttp2 will typedef | |
@@ -2142,6 +2145,8 @@ ssize_t Http2Stream::Provider::FD::OnRead(nghttp2_session* handle, | |||
| 2142 | 2145 | void* user_data) { | |
| 2143 | 2146 | Http2Session* session = static_cast<Http2Session*>(user_data); | |
| 2144 | 2147 | Http2Stream* stream = session->FindStream(id); | |
| 2148 | + if (stream->statistics_.first_byte_sent == 0) | ||
| 2149 | + stream->statistics_.first_byte_sent = uv_hrtime(); | ||
| 2145 | 2150 | ||
| 2146 | 2151 | DEBUG_HTTP2SESSION2(session, "reading outbound file data for stream %d", id); | |
| 2147 | 2152 | CHECK_EQ(id, stream->id()); | |
@@ -2192,6 +2197,7 @@ ssize_t Http2Stream::Provider::FD::OnRead(nghttp2_session* handle, | |||
| 2192 | 2197 | return NGHTTP2_ERR_CALLBACK_FAILURE; | |
| 2193 | 2198 | } | |
| 2194 | 2199 | ||
| 2200 | + stream->statistics_.sent_bytes += numchars; | ||
| 2195 | 2201 | return numchars; | |
| 2196 | 2202 | } | |
| 2197 | 2203 | ||
@@ -2217,6 +2223,8 @@ ssize_t Http2Stream::Provider::Stream::OnRead(nghttp2_session* handle, | |||
| 2217 | 2223 | Http2Session* session = static_cast<Http2Session*>(user_data); | |
| 2218 | 2224 | DEBUG_HTTP2SESSION2(session, "reading outbound data for stream %d", id); | |
| 2219 | 2225 | Http2Stream* stream = GetStream(session, id, source); | |
| 2226 | + if (stream->statistics_.first_byte_sent == 0) | ||
| 2227 | + stream->statistics_.first_byte_sent = uv_hrtime(); | ||
| 2220 | 2228 | CHECK_EQ(id, stream->id()); | |
| 2221 | 2229 | ||
| 2222 | 2230 | size_t amount = 0; // amount of data being sent in this data frame. | |
@@ -2250,6 +2258,8 @@ ssize_t Http2Stream::Provider::Stream::OnRead(nghttp2_session* handle, | |||
| 2250 | 2258 | if (session->IsDestroyed()) | |
| 2251 | 2259 | return NGHTTP2_ERR_CALLBACK_FAILURE; | |
| 2252 | 2260 | } | |
| 2261 | + | ||
| 2262 | + stream->statistics_.sent_bytes += amount; | ||
| 2253 | 2263 | return amount; | |
| 2254 | 2264 | } | |
| 2255 | 2265 | ||
@@ -2863,6 +2873,10 @@ void Initialize(Local<Object> target, | |||
| 2863 | 2873 | "settingsBuffer", state->settings_buffer.GetJSArray()); | |
| 2864 | 2874 | SET_STATE_TYPEDARRAY( | |
| 2865 | 2875 | "optionsBuffer", state->options_buffer.GetJSArray()); | |
| 2876 | + SET_STATE_TYPEDARRAY( | ||
| 2877 | + "streamStats", state->stream_stats_buffer.GetJSArray()); | ||
| 2878 | + SET_STATE_TYPEDARRAY( | ||
| 2879 | + "sessionStats", state->session_stats_buffer.GetJSArray()); | ||
| 2866 | 2880 | #undef SET_STATE_TYPEDARRAY | |
| 2867 | 2881 | ||
| 2868 | 2882 | env->set_http2_state(std::move(state)); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments