summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/tdutils/td/utils/logging.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Telegram/tdlib/td/tdutils/td/utils/logging.cpp')
-rw-r--r--protocols/Telegram/tdlib/td/tdutils/td/utils/logging.cpp238
1 files changed, 238 insertions, 0 deletions
diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/logging.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/logging.cpp
new file mode 100644
index 0000000000..17403ff87b
--- /dev/null
+++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/logging.cpp
@@ -0,0 +1,238 @@
+//
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
+//
+// 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/utils/logging.h"
+
+#include "td/utils/port/Clocks.h"
+#include "td/utils/port/Fd.h"
+#include "td/utils/port/thread_local.h"
+#include "td/utils/Slice.h"
+#include "td/utils/Time.h"
+
+#include <atomic>
+#include <cstdlib>
+
+#if TD_ANDROID
+#include <android/log.h>
+#define ALOG_TAG "DLTD"
+#elif TD_TIZEN
+#include <dlog.h>
+#define DLOG_TAG "DLTD"
+#elif TD_EMSCRIPTEN
+#include <emscripten.h>
+#endif
+
+namespace td {
+
+int VERBOSITY_NAME(level) = VERBOSITY_NAME(DEBUG) + 1;
+int VERBOSITY_NAME(net_query) = VERBOSITY_NAME(INFO);
+int VERBOSITY_NAME(td_requests) = VERBOSITY_NAME(INFO);
+int VERBOSITY_NAME(dc) = VERBOSITY_NAME(DEBUG) + 2;
+int VERBOSITY_NAME(files) = VERBOSITY_NAME(DEBUG) + 2;
+int VERBOSITY_NAME(mtproto) = VERBOSITY_NAME(DEBUG) + 7;
+int VERBOSITY_NAME(connections) = VERBOSITY_NAME(DEBUG) + 8;
+int VERBOSITY_NAME(raw_mtproto) = VERBOSITY_NAME(DEBUG) + 10;
+int VERBOSITY_NAME(fd) = VERBOSITY_NAME(DEBUG) + 9;
+int VERBOSITY_NAME(actor) = VERBOSITY_NAME(DEBUG) + 10;
+int VERBOSITY_NAME(buffer) = VERBOSITY_NAME(DEBUG) + 10;
+int VERBOSITY_NAME(sqlite) = VERBOSITY_NAME(DEBUG) + 10;
+
+TD_THREAD_LOCAL const char *Logger::tag_ = nullptr;
+TD_THREAD_LOCAL const char *Logger::tag2_ = nullptr;
+
+Logger::Logger(LogInterface &log, int log_level, Slice file_name, int line_num, Slice comment, bool simple_mode)
+ : Logger(log, log_level, simple_mode) {
+ if (simple_mode) {
+ return;
+ }
+
+ auto last_slash_ = static_cast<int32>(file_name.size()) - 1;
+ while (last_slash_ >= 0 && file_name[last_slash_] != '/' && file_name[last_slash_] != '\\') {
+ last_slash_--;
+ }
+ file_name = file_name.substr(last_slash_ + 1);
+
+ auto thread_id = get_thread_id();
+
+ (*this) << '[';
+ if (log_level < 10) {
+ (*this) << ' ';
+ }
+ (*this) << log_level << "][t";
+ if (thread_id < 10) {
+ (*this) << ' ';
+ }
+ (*this) << thread_id << "][" << StringBuilder::FixedDouble(Clocks::system(), 9) << "][" << file_name << ':'
+ << line_num << ']';
+ if (tag_ != nullptr && *tag_) {
+ (*this) << "[#" << Slice(tag_) << "]";
+ }
+ if (tag2_ != nullptr && *tag2_) {
+ (*this) << "[!" << Slice(tag2_) << "]";
+ }
+ if (!comment.empty()) {
+ (*this) << "[&" << comment << "]";
+ }
+ (*this) << "\t";
+}
+
+Logger::~Logger() {
+ if (!simple_mode_) {
+ sb_ << '\n';
+ auto slice = as_cslice();
+ if (slice.back() != '\n') {
+ slice.back() = '\n';
+ }
+ }
+
+ log_.append(as_cslice(), log_level_);
+}
+
+TsCerr::TsCerr() {
+ enterCritical();
+}
+TsCerr::~TsCerr() {
+ exitCritical();
+}
+TsCerr &TsCerr::operator<<(Slice slice) {
+ auto &fd = Fd::Stderr();
+ if (fd.empty()) {
+ return *this;
+ }
+ double end_time = 0;
+ while (!slice.empty()) {
+ auto res = fd.write(slice);
+ if (res.is_error()) {
+ if (res.error().code() == EPIPE) {
+ break;
+ }
+ // Resource temporary unavailable
+ if (end_time == 0) {
+ end_time = Time::now() + 0.01;
+ } else if (Time::now() > end_time) {
+ break;
+ }
+ continue;
+ }
+ slice.remove_prefix(res.ok());
+ }
+ return *this;
+}
+
+void TsCerr::enterCritical() {
+ while (lock_.test_and_set(std::memory_order_acquire)) {
+ // spin
+ }
+}
+
+void TsCerr::exitCritical() {
+ lock_.clear(std::memory_order_release);
+}
+TsCerr::Lock TsCerr::lock_ = ATOMIC_FLAG_INIT;
+
+class DefaultLog : public LogInterface {
+ public:
+ void append(CSlice slice, int log_level) override {
+#if TD_ANDROID
+ switch (log_level) {
+ case VERBOSITY_NAME(FATAL):
+ __android_log_write(ANDROID_LOG_FATAL, ALOG_TAG, slice.c_str());
+ break;
+ case VERBOSITY_NAME(ERROR):
+ __android_log_write(ANDROID_LOG_ERROR, ALOG_TAG, slice.c_str());
+ break;
+ case VERBOSITY_NAME(WARNING):
+ __android_log_write(ANDROID_LOG_WARN, ALOG_TAG, slice.c_str());
+ break;
+ case VERBOSITY_NAME(INFO):
+ __android_log_write(ANDROID_LOG_INFO, ALOG_TAG, slice.c_str());
+ break;
+ default:
+ __android_log_write(ANDROID_LOG_DEBUG, ALOG_TAG, slice.c_str());
+ break;
+ }
+#elif TD_TIZEN
+ switch (log_level) {
+ case VERBOSITY_NAME(FATAL):
+ dlog_print(DLOG_ERROR, DLOG_TAG, slice.c_str());
+ break;
+ case VERBOSITY_NAME(ERROR):
+ dlog_print(DLOG_ERROR, DLOG_TAG, slice.c_str());
+ break;
+ case VERBOSITY_NAME(WARNING):
+ dlog_print(DLOG_WARN, DLOG_TAG, slice.c_str());
+ break;
+ case VERBOSITY_NAME(INFO):
+ dlog_print(DLOG_INFO, DLOG_TAG, slice.c_str());
+ break;
+ default:
+ dlog_print(DLOG_DEBUG, DLOG_TAG, slice.c_str());
+ break;
+ }
+#elif TD_EMSCRIPTEN
+ switch (log_level) {
+ case VERBOSITY_NAME(FATAL):
+ emscripten_log(
+ EM_LOG_ERROR | EM_LOG_CONSOLE | EM_LOG_C_STACK | EM_LOG_JS_STACK | EM_LOG_DEMANGLE | EM_LOG_FUNC_PARAMS,
+ "%s", slice.c_str());
+ EM_ASM(throw(UTF8ToString($0)), slice.c_str());
+ break;
+ case VERBOSITY_NAME(ERROR):
+ emscripten_log(EM_LOG_ERROR | EM_LOG_CONSOLE, "%s", slice.c_str());
+ break;
+ case VERBOSITY_NAME(WARNING):
+ emscripten_log(EM_LOG_WARN | EM_LOG_CONSOLE, "%s", slice.c_str());
+ break;
+ default:
+ emscripten_log(EM_LOG_CONSOLE, "%s", slice.c_str());
+ break;
+ }
+#elif !TD_WINDOWS
+ Slice color;
+ switch (log_level) {
+ case VERBOSITY_NAME(FATAL):
+ case VERBOSITY_NAME(ERROR):
+ color = TC_RED;
+ break;
+ case VERBOSITY_NAME(WARNING):
+ color = TC_YELLOW;
+ break;
+ case VERBOSITY_NAME(INFO):
+ color = TC_CYAN;
+ break;
+ }
+ TsCerr() << color << slice << TC_EMPTY;
+#else
+ // TODO: color
+ TsCerr() << slice;
+#endif
+ if (log_level == VERBOSITY_NAME(FATAL)) {
+ process_fatal_error(slice);
+ }
+ }
+ void rotate() override {
+ }
+};
+static DefaultLog default_log;
+
+LogInterface *const default_log_interface = &default_log;
+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) {
+ auto callback = on_fatal_error_callback;
+ if (callback) {
+ callback(message);
+ }
+ std::abort();
+}
+
+} // namespace td