refactor(logger): use std::source_location

This commit is contained in:
Marcus Holland-Moritz 2024-10-19 12:54:00 +02:00
parent 10c943f9c7
commit 6b0ec7f880
3 changed files with 87 additions and 90 deletions

View File

@ -29,8 +29,8 @@
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <source_location>
#include <sstream> #include <sstream>
#include <stdexcept>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <tuple> #include <tuple>
@ -62,8 +62,8 @@ class logger {
virtual ~logger() = default; virtual ~logger() = default;
virtual void write(level_type level, const std::string& output, virtual void write(level_type level, std::string_view output,
char const* file, int line) = 0; std::source_location loc) = 0;
std::string_view policy_name() const { return policy_name_; } std::string_view policy_name() const { return policy_name_; }
@ -98,8 +98,8 @@ class stream_logger : public logger {
stream_logger(std::shared_ptr<terminal const> term, std::ostream& os, stream_logger(std::shared_ptr<terminal const> term, std::ostream& os,
logger_options const& options = {}); logger_options const& options = {});
void write(level_type level, const std::string& output, char const* file, void write(level_type level, std::string_view output,
int line) override; std::source_location loc) override;
void set_threshold(level_type threshold); void set_threshold(level_type threshold);
void set_with_context(bool with_context) { with_context_ = with_context; } void set_with_context(bool with_context) { with_context_ = with_context; }
@ -129,21 +129,20 @@ class null_logger : public logger {
public: public:
null_logger(); null_logger();
void write(level_type, const std::string&, char const*, int) override {} void write(level_type, std::string_view, std::source_location) override {}
}; };
class level_log_entry { class level_log_entry {
public: public:
level_log_entry(logger& lgr, logger::level_type level, level_log_entry(logger& lgr, logger::level_type level,
char const* file = nullptr, int line = 0) std::source_location loc)
: lgr_(lgr) : lgr_(lgr)
, level_(level) , level_(level)
, file_(file) , loc_(loc) {}
, line_(line) {}
level_log_entry(level_log_entry const&) = delete; level_log_entry(level_log_entry const&) = delete;
~level_log_entry() { lgr_.write(level_, oss_.str(), file_, line_); } ~level_log_entry() { lgr_.write(level_, oss_.str(), loc_); }
template <typename T> template <typename T>
level_log_entry& operator<<(const T& val) { level_log_entry& operator<<(const T& val) {
@ -155,8 +154,7 @@ class level_log_entry {
logger& lgr_; logger& lgr_;
std::ostringstream oss_; std::ostringstream oss_;
logger::level_type const level_; logger::level_type const level_;
char const* const file_; std::source_location const loc_;
int const line_;
}; };
class timed_level_log_entry { class timed_level_log_entry {
@ -164,14 +162,12 @@ class timed_level_log_entry {
using thread_clock = boost::chrono::thread_clock; using thread_clock = boost::chrono::thread_clock;
timed_level_log_entry(logger& lgr, logger::level_type level, timed_level_log_entry(logger& lgr, logger::level_type level,
char const* file = nullptr, int line = 0, std::source_location loc, bool with_cpu = false)
bool with_cpu = false)
: lgr_(lgr) : lgr_(lgr)
, level_(level) , level_(level)
, start_time_(std::chrono::high_resolution_clock::now()) , start_time_(std::chrono::high_resolution_clock::now())
, with_cpu_(with_cpu) , with_cpu_(with_cpu)
, file_(file) , loc_(loc) {
, line_(line) {
if (with_cpu) { if (with_cpu) {
cpu_start_time_ = thread_clock::now(); cpu_start_time_ = thread_clock::now();
} }
@ -190,7 +186,7 @@ class timed_level_log_entry {
oss_ << ", " << time_with_unit(cpu_time_sec.count()) << " CPU"; oss_ << ", " << time_with_unit(cpu_time_sec.count()) << " CPU";
} }
oss_ << "]"; oss_ << "]";
lgr_.write(level_, oss_.str(), file_, line_); lgr_.write(level_, oss_.str(), loc_);
} }
} }
@ -209,14 +205,13 @@ class timed_level_log_entry {
thread_clock::time_point cpu_start_time_; thread_clock::time_point cpu_start_time_;
bool output_{false}; bool output_{false};
bool const with_cpu_; bool const with_cpu_;
char const* const file_; std::source_location const loc_;
int const line_;
}; };
class no_log_entry { class no_log_entry {
public: public:
no_log_entry(logger&, logger::level_type) {} no_log_entry(logger&, logger::level_type) {}
no_log_entry(logger&, logger::level_type, char const*, int) {} no_log_entry(logger&, logger::level_type, std::source_location) {}
template <typename T> template <typename T>
no_log_entry& operator<<(const T&) { no_log_entry& operator<<(const T&) {
@ -260,98 +255,98 @@ class log_proxy {
return LogPolicy::is_enabled_for(level); return LogPolicy::is_enabled_for(level);
} }
auto fatal(char const* file, int line) const { auto fatal(std::source_location loc) const {
return level_log_entry(lgr_, logger::FATAL, file, line); return level_log_entry(lgr_, logger::FATAL, loc);
} }
auto error(char const* file, int line) const { auto error(std::source_location loc) const {
return typename LogPolicy::template logger_type<logger::ERROR>( return typename LogPolicy::template logger_type<logger::ERROR>(
lgr_, logger::ERROR, file, line); lgr_, logger::ERROR, loc);
} }
auto warn(char const* file, int line) const { auto warn(std::source_location loc) const {
return typename LogPolicy::template logger_type<logger::WARN>( return typename LogPolicy::template logger_type<logger::WARN>(
lgr_, logger::WARN, file, line); lgr_, logger::WARN, loc);
} }
auto info(char const* file, int line) const { auto info(std::source_location loc) const {
return typename LogPolicy::template logger_type<logger::INFO>( return typename LogPolicy::template logger_type<logger::INFO>(
lgr_, logger::INFO, file, line); lgr_, logger::INFO, loc);
} }
auto verbose(char const* file, int line) const { auto verbose(std::source_location loc) const {
return typename LogPolicy::template logger_type<logger::VERBOSE>( return typename LogPolicy::template logger_type<logger::VERBOSE>(
lgr_, logger::VERBOSE, file, line); lgr_, logger::VERBOSE, loc);
} }
auto debug(char const* file, int line) const { auto debug(std::source_location loc) const {
return typename LogPolicy::template logger_type<logger::DEBUG>( return typename LogPolicy::template logger_type<logger::DEBUG>(
lgr_, logger::DEBUG, file, line); lgr_, logger::DEBUG, loc);
} }
auto trace(char const* file, int line) const { auto trace(std::source_location loc) const {
return typename LogPolicy::template logger_type<logger::TRACE>( return typename LogPolicy::template logger_type<logger::TRACE>(
lgr_, logger::TRACE, file, line); lgr_, logger::TRACE, loc);
} }
auto timed_error(char const* file, int line) const { auto timed_error(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::ERROR>( return typename LogPolicy::template timed_logger_type<logger::ERROR>(
lgr_, logger::ERROR, file, line); lgr_, logger::ERROR, loc);
} }
auto timed_warn(char const* file, int line) const { auto timed_warn(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::WARN>( return typename LogPolicy::template timed_logger_type<logger::WARN>(
lgr_, logger::WARN, file, line); lgr_, logger::WARN, loc);
} }
auto timed_info(char const* file, int line) const { auto timed_info(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::INFO>( return typename LogPolicy::template timed_logger_type<logger::INFO>(
lgr_, logger::INFO, file, line); lgr_, logger::INFO, loc);
} }
auto timed_verbose(char const* file, int line) const { auto timed_verbose(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::VERBOSE>( return typename LogPolicy::template timed_logger_type<logger::VERBOSE>(
lgr_, logger::VERBOSE, file, line); lgr_, logger::VERBOSE, loc);
} }
auto timed_debug(char const* file, int line) const { auto timed_debug(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::DEBUG>( return typename LogPolicy::template timed_logger_type<logger::DEBUG>(
lgr_, logger::DEBUG, file, line); lgr_, logger::DEBUG, loc);
} }
auto timed_trace(char const* file, int line) const { auto timed_trace(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::TRACE>( return typename LogPolicy::template timed_logger_type<logger::TRACE>(
lgr_, logger::TRACE, file, line); lgr_, logger::TRACE, loc);
} }
auto cpu_timed_error(char const* file, int line) const { auto cpu_timed_error(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::ERROR>( return typename LogPolicy::template timed_logger_type<logger::ERROR>(
lgr_, logger::ERROR, file, line, true); lgr_, logger::ERROR, loc, true);
} }
auto cpu_timed_warn(char const* file, int line) const { auto cpu_timed_warn(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::WARN>( return typename LogPolicy::template timed_logger_type<logger::WARN>(
lgr_, logger::WARN, file, line, true); lgr_, logger::WARN, loc, true);
} }
auto cpu_timed_info(char const* file, int line) const { auto cpu_timed_info(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::INFO>( return typename LogPolicy::template timed_logger_type<logger::INFO>(
lgr_, logger::INFO, file, line, true); lgr_, logger::INFO, loc, true);
} }
auto cpu_timed_verbose(char const* file, int line) const { auto cpu_timed_verbose(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::VERBOSE>( return typename LogPolicy::template timed_logger_type<logger::VERBOSE>(
lgr_, logger::VERBOSE, file, line, true); lgr_, logger::VERBOSE, loc, true);
} }
auto cpu_timed_debug(char const* file, int line) const { auto cpu_timed_debug(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::DEBUG>( return typename LogPolicy::template timed_logger_type<logger::DEBUG>(
lgr_, logger::DEBUG, file, line, true); lgr_, logger::DEBUG, loc, true);
} }
auto cpu_timed_trace(char const* file, int line) const { auto cpu_timed_trace(std::source_location loc) const {
return typename LogPolicy::template timed_logger_type<logger::TRACE>( return typename LogPolicy::template timed_logger_type<logger::TRACE>(
lgr_, logger::TRACE, file, line, true); lgr_, logger::TRACE, loc, true);
} }
logger& get_logger() const { return lgr_; } logger& get_logger() const { return lgr_; }
@ -363,31 +358,35 @@ class log_proxy {
#define LOG_DETAIL_LEVEL(level, lgr, method) \ #define LOG_DETAIL_LEVEL(level, lgr, method) \
if constexpr (std::decay_t<decltype(lgr)>::is_enabled_for( \ if constexpr (std::decay_t<decltype(lgr)>::is_enabled_for( \
::dwarfs::logger::level)) \ ::dwarfs::logger::level)) \
lgr.method(__FILE__, __LINE__) lgr.method(std::source_location::current())
#define LOG_PROXY(policy, lgr) ::dwarfs::log_proxy<policy> log_(lgr) #define LOG_PROXY(policy, lgr) ::dwarfs::log_proxy<policy> log_(lgr)
#define LOG_PROXY_DECL(policy) ::dwarfs::log_proxy<policy> log_ #define LOG_PROXY_DECL(policy) ::dwarfs::log_proxy<policy> log_
#define LOG_PROXY_INIT(lgr) log_(lgr) #define LOG_PROXY_INIT(lgr) log_(lgr)
#define LOG_GET_LOGGER log_.get_logger() #define LOG_GET_LOGGER log_.get_logger()
#define LOG_FATAL log_.fatal(__FILE__, __LINE__) #define LOG_FATAL log_.fatal(std::source_location::current())
#define LOG_ERROR LOG_DETAIL_LEVEL(ERROR, log_, error) #define LOG_ERROR LOG_DETAIL_LEVEL(ERROR, log_, error)
#define LOG_WARN LOG_DETAIL_LEVEL(WARN, log_, warn) #define LOG_WARN LOG_DETAIL_LEVEL(WARN, log_, warn)
#define LOG_INFO LOG_DETAIL_LEVEL(INFO, log_, info) #define LOG_INFO LOG_DETAIL_LEVEL(INFO, log_, info)
#define LOG_VERBOSE LOG_DETAIL_LEVEL(VERBOSE, log_, verbose) #define LOG_VERBOSE LOG_DETAIL_LEVEL(VERBOSE, log_, verbose)
#define LOG_DEBUG LOG_DETAIL_LEVEL(DEBUG, log_, debug) #define LOG_DEBUG LOG_DETAIL_LEVEL(DEBUG, log_, debug)
#define LOG_TRACE LOG_DETAIL_LEVEL(TRACE, log_, trace) #define LOG_TRACE LOG_DETAIL_LEVEL(TRACE, log_, trace)
#define LOG_TIMED_ERROR log_.timed_error(__FILE__, __LINE__) #define LOG_TIMED_ERROR log_.timed_error(std::source_location::current())
#define LOG_TIMED_WARN log_.timed_warn(__FILE__, __LINE__) #define LOG_TIMED_WARN log_.timed_warn(std::source_location::current())
#define LOG_TIMED_INFO log_.timed_info(__FILE__, __LINE__) #define LOG_TIMED_INFO log_.timed_info(std::source_location::current())
#define LOG_TIMED_VERBOSE log_.timed_verbose(__FILE__, __LINE__) #define LOG_TIMED_VERBOSE log_.timed_verbose(std::source_location::current())
#define LOG_TIMED_DEBUG log_.timed_debug(__FILE__, __LINE__) #define LOG_TIMED_DEBUG log_.timed_debug(std::source_location::current())
#define LOG_TIMED_TRACE log_.timed_trace(__FILE__, __LINE__) #define LOG_TIMED_TRACE log_.timed_trace(std::source_location::current())
#define LOG_CPU_TIMED_ERROR log_.cpu_timed_error(__FILE__, __LINE__) #define LOG_CPU_TIMED_ERROR \
#define LOG_CPU_TIMED_WARN log_.cpu_timed_warn(__FILE__, __LINE__) log_.cpu_timed_error(std::source_location::current())
#define LOG_CPU_TIMED_INFO log_.cpu_timed_info(__FILE__, __LINE__) #define LOG_CPU_TIMED_WARN log_.cpu_timed_warn(std::source_location::current())
#define LOG_CPU_TIMED_VERBOSE log_.cpu_timed_verbose(__FILE__, __LINE__) #define LOG_CPU_TIMED_INFO log_.cpu_timed_info(std::source_location::current())
#define LOG_CPU_TIMED_DEBUG log_.cpu_timed_debug(__FILE__, __LINE__) #define LOG_CPU_TIMED_VERBOSE \
#define LOG_CPU_TIMED_TRACE log_.cpu_timed_trace(__FILE__, __LINE__) log_.cpu_timed_verbose(std::source_location::current())
#define LOG_CPU_TIMED_DEBUG \
log_.cpu_timed_debug(std::source_location::current())
#define LOG_CPU_TIMED_TRACE \
log_.cpu_timed_trace(std::source_location::current())
class prod_logger_policy : public MinimumLogLevelPolicy<logger::VERBOSE> { class prod_logger_policy : public MinimumLogLevelPolicy<logger::VERBOSE> {
public: public:
@ -417,7 +416,7 @@ std::shared_ptr<Base> make_shared_logging_object(logger& lgr, Args&&... args) {
lgr, std::forward<Args>(args)...); lgr, std::forward<Args>(args)...);
} }
std::string get_logger_context(char const* path, int line); std::string get_logger_context(std::source_location loc);
std::string get_current_time_string(); std::string get_current_time_string();
} // namespace dwarfs } // namespace dwarfs

View File

@ -158,8 +158,8 @@ void stream_logger::write_nolock(std::string_view output) {
} }
} }
void stream_logger::write(level_type level, const std::string& output, void stream_logger::write(level_type level, std::string_view output,
char const* file, int line) { std::source_location loc) {
if (level <= threshold_ || level == FATAL) { if (level <= threshold_ || level == FATAL) {
auto t = get_current_time_string(); auto t = get_current_time_string();
std::string_view prefix; std::string_view prefix;
@ -216,8 +216,8 @@ void stream_logger::write(level_type level, const std::string& output,
std::string context; std::string context;
size_t context_len = 0; size_t context_len = 0;
if (with_context_ && file) { if (with_context_ /*&& file*/) {
context = get_logger_context(file, line); context = get_logger_context(loc);
context_len = context.size(); context_len = context.size();
if (color_) { if (color_) {
context = folly::to<std::string>( context = folly::to<std::string>(
@ -306,8 +306,8 @@ void logging_class_factory::on_policy_not_found(logger const& lgr) {
} // namespace detail } // namespace detail
std::string get_logger_context(char const* path, int line) { std::string get_logger_context(std::source_location loc) {
return fmt::format("[{0}:{1}] ", basename(path), line); return fmt::format("[{0}:{1}] ", basename(loc.file_name()), loc.line());
} }
std::string get_current_time_string() { std::string get_current_time_string() {

View File

@ -36,17 +36,15 @@ namespace dwarfs::test {
class test_logger : public ::dwarfs::logger { class test_logger : public ::dwarfs::logger {
public: public:
struct log_entry { struct log_entry {
log_entry(level_type level, std::string const& output, char const* file, log_entry(level_type level, std::string_view output,
int line) std::source_location loc)
: level{level} : level{level}
, output{output} , output{output}
, file{file} , loc{loc} {}
, line{line} {}
level_type level; level_type level;
std::string output; std::string output;
char const* file; std::source_location loc;
int line;
}; };
test_logger(std::optional<level_type> threshold = std::nullopt) test_logger(std::optional<level_type> threshold = std::nullopt)
@ -61,17 +59,17 @@ class test_logger : public ::dwarfs::logger {
} }
} }
void write(level_type level, std::string const& output, char const* file, void write(level_type level, std::string_view output,
int line) override { std::source_location loc) override {
if (output_ && level <= output_threshold_) { if (output_ && level <= output_threshold_) {
std::lock_guard lock(mx_); std::lock_guard lock(mx_);
std::cerr << level_char(level) << " [" << file << ":" << line << "] " std::cerr << level_char(level) << " [" << loc.file_name() << ":"
<< output << "\n"; << loc.line() << "] " << output << "\n";
} }
if (level <= threshold_) { if (level <= threshold_) {
std::lock_guard lock(mx_); std::lock_guard lock(mx_);
log_.emplace_back(level, output, file, line); log_.emplace_back(level, output, loc);
} }
} }