Remove set_log_fatal_error_callback. Add td_set_log_message_callback, deprecate td_set_log_fatal_error_callback.

This commit is contained in:
levlam 2021-05-18 04:35:36 +03:00
parent 41d75d8c99
commit d34680b83f
14 changed files with 104 additions and 32 deletions

View File

@ -659,6 +659,25 @@ td_api::object_ptr<td_api::Object> ClientManager::execute(td_api::object_ptr<td_
return Td::static_request(std::move(request)); return Td::static_request(std::move(request));
} }
static std::atomic<ClientManager::LogMessageCallbackPtr> log_message_callback;
static void log_message_callback_wrapper(int verbosity_level, CSlice message) {
auto callback = log_message_callback.load(std::memory_order_relaxed);
if (callback != nullptr) {
callback(verbosity_level, message.c_str());
}
}
void ClientManager::set_log_message_callback(int max_verbosity_level, LogMessageCallbackPtr callback) {
if (callback == nullptr) {
::td::set_log_message_callback(max_verbosity_level, nullptr);
log_message_callback = nullptr;
} else {
log_message_callback = callback;
::td::set_log_message_callback(max_verbosity_level, log_message_callback_wrapper);
}
}
ClientManager::~ClientManager() = default; ClientManager::~ClientManager() = default;
ClientManager::ClientManager(ClientManager &&other) = default; ClientManager::ClientManager(ClientManager &&other) = default;
ClientManager &ClientManager::operator=(ClientManager &&other) = default; ClientManager &ClientManager::operator=(ClientManager &&other) = default;

View File

