Refactored error handler
This commit is contained in:
parent
4b74c84354
commit
ea1bcdb0f9
@ -5,6 +5,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <exception>
|
||||
#include "spdlog/common.h"
|
||||
|
||||
// by default, prints the error to stderr, thread safe
|
||||
@ -13,7 +14,7 @@ namespace details {
|
||||
class default_err_handler {
|
||||
mutable std::mutex mutex_;
|
||||
public:
|
||||
void handle(const std::string& origin, const source_loc& loc, const std::string &err_msg) const;
|
||||
void handle_ex(const std::string& origin, const source_loc& loc, const std::exception& ex) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -3,20 +3,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// Thread safe logger, Except for the following methods which are not thread-safe:
|
||||
// set_pattern()
|
||||
// set_formatter()
|
||||
// set_error_handler()
|
||||
// sinks() non const version
|
||||
// Has name, log level, vector of std::shared sink pointers and formatter
|
||||
// Upon each log write the logger:
|
||||
// 1. Checks if its log level is enough to log the message and if yes:
|
||||
// 2. Call the underlying sinks to do the job.
|
||||
// 3. Each sink use its own private copy of a formatter to format the message
|
||||
// and send to its destination.
|
||||
//
|
||||
// The use of private formatter per sink provides the opportunity to cache some
|
||||
// formatted data, and support for different format per sink.
|
||||
// Thread-safe logger, with exceptions for these non-thread-safe methods:
|
||||
// set_pattern() - Modifies the log pattern.
|
||||
// set_formatter() - Sets a new formatter.
|
||||
// set_error_handler() - Assigns a new error handler.
|
||||
// sinks() (non-const) - Accesses and potentially modifies the sinks directly.
|
||||
// By default, the logger does not throw exceptions during logging.
|
||||
// To enable exception throwing for logging errors, set a custom error handler.
|
||||
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
@ -179,12 +172,10 @@ private:
|
||||
memory_buf_t buf;
|
||||
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_error_(loc, ex.what()); \
|
||||
} \
|
||||
catch (...) { \
|
||||
handle_error_(loc, "Unknown exception"); \
|
||||
} catch (const std::exception &ex) {
|
||||
handle_ex_(loc, ex);
|
||||
} catch (...) {
|
||||
handle_unknown_ex_(loc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,12 +186,10 @@ private:
|
||||
if (sink->should_log(msg.log_level)) {
|
||||
try {
|
||||
sink->log(msg);
|
||||
}
|
||||
catch (const std::exception &ex) { \
|
||||
handle_error_(msg.source, ex.what()); \
|
||||
} \
|
||||
catch (...) { \
|
||||
handle_error_(msg.source, "Unknown exception"); \
|
||||
} catch (const std::exception &ex) {
|
||||
handle_ex_(msg.source, ex);
|
||||
} catch (...) {
|
||||
handle_unknown_ex_(msg.source);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -212,7 +201,8 @@ private:
|
||||
void flush_();
|
||||
[[nodiscard]] bool should_flush_(const details::log_msg &msg) const;
|
||||
|
||||
void handle_error_(const source_loc& loc, const std::string &err_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
|
||||
|
@ -8,17 +8,18 @@
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
|
||||
void default_err_handler::handle(const std::string &origin, const source_loc &loc, const std::string &err_msg) const {
|
||||
// print error to stderr with source location if present
|
||||
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[128];
|
||||
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, err_msg);
|
||||
}
|
||||
else {
|
||||
msg = fmt_lib::format("[*** LOGGING ERROR ***] [{}({})] [{}] [{}] {}\n", loc.filename, loc.line, date_buf, origin, err_msg);
|
||||
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);
|
||||
}
|
||||
|
@ -60,9 +60,7 @@ const std::vector<sink_ptr> &logger::sinks() const { return sinks_; }
|
||||
std::vector<sink_ptr> &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) { custom_err_handler_ = std::move(handler); }
|
||||
|
||||
// create new logger with same sinks and configuration.
|
||||
std::shared_ptr<logger> logger::clone(std::string logger_name) {
|
||||
@ -76,12 +74,10 @@ void logger::flush_() {
|
||||
for (auto &sink : sinks_) {
|
||||
try {
|
||||
sink->flush();
|
||||
}
|
||||
catch (const std::exception &ex) { \
|
||||
handle_error_(source_loc{}, ex.what()); \
|
||||
} \
|
||||
catch (...) { \
|
||||
handle_error_(source_loc{}, "Unknown exception"); \
|
||||
} catch (const std::exception &ex) {
|
||||
handle_ex_(source_loc{}, ex);
|
||||
} catch (...) {
|
||||
handle_unknown_ex_(source_loc{});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -91,12 +87,20 @@ bool logger::should_flush_(const details::log_msg &msg) const {
|
||||
return (msg.log_level >= flush_level) && (msg.log_level != level::off);
|
||||
}
|
||||
|
||||
void logger::handle_error_(const source_loc &loc, const std::string &err_msg) const {
|
||||
void logger::handle_ex_(const source_loc &loc, const std::exception &ex) const {
|
||||
if (custom_err_handler_) {
|
||||
custom_err_handler_(err_msg);
|
||||
custom_err_handler_(ex.what());
|
||||
return;
|
||||
}
|
||||
default_err_handler_.handle(name_, loc, err_msg);
|
||||
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
|
||||
|
@ -107,7 +107,7 @@ void async_sink::backend_log_(const details::log_msg &msg) {
|
||||
try {
|
||||
sink->log(msg);
|
||||
} catch (const std::exception &ex) {
|
||||
err_handler_.handle("async", msg.source, std::string("async log failed: ") + ex.what());
|
||||
err_handler_.handle_ex("async log", msg.source, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,9 +118,9 @@ void async_sink::backend_flush_() {
|
||||
try {
|
||||
sink->flush();
|
||||
} catch (const std::exception &ex) {
|
||||
err_handler_.handle("async", source_loc{}, std::string("async flush failed: ") + ex.what());
|
||||
err_handler_.handle_ex("async flush", source_loc{}, ex);
|
||||
} catch (...) {
|
||||
err_handler_.handle("async", source_loc{}, "Async flush failed with unknown exception");
|
||||
err_handler_.handle_ex("async flush", source_loc{}, std::runtime_error("Unknown exception during flush"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user