Skip to content

Commit

Permalink
quic: additional session stats
Browse files Browse the repository at this point in the history
  • Loading branch information
jasnell committed Dec 3, 2019
1 parent 7d5277f commit 57af916
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 11 deletions.
46 changes: 37 additions & 9 deletions lib/internal/quic/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,18 @@ const {
IDX_QUIC_SESSION_STATE_KEYLOG_ENABLED,
IDX_QUIC_SESSION_STATE_MAX_STREAMS_BIDI,
IDX_QUIC_SESSION_STATE_MAX_STREAMS_UNI,
IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT,
IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT,
IDX_QUIC_SESSION_STATS_CREATED_AT,
IDX_QUIC_SESSION_STATS_HANDSHAKE_START_AT,
IDX_QUIC_SESSION_STATS_BYTES_RECEIVED,
IDX_QUIC_SESSION_STATS_BYTES_SENT,
IDX_QUIC_SESSION_STATS_BIDI_STREAM_COUNT,
IDX_QUIC_SESSION_STATS_UNI_STREAM_COUNT,
IDX_QUIC_SESSION_STATS_STREAMS_IN_COUNT,
IDX_QUIC_SESSION_STATS_STREAMS_OUT_COUNT,
IDX_QUIC_SESSION_STATS_KEYUPDATE_COUNT,
IDX_QUIC_SESSION_STATS_MAX_BYTES_IN_FLIGHT,
ERR_INVALID_REMOTE_TRANSPORT_PARAMS,
ERR_INVALID_TLS_SESSION_TICKET,
NGTCP2_PATH_VALIDATION_RESULT_FAILURE,
Expand Down Expand Up @@ -1678,6 +1690,16 @@ class QuicSession extends EventEmitter {
return this.#socket ? this.#socket.address : {};
}

get maxDataLeft() {
return this[kHandle] ?
this[kHandle].state[IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT] : 0;
}

get bytesInFlight() {
return this[kHandle] ?
this[kHandle].state[IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT] : 0;
}

get authenticated() {
// Specifically check for null. Undefined means the check has not
// been performed yet, another other value other than null means
Expand Down Expand Up @@ -1753,6 +1775,7 @@ class QuicSession extends EventEmitter {
};
}


get socket() {
return this.#socket;
}
Expand Down Expand Up @@ -1805,50 +1828,55 @@ class QuicSession extends EventEmitter {
get duration() {
const now = process.hrtime.bigint();
const stats = this.#stats || this[kHandle].stats;
return now - stats[0];
return now - stats[IDX_QUIC_SESSION_STATS_CREATED_AT];
}

get handshakeDuration() {
const stats = this.#stats || this[kHandle].stats;
const end =
this.handshakeComplete ?
stats[4] : process.hrtime.bigint();
return end - stats[1];
return end - stats[IDX_QUIC_SESSION_STATS_HANDSHAKE_START_AT];
}

get bytesReceived() {
const stats = this.#stats || this[kHandle].stats;
return stats[8];
return stats[IDX_QUIC_SESSION_STATS_BYTES_RECEIVED];
}

get bytesSent() {
const stats = this.#stats || this[kHandle].stats;
return stats[9];
return stats[IDX_QUIC_SESSION_STATS_BYTES_SENT];
}

get bidiStreamCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[10];
return stats[IDX_QUIC_SESSION_STATS_BIDI_STREAM_COUNT];
}

get uniStreamCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[11];
return stats[IDX_QUIC_SESSION_STATS_UNI_STREAM_COUNT];
}

get maxInFlightBytes() {
const stats = this.#stats || this[kHandle].stats;
return stats[IDX_QUIC_SESSION_STATS_MAX_BYTES_IN_FLIGHT];
}

get peerInitiatedStreamCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[12];
return stats[IDX_QUIC_SESSION_STATS_STREAMS_IN_COUNT];
}

get selfInitiatedStreamCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[13];
return stats[IDX_QUIC_SESSION_STATS_STREAMS_OUT_COUNT];
}

get keyUpdateCount() {
const stats = this.#stats || this[kHandle].stats;
return stats[14];
return stats[IDX_QUIC_SESSION_STATS_KEYUPDATE_COUNT];
}

