diff --git a/include/journal.hpp b/include/journal.hpp index 12e9e25..bcf8404 100644 --- a/include/journal.hpp +++ b/include/journal.hpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include namespace journal { @@ -48,8 +50,30 @@ enum LogVerbosity { Error, }; +struct Verbosity { + journal::detail::LogVerbosity inner; + + Verbosity(journal::detail::LogVerbosity &&value) : inner(value) {} + Verbosity(const journal::detail::LogVerbosity &value) : inner(value) {} + + auto operator<=>(const Verbosity &rhs) const -> std::strong_ordering { + return static_cast>(inner) <=> + static_cast>(rhs.inner); + } +}; + constexpr auto to_string(const LogVerbosity& verbosity) -> std::string; +namespace formatter { + +struct Formatter { + virtual auto operator()(const Verbosity &verbosity, + const source_location &source) -> std::string = 0; + virtual ~Formatter() {} +}; + +} // namespace formatter + template inline constexpr auto log(const LogVerbosity &verbosity, std::string_view fmt, Args... args, const detail::source_location source) @@ -61,6 +85,7 @@ inline constexpr auto log(const LogVerbosity &verbosity, std::string_view fmt, auto log_internal(const LogVerbosity &verbosity, const detail::source_location source, const std::string &msg) -> void; + } // namespace detail using detail::LogVerbosity; @@ -69,6 +94,8 @@ auto init_std_out(const LogVerbosity &min = LogVerbosity::Info) -> void; auto init_std_out_err(const LogVerbosity &min = LogVerbosity::Info) -> void; auto init() -> void; auto init_no_threads() -> void; +auto set_formatter(std::unique_ptr &&formatter) + -> void; auto add_std_out() -> void; auto add_std_err() -> void; auto add_file(std::string_view file_path, diff --git a/src/journal.cc b/src/journal.cc index f4820fe..e886c58 100644 --- a/src/journal.cc +++ b/src/journal.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -166,17 +167,30 @@ constexpr auto to_string(const LogVerbosity& verbosity) -> std::string { } } -struct Verbosity { - journal::detail::LogVerbosity inner; +namespace formatter { - Verbosity(journal::detail::LogVerbosity &&value) : inner(value) {} - Verbosity(const journal::detail::LogVerbosity &value) : inner(value) {} +struct DefaultFormatter : public Formatter { + virtual auto operator()(const Verbosity &verbosity, + const source_location &source) -> std::string { + return std::format("[{}] [{: <5}] [{}]", get_current_time_string(), + to_string(verbosity.inner), + get_source_location_string(source)); + } - auto operator<=>(const Verbosity &rhs) const -> std::strong_ordering { - return static_cast>(inner) <=> - static_cast>(rhs.inner); + auto get_source_location_string(const source_location &source) + -> std::string { + const auto file = + std::filesystem::path(source.file_name()).filename().string(); + return std::format("{}::{}", file, source.line()); + } + + auto get_current_time_string() -> std::string { + const auto now = std::chrono::utc_clock::now(); + + return std::format("{:%Y-%m-%d %H:%M:%OS} UTC", now); } }; +} // namespace formatter using namespace std::chrono_literals; @@ -251,11 +265,14 @@ static auto try_flush_all_loop(std::stop_token) -> void; class Journal { std::vector> sinks; + std::unique_ptr formatter; std::optional flush_thread; std::chrono::system_clock::duration flush_interval; public: - Journal() : flush_interval(250ms) {} + Journal() + : flush_interval(250ms), + formatter(std::make_unique()) {} ~Journal() { if (flush_thread) { log(LogVerbosity::Trace, source_location::current(), @@ -270,6 +287,15 @@ public: flush_all(); } + auto reset_formatter() -> void { + formatter = std::make_unique(); + } + + auto set_formatter(std::unique_ptr &&formatter) + -> void { + formatter = std::move(formatter); + } + auto set_flush_interval(const std::chrono::system_clock::duration &new_interval) -> void { @@ -311,20 +337,7 @@ public: auto format(std::string_view str, const Verbosity &verbosity, const source_location &source) -> std::string { - return std::format("[{}] [{: <5}] [{}] {}\n", get_current_time_string(), - to_string(verbosity.inner), - get_source_location_string(source), str); -} - -auto get_source_location_string(const source_location& source) -> std::string { - const auto file = std::filesystem::path(source.file_name()).filename().string(); - return std::format("{}::{}", file, source.line()); -} - -auto get_current_time_string() -> std::string { - const auto now = std::chrono::utc_clock::now(); - - return std::format("{:%Y-%m-%d %H:%M:%OS} UTC", now); + return std::format("{} {}\n", (*formatter)(verbosity, source), str); } auto add_file(const std::string &file_name, @@ -392,6 +405,12 @@ auto init_std_out_err(const LogVerbosity &min) -> void { ref->add_std_err(); } +auto set_formatter(std::unique_ptr &&formatter) + -> void { + auto &&[lock, ref] = detail::global_journal.mut(); + ref->set_formatter(std::move(formatter)); +} + auto add_std_out() -> void { auto &&[lock, ref] = detail::global_journal.mut(); ref->add_std_out();