diff --git a/Alloy.toml b/Alloy.toml index 5aa6c3f..9789ded 100644 --- a/Alloy.toml +++ b/Alloy.toml @@ -6,7 +6,6 @@ version = "0.1.0" [lib] name = "libjournal" -cc-flags = ["-DJOURNAL_ALL"] [[bin]] name = "journal" diff --git a/include/journal.hpp b/include/journal.hpp index 81ead34..c667ff8 100644 --- a/include/journal.hpp +++ b/include/journal.hpp @@ -5,7 +5,39 @@ namespace journal { -namespace __detail { +namespace detail { + +struct source_location { + _NODISCARD static constexpr source_location + current(const uint_least32_t _Line_ = __builtin_LINE(), + const uint_least32_t _Column_ = __builtin_COLUMN(), + const char *const _File_ = __builtin_FILE(), + const char *const _Function_ = __builtin_FUNCTION()) noexcept { + source_location _Result; + _Result._Line = _Line_; + _Result._Column = _Column_; + _Result._File = _File_; + _Result._Function = _Function_; + return _Result; + } + + _NODISCARD_CTOR constexpr source_location() noexcept = default; + + _NODISCARD constexpr uint_least32_t line() const noexcept { return _Line; } + _NODISCARD constexpr uint_least32_t column() const noexcept { + return _Column; + } + _NODISCARD constexpr const char *file_name() const noexcept { return _File; } + _NODISCARD constexpr const char *function_name() const noexcept { + return _Function; + } + +private: + uint_least32_t _Line{}; + uint_least32_t _Column{}; + const char *_File = ""; + const char *_Function = ""; +}; enum LogVerbosity { Trace, @@ -19,16 +51,18 @@ constexpr auto to_string(const LogVerbosity& verbosity) -> std::string; template inline constexpr auto log(const LogVerbosity &verbosity, std::string_view fmt, - Args... args) -> void { - const auto msg = std::vformat(fmt, std::make_format_args( args...)); - log_internal(verbosity, msg); + Args... args, const detail::source_location source) + -> void { + const auto msg = std::vformat(fmt, std::make_format_args(args...)); + log_internal(verbosity, source, msg); } auto log_internal(const LogVerbosity &verbosity, - const std::string &msg) -> void; -} // namespace __detail + const detail::source_location source, const std::string &msg) + -> void; +} // namespace detail -using __detail::LogVerbosity; +using detail::LogVerbosity; auto init_stdout(const LogVerbosity& min = LogVerbosity::Info) -> void; @@ -42,8 +76,11 @@ auto init_stdout(const LogVerbosity& min = LogVerbosity::Info) -> void; #ifdef JOURNAL_TRACE template -inline constexpr auto trace(std::string_view fmt, Args... args) -> void { - __detail::log(__detail::LogVerbosity::Trace, fmt, args...); +inline constexpr auto +trace(std::string_view fmt, Args... args, + const detail::source_location source = detail::source_location::current()) + -> void { + detail::log(detail::LogVerbosity::Trace, fmt, args..., source); } #else template @@ -52,8 +89,11 @@ inline constexpr auto trace(std::string_view fmt, Args... args) -> void {} #ifdef JOURNAL_DEBUG template -inline constexpr auto debug(std::string_view fmt, Args... args) -> void { - __detail::log(__detail::LogVerbosity::Debug, fmt, args...); +inline constexpr auto +debug(std::string_view fmt, Args... args, + const detail::source_location source = detail::source_location::current()) + -> void { + detail::log(detail::LogVerbosity::Debug, fmt, args..., source); } #else template @@ -62,8 +102,11 @@ inline constexpr auto debug(std::string_view fmt, Args... args) -> void {} #ifdef JOURNAL_INFO template -inline constexpr auto info(std::string_view fmt, Args... args) -> void { - __detail::log(__detail::LogVerbosity::Info, fmt, args...); +inline constexpr auto +info(std::string_view fmt, Args... args, + const detail::source_location source = detail::source_location::current()) + -> void { + detail::log(detail::LogVerbosity::Info, fmt, args..., source); } #else template @@ -72,8 +115,11 @@ inline constexpr auto info(std::string_view fmt, Args... args) -> void {} #ifdef JOURNAL_WARN template -inline constexpr auto warn(std::string_view fmt, Args... args) -> void { - __detail::log(__detail::LogVerbosity::Warn, fmt, args...); +inline constexpr auto +warn(std::string_view fmt, Args... args, + const detail::source_location source = detail::source_location::current()) + -> void { + detail::log(detail::LogVerbosity::Warn, fmt, args..., source); } #else template @@ -82,8 +128,11 @@ inline constexpr auto warn(std::string_view fmt, Args... args) -> void {} #ifdef JOURNAL_ERROR template -inline constexpr auto error(std::string_view fmt, Args... args) -> void { - __detail::log(__detail::LogVerbosity::Error, fmt, args...); +inline constexpr auto +error(std::string_view fmt, Args... args, + const detail::source_location source = detail::source_location::current()) + -> void { + detail::log(detail::LogVerbosity::Error, fmt, args..., source); } #else template diff --git a/src/journal.cc b/src/journal.cc index aae733e..fb3ec10 100644 --- a/src/journal.cc +++ b/src/journal.cc @@ -1,5 +1,6 @@ #include "journal.hpp" +#include #include #include #include @@ -9,6 +10,7 @@ #include #include #include +#include namespace journal { namespace mutex { @@ -65,7 +67,7 @@ public: }; } // namespace mutex -namespace __detail { +namespace detail { constexpr auto to_string(const LogVerbosity& verbosity) -> std::string { switch (verbosity) { @@ -83,10 +85,10 @@ constexpr auto to_string(const LogVerbosity& verbosity) -> std::string { } struct Verbosity { - journal::__detail::LogVerbosity inner; + journal::detail::LogVerbosity inner; - Verbosity(journal::__detail::LogVerbosity &&value) : inner(value) {} - Verbosity(const journal::__detail::LogVerbosity &value) : inner(value) {} + Verbosity(journal::detail::LogVerbosity &&value) : inner(value) {} + Verbosity(const journal::detail::LogVerbosity &value) : inner(value) {} auto operator<=>(const Verbosity &rhs) -> std::strong_ordering { return static_cast>(inner) <=> @@ -99,14 +101,16 @@ struct Sink { Verbosity min_verbosity; Verbosity max_verbosity; - Sink(std::shared_ptr&& stream) - : stream(std::move(stream)), min_verbosity(journal::__detail::LogVerbosity::Trace), - max_verbosity(journal::__detail::LogVerbosity::Error) {} + Sink(std::shared_ptr &&stream) + : stream(std::move(stream)), + min_verbosity(journal::detail::LogVerbosity::Trace), + max_verbosity(journal::detail::LogVerbosity::Error) {} Sink(std::shared_ptr&& stream, const Verbosity &min, const Verbosity &max) : stream(std::move(stream)),min_verbosity(min), max_verbosity(max) {} - Sink(std::shared_ptr&& stream, const Verbosity &min) - : stream(std::move(stream)),min_verbosity(min), max_verbosity(journal::__detail::Error) {} + Sink(std::shared_ptr &&stream, const Verbosity &min) + : stream(std::move(stream)), min_verbosity(min), + max_verbosity(journal::detail::Error) {} auto operator<<(std::string_view msg) { (*stream) << msg; } }; @@ -116,42 +120,54 @@ class Journal { public: Journal() {} - auto log(const Verbosity &verbosity, std::string_view msg) { - for (auto &&sink : sinks) { - if (verbosity >= sink.min_verbosity && verbosity <= sink.max_verbosity) { - sink << std::format("[{: <5}] {}\n", to_string(verbosity.inner), msg); - } +auto log(const Verbosity &verbosity, source_location source, + std::string_view msg) { + for (auto &&sink : sinks) { + if (verbosity >= sink.min_verbosity && verbosity <= sink.max_verbosity) { + sink << std::format("[{}] [{: <5}] [{}] {}\n", + get_current_time_string(), to_string(verbosity.inner), + get_source_location_string(source), msg); } } +} - auto - add_std_out(const Verbosity &min = journal::__detail::LogVerbosity::Info) { - auto out = std::shared_ptr(&std::cout, [](auto&& _) {}); - sinks.emplace_back(std::move(out)); - } +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); +} + +auto add_std_out(const Verbosity &min = journal::detail::LogVerbosity::Info) { + auto out = std::shared_ptr(&std::cout, [](auto &&_) {}); + sinks.emplace_back(std::move(out)); +} }; static mutex::Mutex> global_journal; -auto log_internal(const LogVerbosity &verbosity, - const std::string &msg) - -> void { +auto log_internal(const LogVerbosity &verbosity, detail::source_location source, + const std::string &msg) -> void { auto &&[lock, ref] = global_journal.ref(); - ref->log(verbosity, msg); + ref->log(verbosity, source, msg); } -} // namespace __detail +} // namespace detail auto init() { - auto &&[lock, ref] = __detail::global_journal.mut(); + auto &&[lock, ref] = detail::global_journal.mut(); if (!ref.get()) { - ref = std::make_unique<__detail::Journal>(); + ref = std::make_unique(); } } auto init_stdout(const LogVerbosity &min) -> void { init(); - auto &&[lock, ref] = __detail::global_journal.mut(); - ref->add_std_out(); + auto &&[lock, ref] = detail::global_journal.mut(); + ref->add_std_out(); } } // namespace journal