get minRTT() {
Expand Down
29 changes: 29 additions & 0 deletions src/node_quic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ void Initialize(Local<Object> target,
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATE_KEYLOG_ENABLED);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATE_MAX_STREAMS_BIDI);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATE_MAX_STREAMS_UNI);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT);
NODE_DEFINE_CONSTANT(constants, MAX_RETRYTOKEN_EXPIRATION);
NODE_DEFINE_CONSTANT(constants, MIN_RETRYTOKEN_EXPIRATION);
NODE_DEFINE_CONSTANT(constants, NGTCP2_MAX_CIDLEN);
Expand Down Expand Up @@ -183,6 +185,33 @@ void Initialize(Local<Object> target,
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_MAX_CRYPTO_BUFFER);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_CONFIG_COUNT);

NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_CREATED_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_HANDSHAKE_START_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_HANDSHAKE_SEND_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_HANDSHAKE_CONTINUE_AT);
NODE_DEFINE_CONSTANT(constants,
IDX_QUIC_SESSION_STATS_HANDSHAKE_COMPLETED_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_HANDSHAKE_ACKED_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_SENT_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_RECEIVED_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_CLOSING_AT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_BYTES_RECEIVED);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_BYTES_SENT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_BIDI_STREAM_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_UNI_STREAM_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_STREAMS_IN_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_STREAMS_OUT_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_KEYUPDATE_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_RETRY_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_LOSS_RETRANSMIT_COUNT);
NODE_DEFINE_CONSTANT(constants,
IDX_QUIC_SESSION_STATS_ACK_DELAY_RETRANSMIT_COUNT);
NODE_DEFINE_CONSTANT(constants,
IDX_QUIC_SESSION_STATS_PATH_VALIDATION_SUCCESS_COUNT);
NODE_DEFINE_CONSTANT(constants,
IDX_QUIC_SESSION_STATS_PATH_VALIDATION_FAILURE_COUNT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_MAX_BYTES_IN_FLIGHT);

NODE_DEFINE_CONSTANT(constants, IDX_HTTP3_QPACK_MAX_TABLE_CAPACITY);
NODE_DEFINE_CONSTANT(constants, IDX_HTTP3_QPACK_BLOCKED_STREAMS);
NODE_DEFINE_CONSTANT(constants, IDX_HTTP3_MAX_HEADER_LIST_SIZE);
Expand Down
22 changes: 20 additions & 2 deletions src/node_quic_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,8 @@ QuicSession::~QuicSession() {
" Streams Out Count: %" PRIu64 "\n"
" Remaining sendbuf_: %" PRIu64 "\n"
" Remaining handshake_: %" PRIu64 "\n"
" Remaining txbuf_: %" PRIu64 "\n",
" Remaining txbuf_: %" PRIu64 "\n"
" Max In Flight Bytes: %" PRIu64 "\n",
uv_hrtime() - session_stats_.created_at,
session_stats_.handshake_start_at,
session_stats_.handshake_completed_at,
Expand All @@ -1314,7 +1315,8 @@ QuicSession::~QuicSession() {
session_stats_.streams_out_count,
sendbuf_length,
handshake_length,
txbuf_length);
txbuf_length,
session_stats_.max_bytes_in_flight);

connection_.reset();