@ -238,6 +238,26 @@ class ClientManager final {
*/ */
static td_api::object_ptr<td_api::Object> execute(td_api::object_ptr<td_api::Function> &&request); static td_api::object_ptr<td_api::Object> execute(td_api::object_ptr<td_api::Function> &&request);
/**
* A type of callback function that will be called when a message is added to the internal TDLib log.
*
* \param verbosity_level Log verbosity level with which the message was added.
* \param message Null-terminated string with the logged message.
*/
using LogMessageCallbackPtr = void (*)(int verbosity_level, const char *message);
/**
* Sets the callback that will be called when a message is added to the internal TDLib log.
* None of the TDLib methods can be called from the callback.
* If message verbosity level is 0, then TDLib will crash as soon as callback returns.
* By default the callback is not set.
*
* \param[in] max_verbosity_level Maximum verbosity level of messages for which the callback will be called.
* \param[in] callback Callback that will be called when a message is added to the internal TDLib log.
* Pass nullptr to remove the callback.
*/
static void set_log_message_callback(int max_verbosity_level, LogMessageCallbackPtr callback);
/** /**
* Destroys the client manager and all TDLib client instances managed by it. * Destroys the client manager and all TDLib client instances managed by it.
*/ */

View File

@ -18,6 +18,7 @@
namespace td { namespace td {
// TODO can be made private in TDLib 2.0
class ClientJson final { class ClientJson final {
public: public:
void send(Slice request); void send(Slice request);

View File

@ -6,6 +6,7 @@
// //
#include "td/telegram/Log.h" #include "td/telegram/Log.h"
#include "td/telegram/Client.h"
#include "td/telegram/Logging.h" #include "td/telegram/Logging.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
@ -23,9 +24,13 @@ static string log_file_path;
static int64 max_log_file_size = 10 << 20; static int64 max_log_file_size = 10 << 20;
static Log::FatalErrorCallbackPtr fatal_error_callback; static Log::FatalErrorCallbackPtr fatal_error_callback;
static void fatal_error_callback_wrapper(CSlice message) { static void fatal_error_callback_wrapper(int verbosity_level, const char *message) {
CHECK(fatal_error_callback != nullptr); if (verbosity_level == 0) {
fatal_error_callback(message.c_str()); auto callback = fatal_error_callback;
if (callback != nullptr) {
callback(message);
}
}
} }
bool Log::set_file_path(string file_path) { bool Log::set_file_path(string file_path) {
@ -59,11 +64,11 @@ void Log::set_verbosity_level(int new_verbosity_level) {
void Log::set_fatal_error_callback(FatalErrorCallbackPtr callback) { void Log::set_fatal_error_callback(FatalErrorCallbackPtr callback) {
std::lock_guard<std::mutex> lock(log_mutex); std::lock_guard<std::mutex> lock(log_mutex);
if (callback == nullptr) { if (callback == nullptr) {
ClientManager::set_log_message_callback(0, nullptr);
fatal_error_callback = nullptr; fatal_error_callback = nullptr;
set_log_fatal_error_callback(nullptr);
} else { } else {
fatal_error_callback = callback; fatal_error_callback = callback;
set_log_fatal_error_callback(fatal_error_callback_wrapper); ClientManager::set_log_message_callback(0, fatal_error_callback_wrapper);
} }
} }

View File

@ -76,6 +76,7 @@ class Log {
* The TDLib will crash as soon as callback returns. * The TDLib will crash as soon as callback returns.
* By default the callback is not set. * By default the callback is not set.
* *
* \deprecated Use ClientManager::set_log_message_callback instead.
* \param[in] callback Callback that will be called when a fatal error happens. * \param[in] callback Callback that will be called when a fatal error happens.
* Pass nullptr to remove the callback. * Pass nullptr to remove the callback.
*/ */

View File

@ -13,7 +13,7 @@
#include "td/net/HttpReader.h" #include "td/net/HttpReader.h"
#include "td/telegram/ClientActor.h" #include "td/telegram/ClientActor.h"
#include "td/telegram/Log.h" #include "td/telegram/Client.h"
#include "td/telegram/Td.h" // for VERBOSITY_NAME(td_requests) #include "td/telegram/Td.h" // for VERBOSITY_NAME(td_requests)
#include "td/telegram/td_api_json.h" #include "td/telegram/td_api_json.h"
@ -4366,8 +4366,11 @@ static void fail_signal(int sig) {
} }
} }
static void on_fatal_error(const char *error) { static void on_log_message(int verbosity_level, const char *message) {
std::cerr << "Fatal error: " << error << std::endl; if (verbosity_level == 0) {
std::cerr << "Fatal error: " << message;
}
std::cerr << "Log message: " << message;
} }
void main(int argc, char **argv) { void main(int argc, char **argv) {
@ -4376,7 +4379,7 @@ void main(int argc, char **argv) {
ignore_signal(SignalType::Pipe).ensure(); ignore_signal(SignalType::Pipe).ensure();
set_signal_handler(SignalType::Error, fail_signal).ensure(); set_signal_handler(SignalType::Error, fail_signal).ensure();
set_signal_handler(SignalType::Abort, fail_signal).ensure(); set_signal_handler(SignalType::Abort, fail_signal).ensure();
Log::set_fatal_error_callback(on_fatal_error); ClientManager::set_log_message_callback(0, on_log_message);
init_openssl_threads(); init_openssl_threads();
const char *locale_name = (std::setlocale(LC_ALL, "fr-FR") == nullptr ? "C" : "fr-FR"); const char *locale_name = (std::setlocale(LC_ALL, "fr-FR") == nullptr ? "C" : "fr-FR");

View File

@ -6,6 +6,7 @@
// //
#include "td/telegram/td_json_client.h" #include "td/telegram/td_json_client.h"
#include "td/telegram/Client.h"
#include "td/telegram/ClientJson.h" #include "td/telegram/ClientJson.h"
#include "td/utils/Slice.h" #include "td/utils/Slice.h"
@ -45,3 +46,7 @@ const char *td_receive(double timeout) {
const char *td_execute(const char *request) { const char *td_execute(const char *request) {
return td::json_execute(td::Slice(request == nullptr ? "" : request)); return td::json_execute(td::Slice(request == nullptr ? "" : request));
} }
void td_set_log_message_callback(int max_verbosity_level, td_log_message_callback_ptr callback) {
td::ClientManager::set_log_message_callback(max_verbosity_level, callback);
}

View File

@ -156,6 +156,26 @@ TDJSON_EXPORT const char *td_receive(double timeout);
*/ */
TDJSON_EXPORT const char *td_execute(const char *request); TDJSON_EXPORT const char *td_execute(const char *request);
/**
* A type of callback function that will be called when a message is added to the internal TDLib log.
*
* \param verbosity_level Log verbosity level with which the message was added.
* \param message Null-terminated string with the logged message.
*/
typedef void (*td_log_message_callback_ptr)(int verbosity_level, const char *message);
/**
* Sets the callback that will be called when a message is added to the internal TDLib log.
* None of the TDLib methods can be called from the callback.
* If message verbosity level is 0, then TDLib will crash as soon as callback returns.
* By default the callback is not set.
*
* \param[in] max_verbosity_level Maximum verbosity level of messages for which the callback will be called.
* \param[in] callback Callback that will be called when a message is added to the internal TDLib log.
* Pass nullptr to remove the callback.
*/
TDJSON_EXPORT void td_set_log_message_callback(int max_verbosity_level, td_log_message_callback_ptr callback);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View File

@ -71,6 +71,7 @@ typedef void (*td_log_fatal_error_callback_ptr)(const char *error_message);
* The TDLib will crash as soon as callback returns. * The TDLib will crash as soon as callback returns.
* By default the callback is not set. * By default the callback is not set.
* *
* \deprecated Use td_set_log_message_callback instead.
* \param[in] callback Callback that will be called when a fatal error happens. * \param[in] callback Callback that will be called when a fatal error happens.
* Pass NULL to remove the callback. * Pass NULL to remove the callback.
*/ */

View File

@ -11,3 +11,4 @@ _td_create_client_id
_td_send _td_send
_td_receive _td_receive
_td_execute _td_execute
_td_set_log_message_callback

View File

@ -74,14 +74,14 @@ void FileLog::do_append(int log_level, CSlice slice) {
if (size_ > rotate_threshold_ || want_rotate_.load(std::memory_order_relaxed)) { if (size_ > rotate_threshold_ || want_rotate_.load(std::memory_order_relaxed)) {
auto status = rename(path_, PSLICE() << path_ << ".old"); auto status = rename(path_, PSLICE() << path_ << ".old");
if (status.is_error()) { if (status.is_error()) {
process_fatal_error(PSLICE() << status.error() << " in " << __FILE__ << " at " << __LINE__); process_fatal_error(PSLICE() << status.error() << " in " << __FILE__ << " at " << __LINE__ << '\n');
} }
do_after_rotation(); do_after_rotation();
} }
while (!slice.empty()) { while (!slice.empty()) {
auto r_size = fd_.write(slice); auto r_size = fd_.write(slice);
if (r_size.is_error()) { if (r_size.is_error()) {
process_fatal_error(PSLICE() << r_size.error() << " in " << __FILE__ << " at " << __LINE__); process_fatal_error(PSLICE() << r_size.error() << " in " << __FILE__ << " at " << __LINE__ << '\n');
} }
auto written = r_size.ok(); auto written = r_size.ok();
size_ += static_cast<int64>(written); size_ += static_cast<int64>(written);
@ -107,7 +107,7 @@ void FileLog::do_after_rotation() {
fd_.close(); fd_.close();
auto r_fd = FileFd::open(path_, FileFd::Create | FileFd::Truncate | FileFd::Write); auto r_fd = FileFd::open(path_, FileFd::Create | FileFd::Truncate | FileFd::Write);
if (r_fd.is_error()) { if (r_fd.is_error()) {
process_fatal_error(PSLICE() << r_fd.error() << " in " << __FILE__ << " at " << __LINE__); process_fatal_error(PSLICE() << r_fd.error() << " in " << __FILE__ << " at " << __LINE__ << '\n');
} }
fd_ = r_fd.move_as_ok(); fd_ = r_fd.move_as_ok();
if (!Stderr().empty() && redirect_stderr_) { if (!Stderr().empty() && redirect_stderr_) {

View File

@ -16,7 +16,7 @@ namespace detail {
void process_check_error(const char *message, const char *file, int line) { void process_check_error(const char *message, const char *file, int line) {
::td::Logger(*log_interface, log_options, VERBOSITY_NAME(FATAL), Slice(file), line, Slice()) ::td::Logger(*log_interface, log_options, VERBOSITY_NAME(FATAL), Slice(file), line, Slice())
<< "Check `" << message << "` failed"; << "Check `" << message << "` failed";
::td::process_fatal_error(PSLICE() << "Check `" << message << "` failed in " << file << " at " << line); ::td::process_fatal_error(PSLICE() << "Check `" << message << "` failed in " << file << " at " << line << '\n');
} }
} // namespace detail } // namespace detail

View File

@ -32,25 +32,28 @@ namespace td {
LogOptions log_options; LogOptions log_options;
static std::atomic<int> max_callback_verbosity_level = 0; static std::atomic<int> max_callback_verbosity_level{-2};
static std::atomic<OnLogMessageCallback> on_log_message_callback = nullptr; static std::atomic<OnLogMessageCallback> on_log_message_callback{nullptr};
void set_log_message_callback(int max_verbosity_level, OnLogMessageCallback callback) { void set_log_message_callback(int max_verbosity_level, OnLogMessageCallback callback) {
if (callback == nullptr) {
max_verbosity_level = -2;
}
max_callback_verbosity_level = max_verbosity_level; max_callback_verbosity_level = max_verbosity_level;
on_log_message_callback = callback; on_log_message_callback = callback;
} }
void LogInterface::append(int log_level, CSlice slice) { void LogInterface::append(int log_level, CSlice slice) {
do_append(log_level, slice); do_append(log_level, slice);
if (log_level <= max_callback_verbosity_level.load(std::memory_order_relaxed)) { if (log_level == VERBOSITY_NAME(FATAL)) {
process_fatal_error(slice);
} else if (log_level <= max_callback_verbosity_level.load(std::memory_order_relaxed)) {
auto callback = on_log_message_callback.load(std::memory_order_relaxed); auto callback = on_log_message_callback.load(std::memory_order_relaxed);
if (callback != nullptr) { if (callback != nullptr) {
callback(log_level, slice); callback(log_level, slice);
} }
} }
if (log_level == VERBOSITY_NAME(FATAL)) {
process_fatal_error(slice);
}
} }
TD_THREAD_LOCAL const char *Logger::tag_ = nullptr; TD_THREAD_LOCAL const char *Logger::tag_ = nullptr;
@ -286,17 +289,14 @@ static DefaultLog default_log;
LogInterface *const default_log_interface = &default_log; LogInterface *const default_log_interface = &default_log;
LogInterface *log_interface = default_log_interface; LogInterface *log_interface = default_log_interface;
static OnFatalErrorCallback on_fatal_error_callback = nullptr;
void set_log_fatal_error_callback(OnFatalErrorCallback callback) {
on_fatal_error_callback = callback;
}
void process_fatal_error(CSlice message) { void process_fatal_error(CSlice message) {
auto callback = on_fatal_error_callback; if (0 <= max_callback_verbosity_level.load(std::memory_order_relaxed)) {
if (callback) { auto callback = on_log_message_callback.load(std::memory_order_relaxed);
callback(message); if (callback != nullptr) {
callback(0, message);
}
} }
std::abort(); std::abort();
} }

View File

@ -187,10 +187,6 @@ extern LogInterface *log_interface;
[[noreturn]] void process_fatal_error(CSlice message); [[noreturn]] void process_fatal_error(CSlice message);
// deprecated in favor of set_log_message_callback
using OnFatalErrorCallback = void (*)(CSlice message);
void set_log_fatal_error_callback(OnFatalErrorCallback callback);
using OnLogMessageCallback = void (*)(int verbosity_level, CSlice message); using OnLogMessageCallback = void (*)(int verbosity_level, CSlice message);
void set_log_message_callback(int max_verbosity_level, OnLogMessageCallback callback); void set_log_message_callback(int max_verbosity_level, OnLogMessageCallback callback);