Skip to content

Commit

Permalink
Refactor logging.
Browse files Browse the repository at this point in the history
- Add `log::Level`.
- Add `log::set_max_level()` per tag and global.
  • Loading branch information
karnkaul committed Jan 27, 2024
1 parent e9b2683 commit 505e0ca
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 13 deletions.
20 changes: 10 additions & 10 deletions lib/include/bave/logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@

namespace bave {
namespace log {
constexpr auto error_v{'E'};
constexpr auto warn_v{'W'};
constexpr auto info_v{'I'};
constexpr auto debug_v{'D'};
enum class Level : int { eError, eWarn, eInfo, eDebug };

[[nodiscard]] auto format_full(char level, std::string_view tag, std::string_view message) -> std::string;
[[nodiscard]] auto format_thread(std::string_view message) -> std::string;

void log_message(char level, CString tag, CString message);
void log_message(Level level, CString tag, CString message);
auto get_thread_id() -> int;

void set_max_level(Level level);
void set_max_level(std::string_view tag, Level level);

namespace internal {
void log_message(char level, CString tag, CString message);
}
Expand All @@ -23,26 +23,26 @@ void log_message(char level, CString tag, CString message);
struct Logger {
std::string tag{"default"};

void log(char level, CString message) const;
void log(log::Level level, CString message) const;

template <typename... Args>
void error(fmt::format_string<Args...> fmt, Args&&... args) const {
log(log::error_v, fmt::format(fmt, std::forward<Args>(args)...).c_str());
log(log::Level::eError, fmt::format(fmt, std::forward<Args>(args)...).c_str());
}

template <typename... Args>
void warn(fmt::format_string<Args...> fmt, Args&&... args) const {
log(log::warn_v, fmt::format(fmt, std::forward<Args>(args)...).c_str());
log(log::Level::eWarn, fmt::format(fmt, std::forward<Args>(args)...).c_str());
}

template <typename... Args>
void info(fmt::format_string<Args...> fmt, Args&&... args) const {
log(log::info_v, fmt::format(fmt, std::forward<Args>(args)...).c_str());
log(log::Level::eInfo, fmt::format(fmt, std::forward<Args>(args)...).c_str());
}

template <typename... Args>
void debug(fmt::format_string<Args...> fmt, Args&&... args) const {
log(log::debug_v, fmt::format(fmt, std::forward<Args>(args)...).c_str());
log(log::Level::eDebug, fmt::format(fmt, std::forward<Args>(args)...).c_str());
}
};
} // namespace bave
2 changes: 1 addition & 1 deletion lib/platform/desktop/desktop_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ auto g_file_logger = std::unique_ptr<FileLogger>{}; // NOLINT(cppcoreguidelines-
void log::internal::log_message(char level, CString tag, CString message) {
auto const formatted = format_full(level, tag, message);

auto& out = level == error_v ? std::cerr : std::cout;
auto& out = level == 'E' ? std::cerr : std::cout;
out << formatted.c_str();

if (g_file_logger) { g_file_logger->push(formatted); }
Expand Down
44 changes: 42 additions & 2 deletions lib/src/logger_common.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
#include <bave/logger.hpp>
#include <algorithm>
#include <array>
#include <chrono>
#include <mutex>
#include <thread>
#include <unordered_map>

namespace bave {
namespace {
using namespace std::chrono_literals;

constexpr std::size_t timestamp_size_v{16};

constexpr auto to_char(log::Level const level) {
constexpr auto levels_v = std::array{'E', 'W', 'I', 'D'};
return levels_v.at(static_cast<std::size_t>(level));
}

auto get_timestamp() -> std::array<char, timestamp_size_v> {
auto ret = std::array<char, timestamp_size_v>{};
auto const time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
Expand All @@ -19,6 +26,29 @@ auto get_timestamp() -> std::array<char, timestamp_size_v> {
std::strftime(ret.data(), ret.size() - 1, "%T", tm);
return ret;
}

struct {
[[nodiscard]] auto get_max_level(std::string_view const tag) const -> log::Level {
auto lock = std::scoped_lock{mutex};
if (auto const it = levels.find(tag); it != levels.end()) { return it->second; }
return fallback;
}

void set_max_level(std::string_view const tag, log::Level const level) {
auto lock = std::scoped_lock{mutex};
levels.insert_or_assign(tag, level);
}

void set_fallback(log::Level const level) {
auto lock = std::scoped_lock{mutex};
fallback = level;
}

private:
std::unordered_map<std::string_view, log::Level> levels{};
log::Level fallback{log::Level::eDebug};
mutable std::mutex mutex{};
} g_data{}; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
} // namespace

auto log::format_full(char const level, std::string_view const tag, std::string_view const message) -> std::string {
Expand All @@ -32,7 +62,10 @@ auto log::format_thread(std::string_view message) -> std::string {
return fmt::format("[{: >2}{}] {}\n", 'T', tid, message);
}

void log::log_message(char const level, CString const tag, CString const message) { internal::log_message(level, tag, message); }
void log::log_message(Level const level, CString const tag, CString const message) {
if (g_data.get_max_level(tag) < level) { return; }
internal::log_message(to_char(level), tag, message);
}

auto log::get_thread_id() -> int {
struct Map {
Expand All @@ -52,5 +85,12 @@ auto log::get_thread_id() -> int {
return id;
}

void Logger::log(char const level, CString const message) const { log::log_message(level, tag.c_str(), message); }
void log::set_max_level(Level const level) { g_data.set_fallback(level); }

void log::set_max_level(std::string_view const tag, Level const level) {
if (tag.empty()) { return; }
g_data.set_max_level(tag, level);
}

void Logger::log(log::Level const level, CString const message) const { log::log_message(level, tag.c_str(), message); }
} // namespace bave

0 comments on commit 505e0ca

Please sign in to comment.