int logger_impl::format_message( char* buf, size_t size, bool add_new_line, bool a_show_ident, bool a_show_location, const timestamp& a_tv, const log_msg_info& info, const char* fmt, va_list args ) throw (badarg_error) { int len = a_tv.write(m_log_mgr->timestamp_type(), buf, size); const char* end = buf + size - 2; const char* q = logger::log_level_to_str(info.level()); char* p = buf + len; *p++ = '|'; const char* e = p + 7; while (*q) *p++ = *q++; while (p < e) *p++ = ' '; *p++ = '|'; if (a_show_ident) { q = info.get_logger().ident().c_str(); while (*q) *p++ = *q++; *p++ = '|'; } int n = vsnprintf(p, end - p, fmt, args); if (n < 0) throw badarg_error("Error formatting string:", fmt, ' ', (info.has_src_location() ? info.src_location() : "")); p += n; if (info.has_src_location() && a_show_location) { q = info.src_location(); while (*q && p != end) *p++ = *q++; if (add_new_line) *p++ = '\n'; } else if (add_new_line) *p++ = '\n'; *p = '\0'; len = p - buf; BOOST_ASSERT(len <= (int)size); return len; }
void logger::init(const config_tree& a_cfg, const sigset_t* a_ignore_signals, bool a_install_finalizer) { if (m_initialized) throw std::runtime_error("Logger already initialized!"); std::lock_guard<std::mutex> guard(m_mutex); do_finalize(); try { m_show_location = a_cfg.get<bool> ("logger.show-location", m_show_location); m_show_fun_namespaces = a_cfg.get<int> ("logger.show-fun-namespaces", m_show_fun_namespaces); m_show_category = a_cfg.get<bool> ("logger.show-category", m_show_category); m_show_ident = a_cfg.get<bool> ("logger.show-ident", m_show_ident); m_show_thread = a_cfg.get<bool> ("logger.show-thread", m_show_thread); m_fatal_kill_signal = a_cfg.get<int> ("logger.fatal-kill-signal",m_fatal_kill_signal); m_ident = a_cfg.get<std::string>("logger.ident", m_ident); m_ident = replace_macros(m_ident); std::string ts = a_cfg.get<std::string>("logger.timestamp", "time-usec"); m_timestamp_type = parse_stamp_type(ts); std::string levs = a_cfg.get<std::string>("logger.levels", ""); if (!levs.empty()) set_level_filter(static_cast<log_level>(parse_log_levels(levs))); std::string ls = a_cfg.get<std::string>("logger.min-level-filter", "info"); if (!levs.empty() && !ls.empty()) std::runtime_error ("Either 'levels' or 'min-level-filter' option is permitted!"); set_min_level_filter(parse_log_level(ls)); long timeout_ms = a_cfg.get<int> ("logger.wait-timeout-ms", 1000); m_wait_timeout = timespec{timeout_ms / 1000, timeout_ms % 1000 * 1000000L}; m_sched_yield_us = a_cfg.get<long> ("logger.sched-yield-us", -1); m_silent_finish = a_cfg.get<bool> ("logger.silent-finish", false); m_block_signals = a_cfg.get<bool> ("logger.block-signals", true); if ((int)m_timestamp_type < 0) throw std::runtime_error("Invalid timestamp type: " + ts); // Install crash signal handlers // (SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM) if (a_cfg.get("logger.handle-crash-signals", true)) { sigset_t sset = sig_members_parse (a_cfg.get("logger.handle-crash-signals.signals",""), UTXX_SRC); // Remove signals from the sset that are handled externally if (a_ignore_signals) for (uint i=1; i < sig_names_count(); ++i) if (sigismember(a_ignore_signals, i)) sigdelset(&sset, i); if (install_sighandler(true, &sset)) { auto old = m_crash_sigset.exchange(new sigset_t(sset)); if (!old) delete old; } } //logger_impl::msg_info info(NULL, 0); //query_timestamp(info); logger_impl_mgr& lim = logger_impl_mgr::instance(); std::lock_guard<std::mutex> guard(lim.mutex()); // Check the list of registered implementations. If corresponding // configuration section is found, initialize the implementation. for(logger_impl_mgr::impl_map_t::iterator it=lim.implementations().begin(); it != lim.implementations().end(); ++it) { std::string path = std::string("logger.") + it->first; if (a_cfg.get_child_optional(path)) { // Determine if implementation of this type is already // registered with the logger bool found = false; for(implementations_vector::iterator im = m_implementations.begin(), iend = m_implementations.end(); im != iend; ++im) if (it->first == (*im)->name()) { found = true; break; } if (found) throw badarg_error("Implementation '", it->first, "' is already registered with the logger!"); // A call to it->second() creates a logger_impl* pointer. // We need to call implementation's init function that may throw, // so use RAII to guarantee proper cleanup. logger_impl_mgr::impl_callback_t& f = it->second; m_implementations.emplace_back( f(it->first.c_str()) ); auto& i = m_implementations.back(); i->set_log_mgr(this); i->init(a_cfg); } } m_initialized = true; m_abort = false; m_thread.reset(new std::thread([this]() { this->run(); })); if (!m_finalizer_installed && a_install_finalizer) { atexit(&finalize_logger_at_exit); m_finalizer_installed = true; } } catch (std::runtime_error& e) { if (m_error) m_error(e.what()); else throw; } }