NetQueryStats
GitOrigin-RevId: 5a04b322e12e2838b1d7f812fcf06bff4eefbace
This commit is contained in:
parent
d7eadd77c1
commit
cacabaf6d1
@ -456,6 +456,7 @@ set(TDLIB_SOURCE
|
|||||||
td/telegram/net/NetQueryCreator.cpp
|
td/telegram/net/NetQueryCreator.cpp
|
||||||
td/telegram/net/NetQueryDelayer.cpp
|
td/telegram/net/NetQueryDelayer.cpp
|
||||||
td/telegram/net/NetQueryDispatcher.cpp
|
td/telegram/net/NetQueryDispatcher.cpp
|
||||||
|
td/telegram/net/NetQueryStats.cpp
|
||||||
td/telegram/net/NetStatsManager.cpp
|
td/telegram/net/NetStatsManager.cpp
|
||||||
td/telegram/net/Proxy.cpp
|
td/telegram/net/Proxy.cpp
|
||||||
td/telegram/net/PublicRsaKeyShared.cpp
|
td/telegram/net/PublicRsaKeyShared.cpp
|
||||||
@ -628,6 +629,7 @@ set(TDLIB_SOURCE
|
|||||||
td/telegram/net/NetQueryCreator.h
|
td/telegram/net/NetQueryCreator.h
|
||||||
td/telegram/net/NetQueryDelayer.h
|
td/telegram/net/NetQueryDelayer.h
|
||||||
td/telegram/net/NetQueryDispatcher.h
|
td/telegram/net/NetQueryDispatcher.h
|
||||||
|
td/telegram/net/NetQueryStats.h
|
||||||
td/telegram/net/NetStatsManager.h
|
td/telegram/net/NetStatsManager.h
|
||||||
td/telegram/net/NetType.h
|
td/telegram/net/NetType.h
|
||||||
td/telegram/net/Proxy.h
|
td/telegram/net/Proxy.h
|
||||||
|
@ -30,6 +30,8 @@ namespace td {
|
|||||||
|
|
||||||
class MultiTd : public Actor {
|
class MultiTd : public Actor {
|
||||||
public:
|
public:
|
||||||
|
explicit MultiTd(Td::Options options) : options_(std::move(options)) {
|
||||||
|
}
|
||||||
void create(int32 td_id, unique_ptr<TdCallback> callback) {
|
void create(int32 td_id, unique_ptr<TdCallback> callback) {
|
||||||
auto &td = tds_[td_id];
|
auto &td = tds_[td_id];
|
||||||
CHECK(td.empty());
|
CHECK(td.empty());
|
||||||
@ -47,7 +49,7 @@ class MultiTd : public Actor {
|
|||||||
auto context = std::make_shared<TdActorContext>(to_string(td_id));
|
auto context = std::make_shared<TdActorContext>(to_string(td_id));
|
||||||
auto old_context = set_context(context);
|
auto old_context = set_context(context);
|
||||||
auto old_tag = set_tag(context->tag_);
|
auto old_tag = set_tag(context->tag_);
|
||||||
td = create_actor<Td>("Td", std::move(callback));
|
td = create_actor<Td>("Td", std::move(callback), options_);
|
||||||
set_context(old_context);
|
set_context(old_context);
|
||||||
set_tag(old_tag);
|
set_tag(old_tag);
|
||||||
}
|
}
|
||||||
@ -64,6 +66,7 @@ class MultiTd : public Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Td::Options options_;
|
||||||
std::unordered_map<int32, ActorOwn<Td>> tds_;
|
std::unordered_map<int32, ActorOwn<Td>> tds_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -112,6 +115,7 @@ class TdReceiver {
|
|||||||
class MultiClient::Impl final {
|
class MultiClient::Impl final {
|
||||||
public:
|
public:
|
||||||
Impl() {
|
Impl() {
|
||||||
|
options_.net_query_stats = std::make_shared<NetQueryStats>();
|
||||||
concurrent_scheduler_ = make_unique<ConcurrentScheduler>();
|
concurrent_scheduler_ = make_unique<ConcurrentScheduler>();
|
||||||
concurrent_scheduler_->init(0);
|
concurrent_scheduler_->init(0);
|
||||||
receiver_ = make_unique<TdReceiver>();
|
receiver_ = make_unique<TdReceiver>();
|
||||||
@ -120,7 +124,8 @@ class MultiClient::Impl final {
|
|||||||
|
|
||||||
ClientId create_client() {
|
ClientId create_client() {
|
||||||
auto client_id = ++client_id_;
|
auto client_id = ++client_id_;
|
||||||
tds_[client_id] = concurrent_scheduler_->create_actor_unsafe<Td>(0, "Td", receiver_->create_callback(client_id));
|
tds_[client_id] =
|
||||||
|
concurrent_scheduler_->create_actor_unsafe<Td>(0, "Td", receiver_->create_callback(client_id), options_);
|
||||||
return client_id;
|
return client_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,6 +190,7 @@ class MultiClient::Impl final {
|
|||||||
std::vector<Request> requests_;
|
std::vector<Request> requests_;
|
||||||
unique_ptr<ConcurrentScheduler> concurrent_scheduler_;
|
unique_ptr<ConcurrentScheduler> concurrent_scheduler_;
|
||||||
ClientId client_id_{0};
|
ClientId client_id_{0};
|
||||||
|
Td::Options options_;
|
||||||
std::unordered_map<int32, ActorOwn<Td>> tds_;
|
std::unordered_map<int32, ActorOwn<Td>> tds_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -270,14 +276,16 @@ class TdReceiver {
|
|||||||
|
|
||||||
class MultiImpl {
|
class MultiImpl {
|
||||||
public:
|
public:
|
||||||
MultiImpl() {
|
MultiImpl(std::shared_ptr<NetQueryStats> net_query_stats) {
|
||||||
concurrent_scheduler_ = std::make_shared<ConcurrentScheduler>();
|
concurrent_scheduler_ = std::make_shared<ConcurrentScheduler>();
|
||||||
concurrent_scheduler_->init(3);
|
concurrent_scheduler_->init(3);
|
||||||
concurrent_scheduler_->start();
|
concurrent_scheduler_->start();
|
||||||
|
|
||||||
{
|
{
|
||||||
auto guard = concurrent_scheduler_->get_main_guard();
|
auto guard = concurrent_scheduler_->get_main_guard();
|
||||||
multi_td_ = create_actor<MultiTd>("MultiTd");
|
Td::Options options;
|
||||||
|
options.net_query_stats = std::move(net_query_stats);
|
||||||
|
multi_td_ = create_actor<MultiTd>("MultiTd", std::move(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduler_thread_ = thread([concurrent_scheduler = concurrent_scheduler_] {
|
scheduler_thread_ = thread([concurrent_scheduler = concurrent_scheduler_] {
|
||||||
@ -343,15 +351,20 @@ class MultiImplPool {
|
|||||||
[](auto &a, auto &b) { return a.lock().use_count() < b.lock().use_count(); });
|
[](auto &a, auto &b) { return a.lock().use_count() < b.lock().use_count(); });
|
||||||
auto res = impl.lock();
|
auto res = impl.lock();
|
||||||
if (!res) {
|
if (!res) {
|
||||||
res = std::make_shared<MultiImpl>();
|
res = std::make_shared<MultiImpl>(net_query_stats_);
|
||||||
impl = res;
|
impl = res;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<NetQueryStats> get_net_query_stats() const {
|
||||||
|
return net_query_stats_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
std::vector<std::weak_ptr<MultiImpl>> impls_;
|
std::vector<std::weak_ptr<MultiImpl>> impls_;
|
||||||
|
std::shared_ptr<NetQueryStats> net_query_stats_ = std::make_shared<NetQueryStats>();
|
||||||
};
|
};
|
||||||
|
|
||||||
class MultiClient::Impl final {
|
class MultiClient::Impl final {
|
||||||
|
@ -9,12 +9,15 @@
|
|||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
|
|
||||||
#include "td/telegram/net/NetQueryCounter.h"
|
#include "td/telegram/net/NetQueryCounter.h"
|
||||||
|
#include "td/telegram/net/NetQueryStats.h"
|
||||||
#include "td/telegram/Td.h"
|
#include "td/telegram/Td.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
ClientActor::ClientActor(unique_ptr<TdCallback> callback) {
|
ClientActor::ClientActor(unique_ptr<TdCallback> callback, Options options) {
|
||||||
td_ = create_actor<Td>("Td", std::move(callback));
|
Td::Options td_options;
|
||||||
|
td_options.net_query_stats = options.net_query_stats;
|
||||||
|
td_ = create_actor<Td>("Td", std::move(callback), std::move(td_options));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientActor::request(uint64 id, td_api::object_ptr<td_api::Function> request) {
|
void ClientActor::request(uint64 id, td_api::object_ptr<td_api::Function> request) {
|
||||||
@ -31,8 +34,16 @@ td_api::object_ptr<td_api::Object> ClientActor::execute(td_api::object_ptr<td_ap
|
|||||||
return Td::static_request(std::move(request));
|
return Td::static_request(std::move(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 get_pending_network_query_count() {
|
std::shared_ptr<NetQueryStats> create_net_query_stats() {
|
||||||
return NetQueryCounter::get_count();
|
return std::make_shared<NetQueryStats>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_pending_network_queries(NetQueryStats &stats) {
|
||||||
|
stats.dump_pending_network_queries();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 get_pending_network_query_count(NetQueryStats &stats) {
|
||||||
|
return stats.get_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
class Td;
|
class Td;
|
||||||
|
class NetQueryStats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a low-level Actor interface for interaction with TDLib. The interface is a lot more flexible than
|
* This is a low-level Actor interface for interaction with TDLib. The interface is a lot more flexible than
|
||||||
@ -27,11 +28,15 @@ class Td;
|
|||||||
*/
|
*/
|
||||||
class ClientActor : public Actor {
|
class ClientActor : public Actor {
|
||||||
public:
|
public:
|
||||||
|
struct Options {
|
||||||
|
std::shared_ptr<NetQueryStats> net_query_stats;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a ClientActor using the specified callback.
|
* Creates a ClientActor using the specified callback.
|
||||||
* \param[in] callback Callback for outgoing notifications from TDLib.
|
* \param[in] callback Callback for outgoing notifications from TDLib.
|
||||||
*/
|
*/
|
||||||
explicit ClientActor(unique_ptr<TdCallback> callback);
|
explicit ClientActor(unique_ptr<TdCallback> callback, Options options = {});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends one request to TDLib. The answer will be received via callback.
|
* Sends one request to TDLib. The answer will be received via callback.
|
||||||
@ -70,16 +75,18 @@ class ClientActor : public Actor {
|
|||||||
ActorOwn<Td> td_;
|
ActorOwn<Td> td_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<NetQueryStats> create_net_query_stats();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps information about all pending network queries to the internal TDLib log.
|
* Dumps information about all pending network queries to the internal TDLib log.
|
||||||
* This is useful for library debugging.
|
* This is useful for library debugging.
|
||||||
*/
|
*/
|
||||||
void dump_pending_network_queries();
|
void dump_pending_network_queries(NetQueryStats &stats);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current number of pending network queries. Useful for library debugging.
|
* Returns the current number of pending network queries. Useful for library debugging.
|
||||||
* \return Number of currently pending network queries.
|
* \return Number of currently pending network queries.
|
||||||
*/
|
*/
|
||||||
uint64 get_pending_network_query_count();
|
uint64 get_pending_network_query_count(NetQueryStats &stats);
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -219,6 +219,10 @@ bool Global::ignore_backgrond_updates() const {
|
|||||||
shared_config_->get_option_boolean("ignore_background_updates");
|
shared_config_->get_option_boolean("ignore_background_updates");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Global::set_net_query_stats(std::shared_ptr<NetQueryStats> net_query_stats) {
|
||||||
|
net_query_creator_.set_create_func([=] { return td::make_unique<NetQueryCreator>(net_query_stats); });
|
||||||
|
}
|
||||||
|
|
||||||
void Global::set_net_query_dispatcher(unique_ptr<NetQueryDispatcher> net_query_dispatcher) {
|
void Global::set_net_query_dispatcher(unique_ptr<NetQueryDispatcher> net_query_dispatcher) {
|
||||||
net_query_dispatcher_ = std::move(net_query_dispatcher);
|
net_query_dispatcher_ = std::move(net_query_dispatcher);
|
||||||
}
|
}
|
||||||
|
@ -102,9 +102,10 @@ class Global : public ActorContext {
|
|||||||
bool ignore_backgrond_updates() const;
|
bool ignore_backgrond_updates() const;
|
||||||
|
|
||||||
NetQueryCreator &net_query_creator() {
|
NetQueryCreator &net_query_creator() {
|
||||||
return net_query_creator_.get();
|
return *net_query_creator_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_net_query_stats(std::shared_ptr<NetQueryStats> net_query_stats);
|
||||||
void set_net_query_dispatcher(unique_ptr<NetQueryDispatcher> net_query_dispatcher);
|
void set_net_query_dispatcher(unique_ptr<NetQueryDispatcher> net_query_dispatcher);
|
||||||
|
|
||||||
NetQueryDispatcher &net_query_dispatcher() {
|
NetQueryDispatcher &net_query_dispatcher() {
|
||||||
@ -422,7 +423,7 @@ class Global : public ActorContext {
|
|||||||
|
|
||||||
ActorId<StateManager> state_manager_;
|
ActorId<StateManager> state_manager_;
|
||||||
|
|
||||||
SchedulerLocalStorage<NetQueryCreator> net_query_creator_;
|
LazySchedulerLocalStorage<td::unique_ptr<NetQueryCreator>> net_query_creator_;
|
||||||
unique_ptr<NetQueryDispatcher> net_query_dispatcher_;
|
unique_ptr<NetQueryDispatcher> net_query_dispatcher_;
|
||||||
|
|
||||||
unique_ptr<ConfigShared> shared_config_;
|
unique_ptr<ConfigShared> shared_config_;
|
||||||
|
@ -3005,7 +3005,8 @@ class SetBackgroundRequest : public RequestActor<> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Td::Td(unique_ptr<TdCallback> callback) : callback_(std::move(callback)) {
|
Td::Td(unique_ptr<TdCallback> callback, Options options)
|
||||||
|
: callback_(std::move(callback)), td_options_(std::move(options)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Td::~Td() = default;
|
Td::~Td() = default;
|
||||||
@ -3740,6 +3741,7 @@ void Td::start_up() {
|
|||||||
|
|
||||||
VLOG(td_init) << "Create Global";
|
VLOG(td_init) << "Create Global";
|
||||||
set_context(std::make_shared<Global>());
|
set_context(std::make_shared<Global>());
|
||||||
|
G()->set_net_query_stats(td_options_.net_query_stats);
|
||||||
inc_request_actor_refcnt(); // guard
|
inc_request_actor_refcnt(); // guard
|
||||||
inc_actor_refcnt(); // guard
|
inc_actor_refcnt(); // guard
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "td/telegram/TdParameters.h"
|
#include "td/telegram/TdParameters.h"
|
||||||
#include "td/telegram/TermsOfService.h"
|
#include "td/telegram/TermsOfService.h"
|
||||||
|
|
||||||
|
#include "td/telegram/net/NetQueryStats.h"
|
||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
#include "td/telegram/telegram_api.h"
|
#include "td/telegram/telegram_api.h"
|
||||||
|
|
||||||
@ -93,7 +94,11 @@ class Td final : public NetQueryCallback {
|
|||||||
Td &operator=(Td &&) = delete;
|
Td &operator=(Td &&) = delete;
|
||||||
~Td() override;
|
~Td() override;
|
||||||
|
|
||||||
explicit Td(unique_ptr<TdCallback> callback);
|
struct Options {
|
||||||
|
std::shared_ptr<td::NetQueryStats> net_query_stats;
|
||||||
|
};
|
||||||
|
|
||||||
|
Td(unique_ptr<TdCallback> callback, Options options);
|
||||||
|
|
||||||
void request(uint64 id, tl_object_ptr<td_api::Function> function);
|
void request(uint64 id, tl_object_ptr<td_api::Function> function);
|
||||||
|
|
||||||
@ -260,6 +265,7 @@ class Td final : public NetQueryCallback {
|
|||||||
TdParameters parameters_;
|
TdParameters parameters_;
|
||||||
|
|
||||||
unique_ptr<TdCallback> callback_;
|
unique_ptr<TdCallback> callback_;
|
||||||
|
Options td_options_;
|
||||||
|
|
||||||
StateManager::State connection_state_;
|
StateManager::State connection_state_;
|
||||||
|
|
||||||
|
@ -846,7 +846,10 @@ class CliClient final : public Actor {
|
|||||||
uint64 generation_;
|
uint64 generation_;
|
||||||
};
|
};
|
||||||
|
|
||||||
td_client_ = create_actor<ClientActor>(name, make_unique<TdCallbackImpl>(this, ++generation_));
|
ClientActor::Options options;
|
||||||
|
options.net_query_stats = net_query_stats_;
|
||||||
|
|
||||||
|
td_client_ = create_actor<ClientActor>(name, make_unique<TdCallbackImpl>(this, ++generation_), std::move(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_td() {
|
void init_td() {
|
||||||
@ -4164,7 +4167,7 @@ class CliClient final : public Actor {
|
|||||||
} else if (op == "q" || op == "Quit") {
|
} else if (op == "q" || op == "Quit") {
|
||||||
quit();
|
quit();
|
||||||
} else if (op == "dnq" || op == "DumpNetQueries") {
|
} else if (op == "dnq" || op == "DumpNetQueries") {
|
||||||
dump_pending_network_queries();
|
dump_pending_network_queries(*net_query_stats_);
|
||||||
} else if (op == "fatal") {
|
} else if (op == "fatal") {
|
||||||
LOG(FATAL) << "Fatal!";
|
LOG(FATAL) << "Fatal!";
|
||||||
} else if (op == "unreachable") {
|
} else if (op == "unreachable") {
|
||||||
@ -4289,6 +4292,7 @@ class CliClient final : public Actor {
|
|||||||
ConcurrentScheduler *scheduler_{nullptr};
|
ConcurrentScheduler *scheduler_{nullptr};
|
||||||
|
|
||||||
bool use_test_dc_ = false;
|
bool use_test_dc_ = false;
|
||||||
|
std::shared_ptr<NetQueryStats> net_query_stats_ = create_net_query_stats();
|
||||||
ActorOwn<ClientActor> td_client_;
|
ActorOwn<ClientActor> td_client_;
|
||||||
std::queue<string> cmd_queue_;
|
std::queue<string> cmd_queue_;
|
||||||
bool close_flag_ = false;
|
bool close_flag_ = false;
|
||||||
|
@ -62,43 +62,4 @@ void NetQuery::set_error(Status status, string source) {
|
|||||||
set_error_impl(std::move(status), std::move(source));
|
set_error_impl(std::move(status), std::move(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
TsList<NetQueryDebug> &NetQuery::get_net_query_list() {
|
|
||||||
static auto init_mutex = [] {
|
|
||||||
TsList<NetQueryDebug>::lock().unlock(); // initialize mutex before any NetQuery
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
CHECK(init_mutex);
|
|
||||||
static TsList<NetQueryDebug> net_query_list;
|
|
||||||
return net_query_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_pending_network_queries() {
|
|
||||||
auto n = NetQueryCounter::get_count();
|
|
||||||
LOG(WARNING) << tag("pending net queries", n);
|
|
||||||
|
|
||||||
decltype(n) i = 0;
|
|
||||||
bool was_gap = false;
|
|
||||||
auto &net_query_list = NetQuery::get_net_query_list();
|
|
||||||
auto guard = net_query_list.lock();
|
|
||||||
for (auto end = net_query_list.end(), cur = net_query_list.begin(); cur != end; cur = cur->get_next(), i++) {
|
|
||||||
if (i < 20 || i + 20 > n || i % (n / 20 + 1) == 0) {
|
|
||||||
if (was_gap) {
|
|
||||||
LOG(WARNING) << "...";
|
|
||||||
was_gap = false;
|
|
||||||
}
|
|
||||||
const NetQueryDebug &debug = cur->get_data_unsafe();
|
|
||||||
const NetQuery &nq = *static_cast<const NetQuery *>(cur);
|
|
||||||
LOG(WARNING) << tag("user", debug.my_id_) << nq << tag("total flood", format::as_time(nq.total_timeout_))
|
|
||||||
<< tag("since start", format::as_time(Time::now_cached() - debug.start_timestamp_))
|
|
||||||
<< tag("state", debug.state_)
|
|
||||||
<< tag("in this state", format::as_time(Time::now_cached() - debug.state_timestamp_))
|
|
||||||
<< tag("state changed", debug.state_change_count_) << tag("resend count", debug.resend_count_)
|
|
||||||
<< tag("fail count", debug.send_failed_count_) << tag("ack state", debug.ack_state_)
|
|
||||||
<< tag("unknown", debug.unknown_state_);
|
|
||||||
} else {
|
|
||||||
was_gap = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "td/telegram/net/DcId.h"
|
#include "td/telegram/net/DcId.h"
|
||||||
#include "td/telegram/net/NetQueryCounter.h"
|
#include "td/telegram/net/NetQueryCounter.h"
|
||||||
|
#include "td/telegram/net/NetQueryStats.h"
|
||||||
|
|
||||||
#include "td/actor/actor.h"
|
#include "td/actor/actor.h"
|
||||||
#include "td/actor/PromiseFuture.h"
|
#include "td/actor/PromiseFuture.h"
|
||||||
@ -40,18 +41,6 @@ class NetQueryCallback : public Actor {
|
|||||||
virtual void on_result_resendable(NetQueryPtr query, Promise<NetQueryPtr> promise);
|
virtual void on_result_resendable(NetQueryPtr query, Promise<NetQueryPtr> promise);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NetQueryDebug {
|
|
||||||
double start_timestamp_ = 0;
|
|
||||||
int32 my_id_ = 0;
|
|
||||||
int32 resend_count_ = 0;
|
|
||||||
string state_ = "empty";
|
|
||||||
double state_timestamp_ = 0;
|
|
||||||
int32 state_change_count_ = 0;
|
|
||||||
int32 send_failed_count_ = 0;
|
|
||||||
int ack_state_ = 0;
|
|
||||||
bool unknown_state_ = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NetQuery : public TsListNode<NetQueryDebug> {
|
class NetQuery : public TsListNode<NetQueryDebug> {
|
||||||
public:
|
public:
|
||||||
NetQuery() = default;
|
NetQuery() = default;
|
||||||
@ -279,8 +268,6 @@ class NetQuery : public TsListNode<NetQueryDebug> {
|
|||||||
|
|
||||||
static int32 tl_magic(const BufferSlice &buffer_slice);
|
static int32 tl_magic(const BufferSlice &buffer_slice);
|
||||||
|
|
||||||
static TsList<NetQueryDebug> &get_net_query_list();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
State state_ = State::Empty;
|
State state_ = State::Empty;
|
||||||
Type type_ = Type::Common;
|
Type type_ = Type::Common;
|
||||||
@ -345,13 +332,12 @@ class NetQuery : public TsListNode<NetQueryDebug> {
|
|||||||
int32 file_type_ = -1; // to be set by caller
|
int32 file_type_ = -1; // to be set by caller
|
||||||
|
|
||||||
NetQuery(State state, uint64 id, BufferSlice &&query, BufferSlice &&answer, DcId dc_id, Type type, AuthFlag auth_flag,
|
NetQuery(State state, uint64 id, BufferSlice &&query, BufferSlice &&answer, DcId dc_id, Type type, AuthFlag auth_flag,
|
||||||
GzipFlag gzip_flag, int32 tl_constructor, double total_timeout_limit)
|
GzipFlag gzip_flag, int32 tl_constructor, double total_timeout_limit, NetQueryStats *stats)
|
||||||
: state_(state)
|
: state_(state)
|
||||||
, type_(type)
|
, type_(type)
|
||||||
, auth_flag_(auth_flag)
|
, auth_flag_(auth_flag)
|
||||||
, gzip_flag_(gzip_flag)
|
, gzip_flag_(gzip_flag)
|
||||||
, dc_id_(dc_id)
|
, dc_id_(dc_id)
|
||||||
, nq_counter_(true)
|
|
||||||
, status_()
|
, status_()
|
||||||
, id_(id)
|
, id_(id)
|
||||||
, query_(std::move(query))
|
, query_(std::move(query))
|
||||||
@ -361,7 +347,9 @@ class NetQuery : public TsListNode<NetQueryDebug> {
|
|||||||
get_data_unsafe().my_id_ = get_my_id();
|
get_data_unsafe().my_id_ = get_my_id();
|
||||||
get_data_unsafe().start_timestamp_ = Time::now();
|
get_data_unsafe().start_timestamp_ = Time::now();
|
||||||
LOG(INFO) << *this;
|
LOG(INFO) << *this;
|
||||||
get_net_query_list().put(this);
|
if (stats) {
|
||||||
|
nq_counter_ = stats->register_query(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ NetQueryPtr NetQueryCreator::create(uint64 id, const telegram_api::Function &fun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto query = object_pool_.create(NetQuery::State::Query, id, std::move(slice), BufferSlice(), dc_id, type, auth_flag,
|
auto query = object_pool_.create(NetQuery::State::Query, id, std::move(slice), BufferSlice(), dc_id, type, auth_flag,
|
||||||
gzip_flag, tl_constructor, total_timeout_limit);
|
gzip_flag, tl_constructor, total_timeout_limit, net_query_stats_.get());
|
||||||
query->set_cancellation_token(query.generation());
|
query->set_cancellation_token(query.generation());
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,8 @@ class Function;
|
|||||||
|
|
||||||
class NetQueryCreator {
|
class NetQueryCreator {
|
||||||
public:
|
public:
|
||||||
NetQueryCreator() {
|
explicit NetQueryCreator(std::shared_ptr<NetQueryStats> net_query_stats = {}) {
|
||||||
|
net_query_stats_ = std::move(net_query_stats);
|
||||||
object_pool_.set_check_empty(true);
|
object_pool_.set_check_empty(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +32,8 @@ class NetQueryCreator {
|
|||||||
|
|
||||||
NetQueryPtr create_update(BufferSlice &&buffer) {
|
NetQueryPtr create_update(BufferSlice &&buffer) {
|
||||||
return object_pool_.create(NetQuery::State::OK, 0, BufferSlice(), std::move(buffer), DcId::main(),
|
return object_pool_.create(NetQuery::State::OK, 0, BufferSlice(), std::move(buffer), DcId::main(),
|
||||||
NetQuery::Type::Common, NetQuery::AuthFlag::On, NetQuery::GzipFlag::Off, 0, 0);
|
NetQuery::Type::Common, NetQuery::AuthFlag::On, NetQuery::GzipFlag::Off, 0, 0,
|
||||||
|
net_query_stats_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
NetQueryPtr create(const telegram_api::Function &function, DcId dc_id = DcId::main(),
|
NetQueryPtr create(const telegram_api::Function &function, DcId dc_id = DcId::main(),
|
||||||
@ -45,6 +47,7 @@ class NetQueryCreator {
|
|||||||
NetQuery::AuthFlag auth_flag);
|
NetQuery::AuthFlag auth_flag);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::shared_ptr<NetQueryStats> net_query_stats_;
|
||||||
ObjectPool<NetQuery> object_pool_;
|
ObjectPool<NetQuery> object_pool_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
50
td/telegram/net/NetQueryStats.cpp
Normal file
50
td/telegram/net/NetQueryStats.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
#include "td/telegram/net/NetQueryStats.h"
|
||||||
|
|
||||||
|
#include "td/telegram/net/NetQuery.h"
|
||||||
|
|
||||||
|
#include "td/utils/logging.h"
|
||||||
|
#include "td/utils/format.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
uint64 NetQueryStats::get_count() const {
|
||||||
|
return count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetQueryStats::dump_pending_network_queries() {
|
||||||
|
auto n = get_count();
|
||||||
|
LOG(WARNING) << tag("pending net queries", n);
|
||||||
|
|
||||||
|
if (!use_list_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
decltype(n) i = 0;
|
||||||
|
bool was_gap = false;
|
||||||
|
auto &net_query_list = list_;
|
||||||
|
auto guard = net_query_list.lock();
|
||||||
|
for (auto end = net_query_list.end(), cur = net_query_list.begin(); cur != end; cur = cur->get_next(), i++) {
|
||||||
|
if (i < 20 || i + 20 > n || i % (n / 20 + 1) == 0) {
|
||||||
|
if (was_gap) {
|
||||||
|
LOG(WARNING) << "...";
|
||||||
|
was_gap = false;
|
||||||
|
}
|
||||||
|
const NetQueryDebug &debug = cur->get_data_unsafe();
|
||||||
|
const NetQuery &nq = *static_cast<const NetQuery *>(cur);
|
||||||
|
LOG(WARNING) << tag("user", debug.my_id_) << nq << tag("total flood", format::as_time(nq.total_timeout_))
|
||||||
|
<< tag("since start", format::as_time(Time::now_cached() - debug.start_timestamp_))
|
||||||
|
<< tag("state", debug.state_)
|
||||||
|
<< tag("in this state", format::as_time(Time::now_cached() - debug.state_timestamp_))
|
||||||
|
<< tag("state changed", debug.state_change_count_) << tag("resend count", debug.resend_count_)
|
||||||
|
<< tag("fail count", debug.send_failed_count_) << tag("ack state", debug.ack_state_)
|
||||||
|
<< tag("unknown", debug.unknown_state_);
|
||||||
|
} else {
|
||||||
|
was_gap = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace td
|
50
td/telegram/net/NetQueryStats.h
Normal file
50
td/telegram/net/NetQueryStats.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
#include "td/telegram/net/NetQueryCounter.h"
|
||||||
|
|
||||||
|
#include "td/utils/int_types.h"
|
||||||
|
#include "td/utils/TsList.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
struct NetQueryDebug {
|
||||||
|
double start_timestamp_ = 0;
|
||||||
|
int32 my_id_ = 0;
|
||||||
|
int32 resend_count_ = 0;
|
||||||
|
string state_ = "empty";
|
||||||
|
double state_timestamp_ = 0;
|
||||||
|
int32 state_change_count_ = 0;
|
||||||
|
int32 send_failed_count_ = 0;
|
||||||
|
int ack_state_ = 0;
|
||||||
|
bool unknown_state_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NetQueryStats {
|
||||||
|
public:
|
||||||
|
[[deprecated]] static NetQueryStats &get_default_stats() {
|
||||||
|
static NetQueryStats res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetQueryCounter register_query(TsListNode<NetQueryDebug> *query) {
|
||||||
|
if (use_list_.load(std::memory_order_relaxed)) {
|
||||||
|
list_.put(query);
|
||||||
|
}
|
||||||
|
return NetQueryCounter(&count_);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 get_count() const;
|
||||||
|
void dump_pending_network_queries();
|
||||||
|
|
||||||
|
private:
|
||||||
|
NetQueryCounter::Counter count_;
|
||||||
|
std::atomic<bool> use_list_{true};
|
||||||
|
TsList<NetQueryDebug> list_;
|
||||||
|
};
|
||||||
|
} // namespace td
|
@ -46,6 +46,10 @@ class LazySchedulerLocalStorage {
|
|||||||
LazySchedulerLocalStorage() = default;
|
LazySchedulerLocalStorage() = default;
|
||||||
explicit LazySchedulerLocalStorage(std::function<T()> create_func) : create_func_(std::move(create_func)) {
|
explicit LazySchedulerLocalStorage(std::function<T()> create_func) : create_func_(std::move(create_func)) {
|
||||||
}
|
}
|
||||||
|
void set_create_func(std::function<T()> create_func) {
|
||||||
|
CHECK(!create_func_);
|
||||||
|
create_func_ = create_func;
|
||||||
|
}
|
||||||
|
|
||||||
T &get() {
|
T &get() {
|
||||||
auto &optional_value_ = sls_optional_value_.get();
|
auto &optional_value_ = sls_optional_value_.get();
|
||||||
|
@ -202,6 +202,9 @@ class TsList : public TsListNode<DataT> {
|
|||||||
|
|
||||||
template <class DataT>
|
template <class DataT>
|
||||||
std::unique_lock<std::mutex> TsListNode<DataT>::lock() {
|
std::unique_lock<std::mutex> TsListNode<DataT>::lock() {
|
||||||
|
if (parent == nullptr) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
CHECK(parent != nullptr);
|
CHECK(parent != nullptr);
|
||||||
return parent->lock();
|
return parent->lock();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user