mirror of
https://github.com/gabime/spdlog.git
synced 2025-01-12 17:00:25 +08:00
noexcept
This commit is contained in:
parent
7dfb474632
commit
ffbb35368d
@ -14,8 +14,8 @@ namespace details {
|
||||
class SPDLOG_API 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 handle_ex(const std::string& origin, const source_loc& loc, const std::exception& ex) const noexcept;
|
||||
void handle_unknown_ex(const std::string& origin, const source_loc& loc) const noexcept;
|
||||
void set_err_handler(err_handler handler);
|
||||
};
|
||||
|
||||
|
@ -48,81 +48,81 @@ public:
|
||||
~logger() = default;
|
||||
|
||||
template <typename... Args>
|
||||
void log(const source_loc &loc, level lvl, format_string_t<Args...> fmt, Args &&...args) {
|
||||
void log(const source_loc &loc, level lvl, format_string_t<Args...> fmt, Args &&...args) noexcept {
|
||||
if (should_log(lvl)) {
|
||||
log_with_format_(loc, lvl, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void log(level lvl, format_string_t<Args...> fmt, Args &&...args) {
|
||||
void log(level lvl, format_string_t<Args...> fmt, Args &&...args) noexcept {
|
||||
if (should_log(lvl)) {
|
||||
log_with_format_(source_loc{}, lvl, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
// log with no format string, just string message
|
||||
void log(const source_loc &loc, level lvl, string_view_t msg) {
|
||||
void log(const source_loc &loc, level lvl, string_view_t msg) noexcept {
|
||||
if (should_log(lvl)) {
|
||||
sink_it_(details::log_msg(loc, name_, lvl, msg));
|
||||
}
|
||||
}
|
||||
|
||||
void log(level lvl, string_view_t msg) {
|
||||
void log(level lvl, string_view_t msg) noexcept {
|
||||
if (should_log(lvl)) {
|
||||
sink_it_(details::log_msg(source_loc{}, name_, lvl, msg));
|
||||
}
|
||||
}
|
||||
|
||||
// support for custom time
|
||||
void log(log_clock::time_point log_time, const source_loc &loc, level lvl, string_view_t msg) {
|
||||
void log(log_clock::time_point log_time, const source_loc &loc, level lvl, string_view_t msg) noexcept {
|
||||
if (should_log(lvl)) {
|
||||
sink_it_(details::log_msg(log_time, loc, name_, lvl, msg));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void trace(format_string_t<Args...> fmt, Args &&...args) {
|
||||
void trace(format_string_t<Args...> fmt, Args &&...args) noexcept {
|
||||
log(level::trace, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void debug(format_string_t<Args...> fmt, Args &&...args) {
|
||||
void debug(format_string_t<Args...> fmt, Args &&...args) noexcept {
|
||||
log(level::debug, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void info(format_string_t<Args...> fmt, Args &&...args) {
|
||||
void info(format_string_t<Args...> fmt, Args &&...args) noexcept {
|
||||
log(level::info, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void warn(format_string_t<Args...> fmt, Args &&...args) {
|
||||
void warn(format_string_t<Args...> fmt, Args &&...args) noexcept {
|
||||
log(level::warn, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void error(format_string_t<Args...> fmt, Args &&...args) {
|
||||
void error(format_string_t<Args...> fmt, Args &&...args) noexcept {
|
||||
log(level::err, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void critical(format_string_t<Args...> fmt, Args &&...args) {
|
||||
void critical(format_string_t<Args...> fmt, Args &&...args) noexcept {
|
||||
log(level::critical, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// log functions with no format string, just string
|
||||
void trace(string_view_t msg) { log(level::trace, msg); }
|
||||
void debug(string_view_t msg) { log(level::debug, msg); }
|
||||
void info(string_view_t msg) { log(level::info, msg); }
|
||||
void warn(string_view_t msg) { log(level::warn, msg); }
|
||||
void error(string_view_t msg) { log(level::err, msg); }
|
||||
void critical(string_view_t msg) { log(level::critical, msg); }
|
||||
void trace(string_view_t msg) noexcept { log(level::trace, msg); }
|
||||
void debug(string_view_t msg) noexcept { log(level::debug, msg); }
|
||||
void info(string_view_t msg) noexcept { log(level::info, msg); }
|
||||
void warn(string_view_t msg) noexcept { log(level::warn, msg); }
|
||||
void error(string_view_t msg) noexcept { log(level::err, msg); }
|
||||
void critical(string_view_t msg) noexcept { log(level::critical, msg); }
|
||||
|
||||
// return true if logging is enabled for the given level.
|
||||
[[nodiscard]] bool should_log(level msg_level) const { return msg_level >= level_.load(std::memory_order_relaxed); }
|
||||
[[nodiscard]] bool should_log(level msg_level) const noexcept { return msg_level >= level_.load(std::memory_order_relaxed); }
|
||||
|
||||
// return true if the given message should be flushed
|
||||
[[nodiscard]] bool should_flush(const details::log_msg &msg) const {
|
||||
[[nodiscard]] bool should_flush(const details::log_msg &msg) const noexcept {
|
||||
return (msg.log_level >= flush_level_.load(std::memory_order_relaxed)) && (msg.log_level != level::off);
|
||||
}
|
||||
|
||||
@ -130,10 +130,10 @@ public:
|
||||
void set_level(level level);
|
||||
|
||||
// return the active log level
|
||||
[[nodiscard]] level log_level() const;
|
||||
[[nodiscard]] level log_level() const noexcept;
|
||||
|
||||
// return the name of the logger
|
||||
[[nodiscard]] const std::string &name() const;
|
||||
[[nodiscard]] const std::string &name() const noexcept;
|
||||
|
||||
// set formatting for the sinks in this logger.
|
||||
// each sink will get a separate instance of the formatter object.
|
||||
@ -146,15 +146,15 @@ public:
|
||||
void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local);
|
||||
|
||||
// flush functions
|
||||
void flush();
|
||||
void flush_on(level level);
|
||||
[[nodiscard]] level flush_level() const;
|
||||
void flush() noexcept;
|
||||
void flush_on(level level) noexcept;
|
||||
[[nodiscard]] level flush_level() const noexcept;
|
||||
|
||||
// sinks
|
||||
[[nodiscard]] const std::vector<sink_ptr> &sinks() const;
|
||||
[[nodiscard]] std::vector<sink_ptr> &sinks();
|
||||
[[nodiscard]] const std::vector<sink_ptr> &sinks() const noexcept;
|
||||
[[nodiscard]] std::vector<sink_ptr> &sinks() noexcept;
|
||||
|
||||
// error handler
|
||||
// error handler. default is err_handler that prints the error to stderr.
|
||||
void set_error_handler(err_handler);
|
||||
|
||||
// create new logger with same sinks and configuration.
|
||||
@ -170,7 +170,10 @@ private:
|
||||
// common implementation for after templated public api has been resolved to format string and
|
||||
// args
|
||||
template <typename... Args>
|
||||
void log_with_format_(const source_loc &loc, const level lvl, const format_string_t<Args...> &format_string, Args &&...args) {
|
||||
void log_with_format_(const source_loc &loc,
|
||||
const level lvl,
|
||||
const format_string_t<Args...> &format_string,
|
||||
Args &&...args) noexcept {
|
||||
assert(should_log(lvl));
|
||||
try {
|
||||
memory_buf_t buf;
|
||||
@ -184,7 +187,7 @@ private:
|
||||
}
|
||||
|
||||
// log the given message (if the given log level is high enough)
|
||||
void sink_it_(const details::log_msg &msg) {
|
||||
void sink_it_(const details::log_msg &msg) noexcept {
|
||||
assert(should_log(msg.log_level));
|
||||
for (auto &sink : sinks_) {
|
||||
if (sink->should_log(msg.log_level)) {
|
||||
@ -202,7 +205,7 @@ private:
|
||||
flush_();
|
||||
}
|
||||
}
|
||||
void flush_();
|
||||
void flush_() noexcept;
|
||||
};
|
||||
|
||||
} // namespace spdlog
|
||||
|
@ -1,8 +1,9 @@
|
||||
// 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 "iostream"
|
||||
#include "spdlog/details/os.h"
|
||||
|
||||
namespace spdlog {
|
||||
@ -10,31 +11,35 @@ 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;
|
||||
void err_helper::handle_ex(const std::string &origin, const source_loc &loc, const std::exception &ex) const noexcept {
|
||||
try {
|
||||
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);
|
||||
} catch (const std::exception &handler_ex) {
|
||||
std::fprintf(stderr, "[*** LOG ERROR ***] [%s] caught exception during error handler: %s\n", origin.c_str(), handler_ex.what());
|
||||
} catch (...) { // catch all exceptions
|
||||
std::fprintf(stderr, "[*** LOG ERROR ***] [%s] caught unknown exception during error handler\n", origin.c_str());
|
||||
}
|
||||
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 {
|
||||
void err_helper::handle_unknown_ex(const std::string &origin, const source_loc &loc) const noexcept {
|
||||
handle_ex(origin, loc, std::runtime_error("unknown exception"));
|
||||
}
|
||||
|
||||
void err_helper::set_err_handler(err_handler handler) {
|
||||
custom_err_handler_ = std::move(handler);
|
||||
}
|
||||
void err_helper::set_err_handler(err_handler handler) { custom_err_handler_ = std::move(handler); }
|
||||
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
||||
|
@ -25,7 +25,7 @@ logger::logger(logger &&other) noexcept
|
||||
|
||||
void logger::set_level(level level) { level_.store(level); }
|
||||
|
||||
level logger::log_level() const { return level_.load(std::memory_order_relaxed); }
|
||||
level logger::log_level() const noexcept { return level_.load(std::memory_order_relaxed); }
|
||||
|
||||
const std::string &logger::name() const { return name_; }
|
||||
|
||||
@ -48,16 +48,16 @@ void logger::set_pattern(std::string pattern, pattern_time_type time_type) {
|
||||
}
|
||||
|
||||
// flush functions
|
||||
void logger::flush() { flush_(); }
|
||||
void logger::flush() noexcept { flush_(); }
|
||||
|
||||
void logger::flush_on(level level) { flush_level_.store(level); }
|
||||
void logger::flush_on(level level) noexcept { flush_level_.store(level); }
|
||||
|
||||
level logger::flush_level() const { return flush_level_.load(std::memory_order_relaxed); }
|
||||
level logger::flush_level() const noexcept { return flush_level_.load(std::memory_order_relaxed); }
|
||||
|
||||
// sinks
|
||||
const std::vector<sink_ptr> &logger::sinks() const { return sinks_; }
|
||||
const std::vector<sink_ptr> &logger::sinks() const noexcept { return sinks_; }
|
||||
|
||||
std::vector<sink_ptr> &logger::sinks() { return sinks_; }
|
||||
std::vector<sink_ptr> &logger::sinks() noexcept { return sinks_; }
|
||||
|
||||
// custom error handler
|
||||
void logger::set_error_handler(err_handler handler) { err_helper_.set_err_handler(std::move(handler)); }
|
||||
@ -70,7 +70,7 @@ std::shared_ptr<logger> logger::clone(std::string logger_name) {
|
||||
}
|
||||
|
||||
// private/protected methods
|
||||
void logger::flush_() {
|
||||
void logger::flush_() noexcept{
|
||||
for (auto &sink : sinks_) {
|
||||
try {
|
||||
sink->flush();
|
||||
|
@ -34,32 +34,31 @@ TEST_CASE("default_error_handler", "[errors]") {
|
||||
|
||||
TEST_CASE("custom_error_handler", "[errors]") {
|
||||
prepare_logdir();
|
||||
auto logger = spdlog::create<basic_file_sink_mt>("test-error", log_filename);
|
||||
auto logger = spdlog::create<basic_file_sink_mt>("test-format-error", log_filename);
|
||||
logger->flush_on(spdlog::level::info);
|
||||
logger->set_error_handler([=](const std::string & msg) {
|
||||
REQUIRE(msg == "argument not found");
|
||||
throw custom_ex();
|
||||
});
|
||||
logger->info("Good message #1");
|
||||
REQUIRE_THROWS_AS(logger->info(SPDLOG_FMT_RUNTIME("Bad format msg {} {}"), "xxx"), custom_ex);
|
||||
REQUIRE_NOTHROW(logger->info(SPDLOG_FMT_RUNTIME("Bad format msg {} {}"), "xxx"));
|
||||
logger->info("Good message #2");
|
||||
require_message_count(log_filename, 2);
|
||||
}
|
||||
|
||||
TEST_CASE("default_error_handler2", "[errors]") {
|
||||
auto logger = std::make_shared<spdlog::logger>("failed_logger", std::make_shared<failing_sink>());
|
||||
auto logger = std::make_shared<spdlog::logger>("test-failing-sink", std::make_shared<failing_sink>());
|
||||
logger->set_error_handler([=](const std::string &msg) {
|
||||
REQUIRE(msg == log_err_msg);
|
||||
throw custom_ex();
|
||||
});
|
||||
REQUIRE_THROWS_AS(logger->info("Some message"), custom_ex);
|
||||
REQUIRE_NOTHROW(logger->info("Some message"));
|
||||
}
|
||||
|
||||
TEST_CASE("flush_error_handler", "[errors]") {
|
||||
auto logger = spdlog::create<failing_sink>("failed_logger");
|
||||
auto logger = spdlog::create<failing_sink>("test-failing-sink");
|
||||
logger->set_error_handler([=](const std::string &msg) {
|
||||
REQUIRE(msg == flush_err_msg);
|
||||
throw custom_ex();
|
||||
});
|
||||
REQUIRE_THROWS_AS(logger->flush(), custom_ex);
|
||||
REQUIRE_NOTHROW(logger->flush());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user