Expand Down Expand Up @@ -1824,6 +1826,9 @@ bool QuicSession::Receive(
// and HandleScope are both exited before continuing on with the
// function. This allows any nextTicks and queued tasks to be processed
// before we continue.
OnScopeLeave update_stats([&](){
UpdateDataStats();
});
Debug(this, "Processing received packet");
HandleScope handle_scope(env()->isolate());
InternalCallbackScope callback_scope(this);
Expand Down Expand Up @@ -2558,6 +2563,7 @@ bool QuicSession::WritePackets(const char* diagnostic_label) {
data.Realloc(nwrite);
remote_address_.Update(path.path.remote.addr, path.path.remote.addrlen);
sendbuf_.Push(std::move(data));
UpdateDataStats();
if (!SendPacket(diagnostic_label))
return false;
}
Expand Down Expand Up @@ -2711,6 +2717,7 @@ void QuicSession::InitServer(
connection_.reset(conn);

InitializeTLS(this);
UpdateDataStats();
UpdateIdleTimer();
}

Expand Down Expand Up @@ -2745,6 +2752,16 @@ void QuicSession::UpdateRecoveryStats() {
recovery_stats_.smoothed_rtt = static_cast<double>(stat->smoothed_rtt);
}

void QuicSession::UpdateDataStats() {
state_[IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT] =
static_cast<double>(ngtcp2_conn_get_max_data_left(Connection()));
size_t bytes_in_flight = ngtcp2_conn_get_bytes_in_flight(Connection());
state_[IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT] =
static_cast<double>(bytes_in_flight);
if (bytes_in_flight > session_stats_.max_bytes_in_flight)
session_stats_.max_bytes_in_flight = bytes_in_flight;
}

BaseObjectPtr<QuicSession> QuicSession::CreateClient(
QuicSocket* socket,
const struct sockaddr* addr,
Expand Down Expand Up @@ -2860,6 +2877,7 @@ bool QuicSession::InitClient(
}

UpdateIdleTimer();
UpdateDataStats();
return true;
}

Expand Down
34 changes: 34 additions & 0 deletions src/node_quic_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,42 @@ enum QuicSessionState : int {
IDX_QUIC_SESSION_STATE_MAX_STREAMS_BIDI,
IDX_QUIC_SESSION_STATE_MAX_STREAMS_UNI,

// Communicates the current maxinum number of bytes that
// the local endpoint can send in this connection
// (updated immediately after processing sent/received packets)
IDX_QUIC_SESSION_STATE_MAX_DATA_LEFT,

// Communicates the current total number of bytes in flight
IDX_QUIC_SESSION_STATE_BYTES_IN_FLIGHT,

// Just the number of session state enums for use when
// creating the AliasedBuffer.
IDX_QUIC_SESSION_STATE_COUNT
};

enum QuicSessionStatsIdx : int {
IDX_QUIC_SESSION_STATS_CREATED_AT,
IDX_QUIC_SESSION_STATS_HANDSHAKE_START_AT,
IDX_QUIC_SESSION_STATS_HANDSHAKE_SEND_AT,
IDX_QUIC_SESSION_STATS_HANDSHAKE_CONTINUE_AT,
IDX_QUIC_SESSION_STATS_HANDSHAKE_COMPLETED_AT,
IDX_QUIC_SESSION_STATS_HANDSHAKE_ACKED_AT,
IDX_QUIC_SESSION_STATS_SENT_AT,
IDX_QUIC_SESSION_STATS_RECEIVED_AT,
IDX_QUIC_SESSION_STATS_CLOSING_AT,
IDX_QUIC_SESSION_STATS_BYTES_RECEIVED,
IDX_QUIC_SESSION_STATS_BYTES_SENT,
IDX_QUIC_SESSION_STATS_BIDI_STREAM_COUNT,
IDX_QUIC_SESSION_STATS_UNI_STREAM_COUNT,
IDX_QUIC_SESSION_STATS_STREAMS_IN_COUNT,
IDX_QUIC_SESSION_STATS_STREAMS_OUT_COUNT,
IDX_QUIC_SESSION_STATS_KEYUPDATE_COUNT,
IDX_QUIC_SESSION_STATS_RETRY_COUNT,
IDX_QUIC_SESSION_STATS_LOSS_RETRANSMIT_COUNT,
IDX_QUIC_SESSION_STATS_ACK_DELAY_RETRANSMIT_COUNT,
IDX_QUIC_SESSION_STATS_PATH_VALIDATION_SUCCESS_COUNT,IDX_QUIC_SESSION_STATS_PATH_VALIDATION_FAILURE_COUNT,IDX_QUIC_SESSION_STATS_MAX_BYTES_IN_FLIGHT
};

class QuicSessionListener {
public:
virtual ~QuicSessionListener();
Expand Down Expand Up @@ -948,6 +979,7 @@ class QuicSession : public AsyncWrap,
uint64_t app_error_code);
bool WritePackets(const char* diagnostic_label = nullptr);
void UpdateRecoveryStats();
void UpdateDataStats();

void VersionNegotiation(
const ngtcp2_pkt_hd* hd,
Expand Down Expand Up @@ -1296,6 +1328,8 @@ class QuicSession : public AsyncWrap,
uint64_t path_validation_success_count;
// The total number of failed path validations
uint64_t path_validation_failure_count;
// The max number of in flight bytes recorded
uint64_t max_bytes_in_flight;
};
session_stats session_stats_{};

Expand Down

0 comments on commit 57af916

Please sign in to comment.