diff --git a/src/quic/node_quic_session.cc b/src/quic/node_quic_session.cc index a8a00a29aa..64b2365805 100644 --- a/src/quic/node_quic_session.cc +++ b/src/quic/node_quic_session.cc @@ -1347,9 +1347,6 @@ QuicSession::QuicSession( QuicSession::~QuicSession() { CHECK(!Ngtcp2CallbackScope::InNgtcp2CallbackScope(this)); - StatsDebug stats_debug(this); - Debug(this, "Destroyed. %s", stats_debug.ToString().c_str()); - crypto_context_->Cancel(); connection_.reset(); @@ -1359,18 +1356,11 @@ QuicSession::~QuicSession() { RemoveListener(listener_); } -std::string QuicSession::StatsDebug::ToString() { -#define V(_, name, label) \ - " "## label + ": " + \ - std::to_string(session_->GetStat(&QuicSessionStats::name)) + "\n" - - std::string out = "Statistics:\n"; - out += " Duration: " + - std::to_string(uv_hrtime() - - session_->GetStat(&QuicSessionStats::created_at)) + "\n" + - SESSION_STATS(V); - return out; - +void StatsBase::StatsDebug::ToString( + StatsBase::AddField add_field) const { +#define V(_n, name, label) \ + add_field(label, ptr->GetStat(&QuicSessionStats::name)); + SESSION_STATS(V) #undef V } diff --git a/src/quic/node_quic_session.h b/src/quic/node_quic_session.h index 91c510968e..5438d77757 100644 --- a/src/quic/node_quic_session.h +++ b/src/quic/node_quic_session.h @@ -613,7 +613,7 @@ class QuicApplication : public MemoryRetainer { // a QuicSession object. class QuicSession : public AsyncWrap, public mem::NgLibMemoryManager, - public StatsBase { + public StatsBase { public: // The default preferred address strategy is to ignore it static void IgnorePreferredAddressStrategy( @@ -1423,15 +1423,6 @@ class QuicSession : public AsyncWrap, static const ngtcp2_conn_callbacks callbacks[2]; - class StatsDebug { - public: - StatsDebug(QuicSession* session) : session_(session) {} - std::string ToString(); - private: - QuicSession* session_; - }; - - friend class QuicCryptoContext; friend class QuicSessionListener; friend class JSQuicSessionListener; diff --git a/src/quic/node_quic_socket.cc b/src/quic/node_quic_socket.cc index ae20d31c01..dab640b818 100644 --- a/src/quic/node_quic_socket.cc +++ b/src/quic/node_quic_socket.cc @@ -285,26 +285,17 @@ QuicSocket::QuicSocket( QuicSocket::~QuicSocket() { uint64_t now = uv_hrtime(); - StatsDebug stats_debug(this); - Debug(this, "Destroyed. %s", stats_debug.ToString().c_str()); QuicSocketListener* listener = listener_; listener_->OnDestroy(); if (listener == listener_) RemoveListener(listener_); } -std::string QuicSocket::StatsDebug::ToString() { -#define V(_, name, label) \ - " "## label + ": " + \ - std::to_string(socket_->GetStat(&QuicSocketStats::name)) + "\n" - - std::string out = "Statistics:\n"; - out += " Duration: " + - std::to_string(uv_hrtime() - - socket_->GetStat(&QuicSocketStats::created_at)) + "\n" + - SOCKET_STATS(V); - return out; - +void StatsBase::StatsDebug::ToString( + StatsBase::AddField add_field) const { +#define V(_n, name, label) \ + add_field(label, ptr->GetStat(&QuicSocketStats::name)); + SOCKET_STATS(V) #undef V } diff --git a/src/quic/node_quic_socket.h b/src/quic/node_quic_socket.h index 9720030db6..d19ed14edb 100644 --- a/src/quic/node_quic_socket.h +++ b/src/quic/node_quic_socket.h @@ -244,7 +244,7 @@ class QuicEndpoint : public BaseObject, class QuicSocket : public AsyncWrap, public QuicEndpointListener, public mem::NgLibMemoryManager, - public StatsBase { + public StatsBase { public: static void Initialize( Environment* env, @@ -531,14 +531,6 @@ class QuicSocket : public AsyncWrap, SendWrap* last_created_send_wrap_ = nullptr; - class StatsDebug { - public: - StatsDebug(QuicSocket* socket) : socket_(socket) {} - std::string ToString(); - private: - QuicSocket* socket_; - }; - friend class QuicSocketListener; }; diff --git a/src/quic/node_quic_stream-inl.h b/src/quic/node_quic_stream-inl.h index 1f5d68eba5..6130834b25 100644 --- a/src/quic/node_quic_stream-inl.h +++ b/src/quic/node_quic_stream-inl.h @@ -148,7 +148,7 @@ void QuicStream::Unschedule() { stream_queue_.Remove(); } -std::string QuicHeader::ToString() { +std::string QuicHeader::ToString() const { return name() + " = " + value(); } diff --git a/src/quic/node_quic_stream.cc b/src/quic/node_quic_stream.cc index aff7484cfc..d7c33a8a7c 100644 --- a/src/quic/node_quic_stream.cc +++ b/src/quic/node_quic_stream.cc @@ -55,23 +55,13 @@ QuicStream::QuicStream( IncrementStat(&QuicStreamStats::max_offset, params.initial_max_data); } -QuicStream::~QuicStream() { - StatsDebug stats_debug(this); - Debug(this, "Destroyed. %s", stats_debug.ToString().c_str()); -} - -std::string QuicStream::StatsDebug::ToString() { -#define V(_, name, label) \ - " "## label + ": " + \ - std::to_string(stream_->GetStat(&QuicStreamStats::name)) + "\n" - - std::string out = "Statistics:\n"; - out += " Duration: " + - std::to_string(uv_hrtime() - - stream_->GetStat(&QuicStreamStats::created_at)) + "\n" + - STREAM_STATS(V); - return out; +QuicStream::~QuicStream() {} +void StatsBase::StatsDebug::ToString( + StatsBase::AddField add_field) const { +#define V(_n, name, label) \ + add_field(label, ptr->GetStat(&QuicStreamStats::name)); + STREAM_STATS(V) #undef V } diff --git a/src/quic/node_quic_stream.h b/src/quic/node_quic_stream.h index 47e0f078d6..76d3ca553a 100644 --- a/src/quic/node_quic_stream.h +++ b/src/quic/node_quic_stream.h @@ -72,8 +72,7 @@ struct QuicStreamStats { // per stream must create a specialization of the Header class. class QuicHeader : public MemoryRetainer { public: - QuicHeader() {} - + QuicHeader() = default; virtual ~QuicHeader() {} virtual v8::MaybeLocal GetName(QuicApplication* app) const = 0; virtual v8::MaybeLocal GetValue(QuicApplication* app) const = 0; @@ -84,7 +83,7 @@ class QuicHeader : public MemoryRetainer { // (including the name and value) virtual size_t length() const = 0; - inline std::string ToString(); + inline std::string ToString() const; }; enum QuicStreamStates : uint32_t { @@ -198,7 +197,7 @@ enum QuicStreamOrigin { class QuicStream : public AsyncWrap, public bob::SourceImpl, public StreamBase, - public StatsBase { + public StatsBase { public: static void Initialize( Environment* env, @@ -381,14 +380,6 @@ class QuicStream : public AsyncWrap, ListNode stream_queue_; - class StatsDebug { - public: - StatsDebug(QuicStream* stream) : stream_(stream) {} - std::string ToString(); - private: - QuicStream* stream_; - }; - public: // Linked List of QuicStream objects using Queue = ListHead; diff --git a/src/quic/node_quic_util-inl.h b/src/quic/node_quic_util-inl.h index f4a6f2d527..692769837a 100644 --- a/src/quic/node_quic_util-inl.h +++ b/src/quic/node_quic_util-inl.h @@ -1,6 +1,7 @@ #ifndef SRC_QUIC_NODE_QUIC_UTIL_INL_H_ #define SRC_QUIC_NODE_QUIC_UTIL_INL_H_ +#include "debug_utils.h" #include "node_internals.h" #include "node_quic_util.h" #include "memory_tracker-inl.h" @@ -317,8 +318,8 @@ bool StatelessResetToken::Compare::operator()( NGTCP2_STATELESS_RESET_TOKENLEN) == 0; } -template -StatsBase::StatsBase( +template +StatsBase::StatsBase( Environment* env, v8::Local wrap, int options) @@ -367,29 +368,29 @@ StatsBase::StatsBase( } } -template -void StatsBase::IncrementStat(uint64_t T::*member, uint64_t amount) { +template +void StatsBase::IncrementStat(uint64_t T::*member, uint64_t amount) { static constexpr uint64_t kMax = std::numeric_limits::max(); stats_.*member += std::min(amount, kMax - stats_.*member); } -template -void StatsBase::SetStat(uint64_t T::*member, uint64_t value) { +template +void StatsBase::SetStat(uint64_t T::*member, uint64_t value) { stats_.*member = value; } -template -void StatsBase::RecordTimestamp(uint64_t T::*member) { +template +void StatsBase::RecordTimestamp(uint64_t T::*member) { stats_.*member = uv_hrtime(); } -template -uint64_t StatsBase::GetStat(uint64_t T::*member) const { +template +uint64_t StatsBase::GetStat(uint64_t T::*member) const { return stats_.*member; } -template -inline void StatsBase::RecordRate(uint64_t T::*member) { +template +inline void StatsBase::RecordRate(uint64_t T::*member) { CHECK(rate_); uint64_t received_at = GetStat(member); @@ -399,14 +400,14 @@ inline void StatsBase::RecordRate(uint64_t T::*member) { SetStat(member, now); } -template -inline void StatsBase::RecordSize(uint64_t val) { +template +inline void StatsBase::RecordSize(uint64_t val) { CHECK(size_); size_->Record(val); } -template -inline void StatsBase::RecordAck(uint64_t T::*member) { +template +inline void StatsBase::RecordAck(uint64_t T::*member) { CHECK(ack_); uint64_t acked_at = GetStat(member); uint64_t now = uv_hrtime(); @@ -415,14 +416,35 @@ inline void StatsBase::RecordAck(uint64_t T::*member) { SetStat(member, now); } -template -void StatsBase::StatsMemoryInfo(MemoryTracker* tracker) const { +template +void StatsBase::StatsMemoryInfo(MemoryTracker* tracker) const { tracker->TrackField("stats_buffer", stats_buffer_); tracker->TrackField("rate_histogram", rate_); tracker->TrackField("size_histogram", size_); tracker->TrackField("ack_histogram", ack_); } +template +StatsBase::~StatsBase() { + StatsBase::StatsDebug stats_debug(static_cast(this)); + Debug(static_cast(this), "Destroyed. %s", stats_debug.ToString().c_str()); +} + +template +std::string StatsBase::StatsDebug::ToString() const { + std::string out = "Statistics:\n"; + auto add_field = [&out](const char* name, uint64_t val) { + out += " "; + out += std::string(name); + out += ": "; + out += std::to_string(val); + out += "\n"; + }; + add_field("Duration", uv_hrtime() - ptr->GetStat(&T::created_at)); + ToString(add_field); + return out; +} + template size_t get_length(const T* vec, size_t count) { CHECK_NOT_NULL(vec); diff --git a/src/quic/node_quic_util.h b/src/quic/node_quic_util.h index 0b06e573f8..9e887d7d8b 100644 --- a/src/quic/node_quic_util.h +++ b/src/quic/node_quic_util.h @@ -73,7 +73,7 @@ enum QuicErrorFamily : int32_t { // StatsBase is a utility help for classes (like QuicSession) // that record performance statistics -template +template class StatsBase { public: enum HistogramOptions { @@ -87,6 +87,19 @@ class StatsBase { v8::Local wrap, int options = HistogramOptions::NONE); + inline ~StatsBase(); + + using AddField = std::function; + + // The StatsDebug utility is used when StatsBase is destroyed + // to output statistical information. + struct StatsDebug { + Q* ptr; + explicit StatsDebug(Q* ptr_) : ptr(ptr_) {} + std::string ToString() const; + void ToString(AddField add_field) const; + }; + protected: // Increments the given stat field by the given amount inline void IncrementStat(uint64_t T::*member, uint64_t amount = 1);