#include "cru/base/log/Logger.h" #include "cru/base/log/StdioLogTarget.h" #include #include #ifdef CRU_PLATFORM_WINDOWS #include "cru/base/platform/win/DebugLogTarget.h" #endif namespace cru::log { Logger *Logger::GetInstance() { static Logger logger; logger.AddLogTarget(std::make_unique()); #ifdef CRU_PLATFORM_WINDOWS logger.AddLogTarget(std::make_unique()); #endif return &logger; } void Logger::AddLogTarget(std::unique_ptr target) { std::lock_guard lock(target_list_mutex_); target_list_.push_back(std::move(target)); } void Logger::RemoveLogTarget(ILogTarget *target) { std::lock_guard lock(target_list_mutex_); target_list_.erase( std::remove_if(target_list_.begin(), target_list_.end(), [target](const auto &t) { return t.get() == target; }), target_list_.end()); } namespace { String LogLevelToString(LogLevel level) { switch (level) { case LogLevel::Debug: return u"DEBUG"; case LogLevel::Info: return u"INFO"; case LogLevel::Warn: return u"WARN"; case LogLevel::Error: return u"ERROR"; default: std::terminate(); } } String GetLogTime() { auto time = std::time(nullptr); auto calendar = std::localtime(&time); return Format(u"{}:{}:{}", calendar->tm_hour, calendar->tm_min, calendar->tm_sec); } String MakeLogFinalMessage(const LogInfo &log_info) { return Format(u"[{}] {} {}: {}\n", GetLogTime(), LogLevelToString(log_info.level), log_info.tag, log_info.message); } } // namespace Logger::Logger() : log_thread_([this] { while (true) { auto log_info = log_queue_.Pull(); std::lock_guard lock_guard{target_list_mutex_}; for (const auto &target : target_list_) { target->Write(log_info.level, MakeLogFinalMessage(log_info)); } } }) {} Logger::~Logger() { log_thread_.detach(); } void Logger::Log(LogInfo log_info) { #ifndef CRU_DEBUG if (log_info.level == LogLevel::Debug) { return; } #endif log_queue_.Push(std::move(log_info)); } LoggerCppStream::LoggerCppStream(Logger *logger, LogLevel level, String tag) : logger_(logger), level_(level), tag_(std::move(tag)) {} LoggerCppStream LoggerCppStream::WithLevel(LogLevel level) const { return LoggerCppStream(this->logger_, level, this->tag_); } LoggerCppStream LoggerCppStream::WithTag(String tag) const { return LoggerCppStream(this->logger_, this->level_, std::move(tag)); } void LoggerCppStream::Consume(StringView str) { this->logger_->Log(this->level_, this->tag_, str.ToString()); } } // namespace cru::log