#include "matador/logger/log_domain.hpp" #include #include namespace matador::logger { namespace details { std::size_t acquire_thread_index(const std::thread::id id) { static std::size_t next_index = 0; static std::mutex thread_mutex; static std::map ids; std::lock_guard lock(thread_mutex); if(ids.find(id) == ids.end()) { ids[id] = next_index++; } return ids[id]; } char* gettimestamp(char* const buffer, const size_t size) { using namespace std::chrono; const auto now = system_clock::now(); const auto now_ms = time_point_cast(now); std::time_t t = system_clock::to_time_t(now); const auto ms = duration_cast(now_ms.time_since_epoch()) % 1000; std::tm tm{}; #ifdef _WIN32 localtime_s(&tm, &t); #else localtime_r(&t, &tm); #endif char buf[32]; std::strftime(buf, 32, "%Y-%m-%d %H:%M:%S", &tm); std::snprintf(buffer, size, "%s.%03ld", buf, static_cast(ms.count())); return buffer; } } std::map log_domain::level_strings = { /* NOLINT */ { log_level::LVL_DEBUG, "DEBUG" }, { log_level::LVL_INFO, "INFO" }, { log_level::LVL_WARN, "WARN" }, { log_level::LVL_ERROR, "ERROR" }, { log_level::LVL_TRACE, "TRACE" } }; log_domain::log_domain(std::string name, const log_level_range log_range) : name_(std::move(name)) , log_level_range_(log_range) {} std::string log_domain::name() const { return name_; } void log_domain::max_log_level(log_level max_level) { log_level_range_.max_level = max_level; } log_level log_domain::max_log_level() const { return log_level_range_.max_level; } void log_domain::min_log_level(log_level min_level) { log_level_range_.min_level = min_level; } log_level log_domain::min_log_level() const { return log_level_range_.min_level; } void log_domain::add_sink(sink_ptr sink) { sinks.push_back(std::move(sink)); } void log_domain::log(log_level lvl, const std::string &source, const char *message) { if (lvl < log_level_range_.max_level || lvl > log_level_range_.min_level) { return; } char timestamp[80]; get_time_stamp(timestamp); char buffer[1024]; #ifdef _MSC_VER int ret = sprintf_s(buffer, 1024, "%s [Thread %zu] [%-7s] [%s]: %s\n", timestamp, details::acquire_thread_index(std::this_thread::get_id()), level_strings[lvl].c_str(), source.c_str(), message); #else int ret = sprintf(buffer, "%s [Thread %lu] [%-7s] [%s]: %s\n", timestamp, details::acquire_thread_index(std::this_thread::get_id()), level_strings[lvl].c_str(), source.c_str(), message); #endif std::lock_guard l(mutex_); for (auto &sink : sinks) { sink->write(buffer, ret); } } void log_domain::clear() { sinks.clear(); } void log_domain::get_time_stamp(char* const timestamp_buffer) { std::lock_guard l(mutex_); details::gettimestamp(timestamp_buffer, 80); } }