diff --git a/CMakeLists.txt b/CMakeLists.txt index 59076775..81df3bf8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,7 +156,7 @@ set(SPDLOG_HEADERS "include/spdlog/details/mpmc_blocking_q.h" "include/spdlog/details/null_mutex.h" "include/spdlog/details/os.h" - "include/spdlog/details/default_err_handler.h" + "include/spdlog/details/err_helper.h" "include/spdlog/bin_to_hex.h" "include/spdlog/sinks/android_sink.h" "include/spdlog/sinks/base_sink.h" @@ -192,7 +192,7 @@ set(SPDLOG_SRCS "src/details/os_filesystem.cpp" "src/details/log_msg.cpp" "src/details/async_log_msg.cpp" - "src/details/default_err_handler.cpp" + "src/details/err_helper.cpp" "src/sinks/base_sink.cpp" "src/sinks/basic_file_sink.cpp" "src/sinks/rotating_file_sink.cpp" diff --git a/include/spdlog/details/default_err_handler.h b/include/spdlog/details/err_helper.h similarity index 71% rename from include/spdlog/details/default_err_handler.h rename to include/spdlog/details/err_helper.h index cfe90634..14138291 100644 --- a/include/spdlog/details/default_err_handler.h +++ b/include/spdlog/details/err_helper.h @@ -11,10 +11,12 @@ // by default, prints the error to stderr, thread safe namespace spdlog { namespace details { -class default_err_handler { - mutable std::mutex mutex_; +class err_helper { + err_handler custom_err_handler_; public: void handle_ex(const std::string& origin, const source_loc& loc, const std::exception& ex) const; + void handle_unknown_ex(const std::string& origin, const source_loc& loc) const; + void set_err_handler(err_handler handler); }; diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 6171bc54..214f48a7 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -16,7 +16,7 @@ #include #include "common.h" -#include "details/default_err_handler.h" +#include "details/err_helper.h" #include "details/log_msg.h" #include "sinks/sink.h" @@ -160,8 +160,7 @@ private: std::vector sinks_; atomic_level_t level_{level::info}; atomic_level_t flush_level_{level::off}; - err_handler custom_err_handler_; - details::default_err_handler default_err_handler_; + details::err_helper err_helper_; // common implementation for after templated public api has been resolved to format string and // args @@ -173,9 +172,9 @@ private: fmt::vformat_to(std::back_inserter(buf), format_string, fmt::make_format_args(args...)); sink_it_(details::log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()))); } catch (const std::exception &ex) { - handle_ex_(loc, ex); + err_helper_.handle_ex(name_, loc, ex); } catch (...) { - handle_unknown_ex_(loc); + err_helper_.handle_unknown_ex(name_, loc); } } @@ -187,9 +186,9 @@ private: try { sink->log(msg); } catch (const std::exception &ex) { - handle_ex_(msg.source, ex); + err_helper_.handle_ex(name_, msg.source, ex); } catch (...) { - handle_unknown_ex_(msg.source); + err_helper_.handle_unknown_ex(name_, msg.source); } } } @@ -200,9 +199,6 @@ private: } void flush_(); [[nodiscard]] bool should_flush_(const details::log_msg &msg) const; - - void handle_ex_(const source_loc &loc, const std::exception &ex) const; - void handle_unknown_ex_(const source_loc &loc) const; }; } // namespace spdlog diff --git a/include/spdlog/sinks/async_sink.h b/include/spdlog/sinks/async_sink.h index 1f3fd14c..47197fc1 100644 --- a/include/spdlog/sinks/async_sink.h +++ b/include/spdlog/sinks/async_sink.h @@ -8,7 +8,7 @@ #include #include "../details/async_log_msg.h" -#include "../details/default_err_handler.h" +#include "../details/err_helper.h" #include "sink.h" // async_sink is a sink that sends log messages to a dist_sink in a separate thread using a queue. @@ -39,6 +39,7 @@ public: std::vector> sinks; std::function on_thread_start = nullptr; std::function on_thread_stop = nullptr; + err_handler err_handler = nullptr; }; explicit async_sink(config async_config); @@ -78,7 +79,7 @@ private: config config_; std::unique_ptr q_; std::thread worker_thread_; - details::default_err_handler err_handler_; + details::err_helper err_helper_; }; } // namespace sinks diff --git a/src/details/default_err_handler.cpp b/src/details/default_err_handler.cpp deleted file mode 100644 index 1eb39dcb..00000000 --- a/src/details/default_err_handler.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#include "iostream" -#include "spdlog/details/default_err_handler.h" -#include "spdlog/details/os.h" - -namespace spdlog { -namespace details { - -// Prints error to stderr with source location (if available). A stderr sink is not used because reaching -// this point might indicate a problem with the logging system itself so we use fputs() directly. -void default_err_handler::handle_ex(const std::string &origin, const source_loc &loc, const std::exception &ex) const { - std::lock_guard lk{mutex_}; - const auto tm_time = os::localtime(); - char date_buf[64]; - std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); - std::string msg; - if (loc.empty()) { - msg = fmt_lib::format("[*** LOGGING ERROR ***] [{}] [{}] {}\n", date_buf, origin, ex.what()); - } else { - msg = fmt_lib::format("[*** LOGGING ERROR ***] [{}({})] [{}] [{}] {}\n", loc.filename, loc.line, date_buf, origin, - ex.what()); - } - std::fputs(msg.c_str(), stderr); -} - -} // namespace details -} // namespace spdlog diff --git a/src/details/err_helper.cpp b/src/details/err_helper.cpp new file mode 100644 index 00000000..153cf988 --- /dev/null +++ b/src/details/err_helper.cpp @@ -0,0 +1,40 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#include "iostream" +#include "spdlog/details/err_helper.h" +#include "spdlog/details/os.h" + +namespace spdlog { +namespace details { + +// Prints error to stderr with source location (if available). A stderr sink is not used because reaching +// this point might indicate a problem with the logging system itself so we use fputs() directly. +void err_helper::handle_ex(const std::string &origin, const source_loc &loc, const std::exception &ex) const { + if (custom_err_handler_) { + custom_err_handler_(ex.what()); + return; + } + const auto tm_time = os::localtime(); + char date_buf[32]; + std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); + std::string msg; + if (loc.empty()) { + msg = fmt_lib::format("[*** LOG ERROR ***] [{}] [{}] {}\n", date_buf, origin, ex.what()); + } else { + msg = fmt_lib::format("[*** LOG ERROR ***] [{}({})] [{}] [{}] {}\n", loc.filename, loc.line, date_buf, origin, + ex.what()); + } + std::fputs(msg.c_str(), stderr); +} + +void err_helper::handle_unknown_ex(const std::string &origin, const source_loc &loc) const { + handle_ex(origin, loc, std::runtime_error("unknown exception")); +} + +void err_helper::set_err_handler(err_handler handler) { + custom_err_handler_ = std::move(handler); +} + +} // namespace details +} // namespace spdlog diff --git a/src/logger.cpp b/src/logger.cpp index 93c92fa8..ee8fef21 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -14,14 +14,14 @@ logger::logger(const logger &other) noexcept sinks_(other.sinks_), level_(other.level_.load(std::memory_order_relaxed)), flush_level_(other.flush_level_.load(std::memory_order_relaxed)), - custom_err_handler_(other.custom_err_handler_) {} + err_helper_(other.err_helper_) {} logger::logger(logger &&other) noexcept : name_(std::move(other.name_)), sinks_(std::move(other.sinks_)), level_(other.level_.load(std::memory_order_relaxed)), flush_level_(other.flush_level_.load(std::memory_order_relaxed)), - custom_err_handler_(std::move(other.custom_err_handler_)) {} + err_helper_(std::move(other.err_helper_)) {} void logger::set_level(level level) { level_.store(level); } @@ -60,7 +60,7 @@ const std::vector &logger::sinks() const { return sinks_; } std::vector &logger::sinks() { return sinks_; } // custom error handler -void logger::set_error_handler(err_handler handler) { custom_err_handler_ = std::move(handler); } +void logger::set_error_handler(err_handler handler) { err_helper_.set_err_handler(std::move(handler)); } // create new logger with same sinks and configuration. std::shared_ptr logger::clone(std::string logger_name) { @@ -75,32 +75,16 @@ void logger::flush_() { try { sink->flush(); } catch (const std::exception &ex) { - handle_ex_(source_loc{}, ex); + err_helper_.handle_ex(name_, source_loc{}, ex); } catch (...) { - handle_unknown_ex_(source_loc{}); + err_helper_.handle_unknown_ex(name_, source_loc{}); } } } bool logger::should_flush_(const details::log_msg &msg) const { - auto flush_level = flush_level_.load(std::memory_order_relaxed); + const auto flush_level = flush_level_.load(std::memory_order_relaxed); return (msg.log_level >= flush_level) && (msg.log_level != level::off); } -void logger::handle_ex_(const source_loc &loc, const std::exception &ex) const { - if (custom_err_handler_) { - custom_err_handler_(ex.what()); - return; - } - default_err_handler_.handle_ex(name_, loc, ex); -} - -void logger::handle_unknown_ex_(const source_loc &loc) const { - if (custom_err_handler_) { - custom_err_handler_("unknown exception"); - return; - } - default_err_handler_.handle_ex(name_, loc, std::runtime_error("Unknown exception")); -} - } // namespace spdlog diff --git a/src/sinks/async_sink.cpp b/src/sinks/async_sink.cpp index b59d4baa..6a7f6f99 100644 --- a/src/sinks/async_sink.cpp +++ b/src/sinks/async_sink.cpp @@ -107,7 +107,9 @@ void async_sink::backend_log_(const details::log_msg &msg) { try { sink->log(msg); } catch (const std::exception &ex) { - err_handler_.handle_ex("async log", msg.source, ex); + err_helper_.handle_ex("async log", msg.source, ex); + } catch (...) { + err_helper_.handle_unknown_ex("async log", source_loc{}); } } } @@ -118,9 +120,9 @@ void async_sink::backend_flush_() { try { sink->flush(); } catch (const std::exception &ex) { - err_handler_.handle_ex("async flush", source_loc{}, ex); + err_helper_.handle_ex("async flush", source_loc{}, ex); } catch (...) { - err_handler_.handle_ex("async flush", source_loc{}, std::runtime_error("Unknown exception during flush")); + err_helper_.handle_unknown_ex("async flush", source_loc{}); } } }