diff --git a/CMakeLists.txt b/CMakeLists.txt index 3627ee3f..151b920a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,6 +110,7 @@ endif() -DPROJECT_ENABLE_LIBSODIUM=${PROJECT_ENABLE_LIBSODIUM} -DPROJECT_ENABLE_OPENSSL=${PROJECT_ENABLE_OPENSSL} -DPROJECT_ENABLE_PUGIXML=${PROJECT_ENABLE_PUGIXML} + -DPROJECT_ENABLE_SPDLOG=${PROJECT_ENABLE_SPDLOG} -DPROJECT_ENABLE_SQLITE=${PROJECT_ENABLE_SQLITE} -DPROJECT_ENABLE_STDUUID=${PROJECT_ENABLE_STDUUID} -DPROJECT_ENABLE_TESTING=${PROJECT_ENABLE_TESTING} diff --git a/cmake/libraries.cmake b/cmake/libraries.cmake index 0e4d1a79..7e1b852f 100644 --- a/cmake/libraries.cmake +++ b/cmake/libraries.cmake @@ -12,6 +12,7 @@ include(cmake/libraries/fuse.cmake) include(cmake/libraries/json.cmake) include(cmake/libraries/libsodium.cmake) include(cmake/libraries/pugixml.cmake) +include(cmake/libraries/spdlog.cmake) include(cmake/libraries/sqlite.cmake) include(cmake/libraries/stduuid.cmake) include(cmake/libraries/testing.cmake) diff --git a/cmake/libraries/spdlog.cmake b/cmake/libraries/spdlog.cmake new file mode 100644 index 00000000..724192e9 --- /dev/null +++ b/cmake/libraries/spdlog.cmake @@ -0,0 +1,33 @@ +if(PROJECT_ENABLE_SPDLOG) + if(PROJECT_BUILD) + find_package(spdlog ${SPDLOG_VERSION} REQUIRED) + + add_definitions(-DPROJECT_ENABLE_SPDLOG) + + include_directories(BEFORE SYSTEM + ${SPDLOG_INCLUDE_DIRS} + ) + + link_libraries( + spdlog::spdlog + ) + elseif(NOT PROJECT_IS_MINGW OR CMAKE_HOST_WIN32) + ExternalProject_Add(spdlog_project + PREFIX external + URL ${PROJECT_3RD_PARTY_DIR}/spdlog-${SPDLOG_VERSION}.tar.gz + URL_HASH SHA256=1586508029a7d0670dfcb2d97575dcdc242d3868a259742b69f100801ab4e16b + LIST_SEPARATOR | + CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS} + -DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS} + -DBUILD_STATIC_LIBS=ON + -DSPDLOG_BUILD_EXAMPLE=OFF + -DSPDLOG_FMT_EXTERNAL=OFF + -DSPDLOG_FMT_EXTERNAL_HO=OFF + ) + + set(PROJECT_DEPENDENCIES + ${PROJECT_DEPENDENCIES} + spdlog_project + ) + endif() +endif() diff --git a/cmake/options.cmake b/cmake/options.cmake index 55fe03f7..669f0e5a 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -6,6 +6,7 @@ option(PROJECT_ENABLE_JSON "Enable JSON for Modern C++ library" OFF) option(PROJECT_ENABLE_LIBSODIUM "Enable libsodium library" OFF) option(PROJECT_ENABLE_OPENSSL "Enable OpenSSL library" OFF) option(PROJECT_ENABLE_PUGIXML "Enable PugiXML library" OFF) +option(PROJECT_ENABLE_SPDLOG "Enable spdlog library" OFF) option(PROJECT_ENABLE_SQLITE "Enable SQLite" OFF) option(PROJECT_ENABLE_STDUUID "Enable stduuid library" OFF) option(PROJECT_ENABLE_TESTING "Enable building unit tests" OFF) diff --git a/config.sh b/config.sh index 5fe52b68..2255f176 100755 --- a/config.sh +++ b/config.sh @@ -27,6 +27,7 @@ PROJECT_ENABLE_JSON=ON PROJECT_ENABLE_LIBSODIUM=ON PROJECT_ENABLE_OPENSSL=ON PROJECT_ENABLE_PUGIXML=ON +PROJECT_ENABLE_SPDLOG=ON PROJECT_ENABLE_SQLITE=ON PROJECT_ENABLE_STDUUID=ON PROJECT_ENABLE_TESTING=ON diff --git a/repertory/librepertory/include/events/consumers/logging_consumer.hpp b/repertory/librepertory/include/events/consumers/logging_consumer.hpp index dd084454..57c8cb7c 100644 --- a/repertory/librepertory/include/events/consumers/logging_consumer.hpp +++ b/repertory/librepertory/include/events/consumers/logging_consumer.hpp @@ -41,26 +41,9 @@ private: private: event_level event_level_; std::string log_directory_; - std::string log_path_; private: - std::deque> event_queue_; - FILE *log_file_{nullptr}; - std::mutex log_mutex_; - std::condition_variable log_notify_; - bool logging_active_{true}; - std::unique_ptr logging_thread_; - -private: - void check_log_roll(std::size_t count); - - void close_log_file(); - - void logging_thread(bool drain); - void process_event(const event &event); - - void reopen_log_file(); }; } // namespace repertory diff --git a/repertory/librepertory/src/events/consumers/logging_consumer.cpp b/repertory/librepertory/src/events/consumers/logging_consumer.cpp index 6a4e2b45..757fb3b8 100644 --- a/repertory/librepertory/src/events/consumers/logging_consumer.cpp +++ b/repertory/librepertory/src/events/consumers/logging_consumer.cpp @@ -21,158 +21,32 @@ */ #include "events/consumers/logging_consumer.hpp" -#include "events/events.hpp" -#include "types/startup_exception.hpp" -#include "utils/error_utils.hpp" -#include "utils/file_utils.hpp" #include "utils/path_utils.hpp" -#include "utils/unix/unix_utils.hpp" -#include "utils/utils.hpp" namespace repertory { logging_consumer::logging_consumer(event_level level, std::string log_directory) : event_level_(level), - log_directory_(utils::path::absolute(log_directory)), - log_path_(utils::path::combine(log_directory, {"repertory.log"})) { - if (not utils::file::create_full_directory_path(log_directory_)) { - throw startup_exception("failed to create log directory|sp|" + - log_directory_ + "|err|" + - std::to_string(utils::get_last_error_code())); - } - - check_log_roll(0); - reopen_log_file(); + log_directory_(utils::path::absolute(log_directory)) { E_SUBSCRIBE_ALL(process_event); E_SUBSCRIBE_EXACT(event_level_changed, [this](const event_level_changed &changed) { event_level_ = event_level_from_string( changed.get_new_event_level().get()); }); - logging_thread_ = - std::make_unique([this] { logging_thread(false); }); } -logging_consumer::~logging_consumer() { - E_CONSUMER_RELEASE(); - - unique_mutex_lock lock(log_mutex_); - logging_active_ = false; - log_notify_.notify_all(); - lock.unlock(); - - logging_thread_->join(); - logging_thread_.reset(); - - logging_thread(true); - close_log_file(); -} - -void logging_consumer::check_log_roll(std::size_t count) { - constexpr const auto *function_name = static_cast(__FUNCTION__); - - std::uint64_t file_size{}; - auto success = utils::file::get_file_size(log_path_, file_size); - if (success && (file_size + count) >= MAX_LOG_FILE_SIZE) { - close_log_file(); - for (std::uint8_t i = MAX_LOG_FILES; i > 0u; i--) { - auto temp_log_path = utils::path::combine( - log_directory_, {"repertory." + std::to_string(i) + ".log"}); - if (utils::file::is_file(temp_log_path)) { - if (i == MAX_LOG_FILES) { - if (not utils::file::retry_delete_file(temp_log_path)) { - // TODO Handle error - } - } else { - auto next_file_path = utils::path::combine( - log_directory_, - {"repertory." + std::to_string(i + std::uint8_t(1)) + ".log"}); - if (not utils::file::move_file(temp_log_path, next_file_path)) { - utils::error::raise_error(function_name, - utils::get_last_error_code(), - temp_log_path + "|dest|" + next_file_path, - "failed to move file"); - } - } - } - } - - auto backup_log_path = - utils::path::combine(log_directory_, {"repertory.1.log"}); - if (not utils::file::move_file(log_path_, backup_log_path)) { - utils::error::raise_error(function_name, utils::get_last_error_code(), - log_path_ + "|dest|" + backup_log_path, - "failed to move file"); - } - reopen_log_file(); - } -} - -void logging_consumer::close_log_file() { - if (log_file_) { - fclose(log_file_); - log_file_ = nullptr; - } -} - -void logging_consumer::logging_thread(bool drain) { - do { - std::deque> events; - { - unique_mutex_lock l(log_mutex_); - if (event_queue_.empty() && not drain) { - log_notify_.wait_for(l, 2s); - } else { - events.insert(events.end(), event_queue_.begin(), event_queue_.end()); - event_queue_.clear(); - } - } - - while (not events.empty()) { - auto event = events.front(); - events.pop_front(); - - if (event->get_event_level() <= event_level_) { - auto msg = ([&]() -> std::string { - struct tm local_time {}; - utils::get_local_time_now(local_time); - - std::stringstream ss; - ss << std::put_time(&local_time, "%F %T") << "|" - << event_level_to_string(event->get_event_level()).c_str() << "|" - << event->get_single_line().c_str() << std::endl; - return ss.str(); - })(); - - check_log_roll(msg.length()); - auto retry = true; - for (int i = 0; retry && (i < 2); i++) { - retry = (not log_file_ || (fwrite(msg.data(), 1, msg.length(), - log_file_) != msg.length())); - if (retry) { - reopen_log_file(); - } - } - - if (log_file_) { - fflush(log_file_); - } - } - } - } while (logging_active_); -} +logging_consumer::~logging_consumer() { E_CONSUMER_RELEASE(); } void logging_consumer::process_event(const event &event) { - mutex_lock lock(log_mutex_); - event_queue_.push_back(event.clone()); - log_notify_.notify_all(); -} + /* auto msg = ([&]() -> std::string { + struct tm local_time {}; + utils::get_local_time_now(local_time); -void logging_consumer::reopen_log_file() { - close_log_file(); -#if defined(_WIN32) - log_file_ = _fsopen(log_path_.c_str(), "a+", _SH_DENYWR); -#else - log_file_ = fopen(log_path_.c_str(), "a+"); -#endif + std::stringstream ss; + ss << std::put_time(&local_time, "%F %T") << "|" + << event_level_to_string(event->get_event_level()).c_str() << "|" + << event->get_single_line().c_str() << std::endl; + return ss.str(); + })(); */ } } // namespace repertory diff --git a/scripts/options.sh b/scripts/options.sh index a83e4de4..9e70d8ad 100755 --- a/scripts/options.sh +++ b/scripts/options.sh @@ -8,6 +8,7 @@ PROJECT_LIBRARIES=( LIBSODIUM OPENSSL PUGIXML + SPDLOG SQLITE STDUUID TESTING @@ -21,6 +22,7 @@ PROJECT_CLEANUP[JSON]="json-*" PROJECT_CLEANUP[LIBSODIUM]="libsodium*" PROJECT_CLEANUP[OPENSSL]="openssl-*" PROJECT_CLEANUP[PUGIXML]="pugixml-*" +PROJECT_CLEANUP[SPDLOG]="spdlog-*" PROJECT_CLEANUP[SQLITE]="sqlite-*" PROJECT_CLEANUP[STDUUID]="stduuid-*" PROJECT_CLEANUP[TESTING]="googletest-*" diff --git a/support/3rd_party/spdlog-1.14.1.tar.gz b/support/3rd_party/spdlog-1.14.1.tar.gz new file mode 100644 index 00000000..a0692e55 Binary files /dev/null and b/support/3rd_party/spdlog-1.14.1.tar.gz differ diff --git a/support/3rd_party/spdlog-1.14.1.tar.gz.sha256 b/support/3rd_party/spdlog-1.14.1.tar.gz.sha256 new file mode 100644 index 00000000..abd59d97 --- /dev/null +++ b/support/3rd_party/spdlog-1.14.1.tar.gz.sha256 @@ -0,0 +1 @@ +1586508029a7d0670dfcb2d97575dcdc242d3868a259742b69f100801ab4e16b *spdlog-1.14.1.tar.gz