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) {
|
||||
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::ostream>(&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::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();
|
||||
ref->add_std_out();
|
||||
auto &&[lock, ref] = detail::global_journal.mut();
|
||||
ref->add_std_out();
|
||||
}
|
||||
} // namespace journal
|
||||
|
|
Loading…
Reference in a new issue