// // logger.cpp // logger // // Created by Sam Jaffe on 9/3/16. // #include #include #include #include #include #include #include "expect/expect.hpp" #include "logger.hpp" #include "properties.hpp" namespace logging { #define X(l) \ case logging::L##l: \ return #l; const char* level_header(ilog_level l) { assert(l != logging::LNONE); switch (l) { X(FATAL) X(CRITICAL) X(ERROR) X(WARNING) X(INFO) X(DEBUG) X(TRACE) X(NONE) } } #undef X } namespace { struct timeval now( ) { struct timeval tv; gettimeofday( &tv, nullptr ); return tv; } } namespace logging { class multiple_bindings : public std::logic_error { using std::logic_error::logic_error; }; // extern logger_impl& _logger_impl_shared_instance(); extern _binding _default_logger_impl; static _binding _impl_binding = nullptr; bool bind_logger_impl(_binding impl) { expects(_impl_binding == nullptr, multiple_bindings, "Only one logger implementation may be bound"); _impl_binding = impl; return true; } ilogger_impl& _i_get_shared_instance() { if (_impl_binding == nullptr) { return _default_logger_impl(); } else { return _impl_binding(); } } } namespace logging { ilogger& ilogger::instance() { static ilogger instance; return instance; } ilogger& ilogger::instance(std::string const & name) { using p_logger = std::unique_ptr; using store = std::map; static store instances; store::iterator it; if ((it = instances.find(name)) != instances.end()) { return *(it->second); } return *(instances.emplace(std::make_pair(name, p_logger(new ilogger(name)))).first->second); } ilogger::ilogger(std::string const & name) : min_level_(LDEBUG) , logger_name_(name) , impl_(_i_get_shared_instance()) { } ilogger::~ilogger() { flush(); } void ilogger::log(ilog_level ll, location_info info, std::string const & msg) { impl_.write({ now( ), ll, info, logger_name_.c_str(), msg }); } bool ilogger::should_log( ilog_level ll ) const { return ll < min_level_ && impl_.should_log( ll ); } void ilogger::flush() { impl_.flush(); } } namespace logging { bool ilogger_impl::should_log( ilog_level ll ) const { return ll < min_log_level; } } void test() { logging::ilogger & LOG = logging::ilogger::instance( ); LOG.log(logging::LERROR, "{}", 5); }