#pragma once #ifndef _NB_LOGGER #define _NB_LOGGER #include #include #include #include #include #include "Processes.hpp" #include "ThreadSafeQueue.hpp" namespace nb { typedef std::chrono::time_point< std::chrono::system_clock, std::chrono::nanoseconds > LoggerTimePoint; struct LogEvent{ const LoggerTimePoint time; const unsigned char lvl; const std::string msg; const std::thread::id tid; const uint64_t pid; }; typedef std::string (*LogProcessFunction)(const LoggerTimePoint&, const std::string&); typedef std::unordered_map LogProcessFunctionMap; template class Logger { public: Logger(StreamType& stream) : _ostream(&stream) {} bool isRunning() const; unsigned int count() const; bool run(); bool stop(); LogEvent pop(); void flush() { while(_queue.size()) { pop(); } } void deleteAll() { _queue.empty(); } void msg(const std::string& _msg, uint8_t lvl=0) { _queue.push(LogEvent{ std::chrono::system_clock::now(), lvl, _msg, std::this_thread::get_id(), get_pid() }); } void warn(const std::string& _msg, uint8_t lvl=1) { msg(_msg, lvl); } void warn(const std::exception& _err, uint8_t lvl=1) { msg(_err.what(), lvl); } void error(const std::string& _msg, uint8_t lvl=0xFF) { msg(_msg, lvl); } void error(const std::exception& _err, uint8_t lvl=0xFF) { msg(_err.what(), lvl); } protected: virtual void process(const LogEvent& event) { uint8_t lvl = event.lvl; *_ostream << "\n"; } ThreadsafeQueue _queue; StreamType* const _ostream; std::atomic _running; std::shared_ptr _runningThread = nullptr; }; template bool Logger::isRunning() const { return _running && bool(_runningThread); } template unsigned int Logger::count() const { return _queue.size(); } template bool Logger::run() { if (!isRunning()) { _runningThread = std::make_shared([&]{ while(this->isRunning()) { this->flush(); } }); } return isRunning(); } template bool Logger::stop() { if (isRunning()) { _running = false; _runningThread->join(); _runningThread = nullptr; flush(); } return isRunning(); } template LogEvent Logger::pop() { std::shared_ptr event; _queue.pop(event); process(*event); return *event; } } // namespace nb #endif // _NB_LOGGER