19 default:
return "UNKNOWN";
27 std::lock_guard<std::mutex> lock(this->logs_mutex);
30 this->cv.notify_one();
42 std::queue<std::string> local_logs = {};
44 std::unique_lock<std::mutex> lock(this->logs_mutex);
46 this->cv.wait(lock, [
this] {
51 return !this->logs.empty() || this->should_stop;
54 if (this->should_stop && this->logs.empty())
return;
56 std::swap(local_logs, this->logs);
59 while(!local_logs.empty())
61 this->
write(local_logs.front());
70 std::lock_guard<std::mutex> lock(this->logs_mutex);
71 this->should_stop =
true;
73 this->cv.notify_all();
79 auto file = std::ofstream(path);
82 std::print(
"[ERROR] [oak] Error creating writer for file {}", path.c_str());
86 this->out = std::move(file);
91 if (this->out.is_open())
105 std::print(
"{}", str);
118 auto writer = std::make_shared<StdoutWriter>();
119 this->writers.push_back(writer);
121 std::jthread t([writer] { writer->write_loop(); });
124 OAK_INFO2(
this,
"[ OAK ] Initialized writer {}", writer->get_name());
129 std::lock_guard<std::mutex> lock(this->logger_mutex);
130 for (
auto it = this->writers.begin(); it != this->writers.end(); ++it)
132 if ((*it)->get_name() == name)
134 this->writers.erase(it);
135 OAK_INFO2(
this,
"Removed writer {}", name);
149 std::lock_guard<std::mutex> lock(this->logger_mutex);
156 std::lock_guard<std::mutex> lock(this->logger_mutex);
157 this->formatter = formatter;
170#define KRED "\x1B[31m"
171#define KGRN "\x1B[32m"
172#define KYEL "\x1B[33m"
173#define KBLU "\x1B[34m"
174#define KMAG "\x1B[35m"
175#define KCYN "\x1B[36m"
176#define KWHT "\x1B[37m"
179#define FRED(x) KRED x RST
180#define FGRN(x) KGRN x RST
181#define FYEL(x) KYEL x RST
182#define FBLU(x) KBLU x RST
183#define FMAG(x) KMAG x RST
184#define FCYN(x) KCYN x RST
185#define FWHT(x) KWHT x RST
187#define FRED_S(x) std::string(KRED) + x + std::string(RST)
188#define FGRN_S(x) std::string(KGRN) + x + std::string(RST)
189#define FYEL_S(x) std::string(KYEL) + x + std::string(RST)
190#define FBLU_S(x) std::string(KBLU) + x + std::string(RST)
191#define FMAG_S(x) std::string(KMAG) + x + std::string(RST)
192#define FCYN_S(x) std::string(KCYN) + x + std::string(RST)
193#define FWHT_S(x) std::string(KWHT) + x + std::string(RST)
195std::string Logger::colorize(
enum Level level,
const std::string &str)
218std::expected<int, std::string>
221 if (!std::filesystem::exists(file))
223 return std::unexpected(
"Settings file does not exist");
226 std::ifstream settings(file);
227 while (!settings.eof())
230 std::getline(settings, line);
231 if (line.size() == 0)
234 std::string key = line.substr(0, line.find(
'='));
235 std::string value = line.substr(line.find(
'=') + 1);
237 key.erase(std::remove_if(key.begin(), key.end(), isspace), key.end());
238 value.erase(std::remove_if(value.begin(), value.end(), isspace),
243 if (value ==
"debug")
245 else if (value ==
"info")
247 else if (value ==
"warn")
249 else if (value ==
"error")
252 return std::unexpected(
"Invalid log level in file");
254 else if (key ==
"flags")
257 while (value.find(
',') != std::string::npos)
259 std::string flag = value.substr(0, value.find(
','));
260 value = value.substr(value.find(
',') + 1);
263 else if (flag ==
"level")
265 else if (flag ==
"date")
267 else if (flag ==
"time")
269 else if (flag ==
"pid")
271 else if (flag ==
"tid")
273 else if (flag ==
"json")
276 return std::unexpected(
"Invalid flags in file");
281 else if (value ==
"level")
283 else if (value ==
"date")
285 else if (value ==
"time")
287 else if (value ==
"pid")
289 else if (value ==
"tid")
291 else if (value ==
"json")
294 return std::unexpected(
"Invalid flags in file");
296 else if (key ==
"file")
302 return std::unexpected(
"Invalid key in file");
313 std::lock_guard<std::mutex>
lock(this->logger_mutex);
314 this->events[
id] = name;
319 std::lock_guard<std::mutex>
lock(this->logger_mutex);
320 this->events.erase(
id);
323std::string Logger::json_formatter(
enum Level level,
int flags,
325 const std::string&
log)
340 auto now = std::chrono::system_clock::now();
343 std::ostringstream
oss;
344 oss <<
"\"date\": \"" << std::put_time(&
now_tm,
"%Y-%m-%d") <<
"\", ";
349 auto now = std::chrono::system_clock::now();
352 std::ostringstream
oss;
353 oss <<
"\"time\": \"" << std::put_time(&
now_tm,
"%H:%M:%S") <<
"\", ";
358 std::string
pid = std::to_string(
getpid());
363 std::ostringstream
oss;
364 oss << std::this_thread::get_id();
365 std::string
tid =
oss.str();
370 output +=
"\"file\": \"" + std::string(
file) +
"\", ";
375 output +=
"\"line\": " + std::to_string(
line) +
", ";
385 return Logger::colorize(level,
output);
390 [](
enum Level level,
int flags,
393 const std::string&
log)
399 return json_formatter(level, flags,
file,
line,
log);
411 auto now = std::chrono::system_clock::now();
414 std::ostringstream
oss;
415 oss << std::put_time(&
now_tm,
"%Y-%m-%d") <<
" ";
420 auto now = std::chrono::system_clock::now();
423 std::ostringstream
oss;
424 oss << std::put_time(&
now_tm,
"%H:%M:%S") <<
" ";
429 std::string
pid = std::to_string(
getpid());
434 std::ostringstream
oss;
435 oss << std::this_thread::get_id();
436 std::string
tid =
oss.str();
455 return colorize(level,
output);
FileWriter(const std::filesystem::path &path)
std::string get_name() override
static const std::string name
void write(const std::string &str) override
void enable_event(unsigned int id, const std::string &name)
std::expected< int, std::string > load_config_file(const std::filesystem::path &file)
std::function< std::string(enum Level, int flags, const char *file, int line, const std::string &log)> Formatter
bool remove_writer(const std::string &name)
void add_flags(Flags flag, F &&... flags)
void set_formatter(Formatter formatter)
void disable_event(unsigned int id)
unsigned int get_flags() const
void set_level(enum Level level)
void add_writer(Args &&...init_args)
void log(enum Level l, const char *fmt, Args &&...args)
enum Level get_level() const
void set_flags(F &&... flags)
static const std::string name
void write(const std::string &str) override
std::string get_name() override
virtual void write(const std::string &str)=0
void submit(const std::string &log)
std::string level_to_string(enum Level level)
static void add_writer(Args &&...init_args)
static void log(enum oak::Level level, const char *fmt, Args &&...args)
#define OAK_INFO2(logger,...)