diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index 5b9e4bfd4..36b2634eb 100644 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -1875,6 +1875,12 @@ namespace libtorrent // calling post_session_stats() on the session object. Its category is // ``status_notification``, but it is not subject to filtering, since it's only // manually posted anyway. + // + // the ``message()`` member function returns a string representation of the values that + // properly match the line returned in ``session_stats_header_alert::message()``. + // + // this specific output is parsed by tools/parse_session_stats.py + // if this is changed, that parser should also be changed struct TORRENT_EXPORT session_stats_alert final : alert { session_stats_alert(aux::stack_allocator& alloc, counters const& cnt); @@ -2498,7 +2504,7 @@ namespace libtorrent // this alert is posted when the session encounters a serious error, // potentially fatal - struct TORRENT_EXPORT session_error_alert : alert + struct TORRENT_EXPORT session_error_alert final : alert { // internal session_error_alert(aux::stack_allocator& alloc, error_code err @@ -2541,11 +2547,29 @@ namespace libtorrent aux::allocation_slot m_v6_nodes_idx; }; + // The session_stats_header alert is posted during the init of the + // session thread. + // + // the ``message()`` member function returns a string representation of the + // header that properly match the stats values string returned in + // ``session_stats_alert::message()``. + // + // this specific output is parsed by tools/parse_session_stats.py + // if this is changed, that parser should also be changed + struct TORRENT_EXPORT session_stats_header_alert final : alert + { + explicit session_stats_header_alert(aux::stack_allocator& alloc); + TORRENT_DEFINE_ALERT(session_stats_header_alert, 92) + + static const int static_category = alert::stats_notification; + virtual std::string message() const override; + }; + #undef TORRENT_DEFINE_ALERT_IMPL #undef TORRENT_DEFINE_ALERT #undef TORRENT_DEFINE_ALERT_PRIO - enum { num_alert_types = 92 }; // this enum represents "max_alert_index" + 1 + enum { num_alert_types = 93 }; // this enum represents "max_alert_index" + 1 } #endif diff --git a/src/alert.cpp b/src/alert.cpp index c96ce3c9f..85fab2663 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -44,6 +44,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/stack_allocator.hpp" #include "libtorrent/piece_block.hpp" #include "libtorrent/hex.hpp" // to_hex +#include "libtorrent/session_stats.hpp" #ifndef TORRENT_NO_DEPRECATE #include "libtorrent/write_resume_data.hpp" @@ -1742,8 +1743,6 @@ namespace libtorrent std::string session_stats_alert::message() const { - // this specific output is parsed by tools/parse_session_stats.py - // if this is changed, that parser should also be changed char msg[50]; std::snprintf(msg, sizeof(msg), "session stats (%d values): " , int(values.size())); std::string ret = msg; @@ -2218,4 +2217,25 @@ namespace libtorrent return nodes; } + session_stats_header_alert::session_stats_header_alert(aux::stack_allocator&) + {} + + std::string session_stats_header_alert::message() const + { + std::string stats_header = "session stats header: "; + std::vector stats = session_stats_metrics(); + std::sort(stats.begin(), stats.end() + , [] (stats_metric const& lhs, stats_metric const& rhs) + { return lhs.value_index < rhs.value_index; }); + bool first = true; + for (auto const& s : stats) + { + if (!first) stats_header += ", "; + stats_header += s.name; + first = false; + } + + return stats_header; + } + } // namespace libtorrent diff --git a/src/session_impl.cpp b/src/session_impl.cpp index cf4d4433d..d2e839a14 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -73,7 +73,6 @@ const rlim_t rlim_infinity = RLIM_INFINITY; #include "libtorrent/peer_connection_handle.hpp" #include "libtorrent/ip_filter.hpp" #include "libtorrent/socket.hpp" -#include "libtorrent/session_stats.hpp" #include "libtorrent/aux_/session_impl.hpp" #ifndef TORRENT_DISABLE_DHT #include "libtorrent/kademlia/dht_tracker.hpp" @@ -589,31 +588,10 @@ namespace aux { TORRENT_ASSERT(is_single_thread()); #ifndef TORRENT_DISABLE_LOGGING - // this alert is a bit special. The stats headers aren't very useful - // unless session_stats is enabled, so it's posted in the session_stats - // category as well - if (m_alerts.should_post() - || m_alerts.should_post()) - { - session_log(" *** session thread init"); - - // this specific output is parsed by tools/parse_session_stats.py - // if this is changed, that parser should also be changed - std::vector stats = session_stats_metrics(); - std::sort(stats.begin(), stats.end() - , [] (stats_metric const& lhs, stats_metric const& rhs) - { return lhs.value_index < rhs.value_index; }); - std::string stats_header = "session stats header: "; - bool first = true; - for (auto const& s : stats) - { - if (!first) stats_header += ", "; - stats_header += s.name; - first = false; - } - m_alerts.emplace_alert(stats_header.c_str()); - } + session_log(" *** session thread init"); #endif + if (m_alerts.should_post()) + m_alerts.emplace_alert(); // this is where we should set up all async operations. This // is called from within the network thread as opposed to the diff --git a/test/test_alert_types.cpp b/test/test_alert_types.cpp index e81a7d8a2..c50e74ade 100644 --- a/test/test_alert_types.cpp +++ b/test/test_alert_types.cpp @@ -41,17 +41,20 @@ using namespace libtorrent; TORRENT_TEST(alerts_types) { -#define TEST_ALERT_TYPE(name, seq, prio) \ +#define TEST_ALERT_TYPE(name, seq, prio, cat) \ TEST_EQUAL(name::priority, prio); \ - TEST_EQUAL(name::alert_type, seq); + TEST_EQUAL(name::alert_type, seq); \ + TEST_EQUAL(name::static_category, cat); - TEST_ALERT_TYPE(dht_get_peers_reply_alert, 87, 0); - TEST_ALERT_TYPE(session_error_alert, 90, 0); - TEST_ALERT_TYPE(dht_live_nodes_alert, 91, 0); + TEST_ALERT_TYPE(session_stats_alert, 70, 1, alert::stats_notification); + TEST_ALERT_TYPE(dht_get_peers_reply_alert, 87, 0, alert::dht_operation_notification); + TEST_ALERT_TYPE(session_error_alert, 90, 0, alert::error_notification); + TEST_ALERT_TYPE(dht_live_nodes_alert, 91, 0, alert::dht_notification); + TEST_ALERT_TYPE(session_stats_header_alert, 92, 0, alert::stats_notification); #undef TEST_ALERT_TYPE - TEST_EQUAL(num_alert_types, 92); + TEST_EQUAL(num_alert_types, 93); } TORRENT_TEST(dht_get_peers_reply_alert) @@ -129,3 +132,24 @@ TORRENT_TEST(dht_live_nodes_alert) std::sort(nodes.begin(), nodes.end()); TEST_CHECK(v == nodes); } + +TORRENT_TEST(session_stats_alert) +{ + alert_manager mgr(1, alert::stats_notification); + + std::vector alerts; + counters cnt; + + mgr.emplace_alert(); + mgr.emplace_alert(cnt); + mgr.get_all(alerts); + TEST_EQUAL(alerts.size(), 2); + + auto const* h = alert_cast(alerts[0]); + TEST_CHECK(h != nullptr); + TEST_CHECK(h->message().find("session stats header: ") != std::string::npos); + + auto const* v = alert_cast(alerts[1]); + TEST_CHECK(v != nullptr); + TEST_CHECK(v->message().find("session stats (") != std::string::npos); +}