source location and time/date
This commit is contained in:
		
							parent
							
								
									2719942c9e
								
							
						
					
					
						commit
						31d1dda7f8
					
				|  | @ -6,7 +6,6 @@ version = "0.1.0" | |||
| 
 | ||||
| [lib] | ||||
| name = "libjournal" | ||||
| cc-flags = ["-DJOURNAL_ALL"] | ||||
| 
 | ||||
| [[bin]] | ||||
| name = "journal" | ||||
|  |  | |||
|  | @ -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 <typename... Args> | ||||
| 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 <typename... Args> | ||||
| 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 <typename... Args> | ||||
|  | @ -52,8 +89,11 @@ inline constexpr auto trace(std::string_view fmt, Args... args) -> void {} | |||
| 
 | ||||
| #ifdef JOURNAL_DEBUG | ||||
| template <typename... Args> | ||||
| 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 <typename... Args> | ||||
|  | @ -62,8 +102,11 @@ inline constexpr auto debug(std::string_view fmt, Args... args) -> void {} | |||
| 
 | ||||
| #ifdef JOURNAL_INFO | ||||
| template <typename... Args> | ||||
| 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 <typename... Args> | ||||
|  | @ -72,8 +115,11 @@ inline constexpr auto info(std::string_view fmt, Args... args) -> void {} | |||
| 
 | ||||
| #ifdef JOURNAL_WARN | ||||
| template <typename... Args> | ||||
| 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 <typename... Args> | ||||
|  | @ -82,8 +128,11 @@ inline constexpr auto warn(std::string_view fmt, Args... args) -> void {} | |||
| 
 | ||||
| #ifdef JOURNAL_ERROR | ||||
| template <typename... Args> | ||||
| 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 <typename... Args> | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| #include "journal.hpp" | ||||
| 
 | ||||
| #include <chrono> | ||||
| #include <compare> | ||||
| #include <concepts> | ||||
| #include <cstdio> | ||||
|  | @ -9,6 +10,7 @@ | |||
| #include <optional> | ||||
| #include <string_view> | ||||
| #include <type_traits> | ||||
| #include <filesystem> | ||||
| 
 | ||||
| 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<std::underlying_type_t<decltype(inner)>>(inner) <=> | ||||
|  | @ -99,14 +101,16 @@ struct Sink { | |||
|   Verbosity min_verbosity; | ||||
|   Verbosity max_verbosity; | ||||
| 
 | ||||
|   Sink(std::shared_ptr<std::ostream>&& stream) | ||||
|       : stream(std::move(stream)), min_verbosity(journal::__detail::LogVerbosity::Trace), | ||||
|         max_verbosity(journal::__detail::LogVerbosity::Error) {} | ||||
|   Sink(std::shared_ptr<std::ostream> &&stream) | ||||
|       : stream(std::move(stream)), | ||||
|         min_verbosity(journal::detail::LogVerbosity::Trace), | ||||
|         max_verbosity(journal::detail::LogVerbosity::Error) {} | ||||
|   Sink(std::shared_ptr<std::ostream>&& stream, const Verbosity &min, | ||||
|        const Verbosity &max) | ||||
|       : stream(std::move(stream)),min_verbosity(min), max_verbosity(max) {} | ||||
|   Sink(std::shared_ptr<std::ostream>&& stream, const Verbosity &min) | ||||
|       : stream(std::move(stream)),min_verbosity(min), max_verbosity(journal::__detail::Error) {} | ||||
|   Sink(std::shared_ptr<std::ostream> &&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) { | ||||
| 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", to_string(verbosity.inner), msg); | ||||
|       } | ||||
|       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::ostream>(&std::cout, [](auto&& _) {}); | ||||
| 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::ostream>(&std::cout, [](auto &&_) {}); | ||||
|   sinks.emplace_back(std::move(out)); | ||||
|   } | ||||
| } | ||||
| }; | ||||
| 
 | ||||
| static mutex::Mutex<std::unique_ptr<Journal>> 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<detail::Journal>(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| auto init_stdout(const LogVerbosity &min) -> void { | ||||
|     init(); | ||||
|   auto &&[lock, ref] = __detail::global_journal.mut(); | ||||
|     auto &&[lock, ref] = detail::global_journal.mut(); | ||||
|     ref->add_std_out(); | ||||
| } | ||||
| } // namespace journal
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue