Loading src/logger.hpp +126 −36 Original line number Diff line number Diff line // // Copyright (C) 2017 Barcelona Supercomputing Center // Centro Nacional de Supercomputacion // // This file is part of the Data Scheduler, a daemon for tracking and managing // requests for asynchronous data transfer in a hierarchical storage environment. // // See AUTHORS file in the top level directory for information // regarding developers and contributors. // // The Data Scheduler is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Data Scheduler is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with Data Scheduler. If not, see <http://www.gnu.org/licenses/>. // // /************************************************************************* * Copyright (C) 2017-2018 Barcelona Supercomputing Center * * Centro Nacional de Supercomputacion * * * * This file is part of the Data Scheduler, a daemon for tracking and * * managing requests for asynchronous data transfer in a hierarchical * * storage environment. * * * * See AUTHORS file in the top level directory for information * * regarding developers and contributors. * * * * The Data Scheduler is free software: you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public License * * as published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version. * * * * The Data Scheduler is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General * * Public License along with Data Scheduler. If not, see * * <http://www.gnu.org/licenses/>. * * * *************************************************************************/ #ifndef __LOGGER_HPP__ #define __LOGGER_HPP__ #include <spdlog/spdlog.h> #include <spdlog/fmt/ostr.h> #include <sstream> class logger { static const int32_t queue_size = 8192; // must be a power of 2 public: logger(const std::string& ident, const std::string& type) { logger(const std::string& ident, const std::string& type, const std::string& logfile="") { try { if(type == "stdout") { if(type == "console") { spdlog::set_async_mode(queue_size); m_internal_logger = spdlog::stdout_logger_mt(ident); } else if(type == "stdout color") { else if(type == "console color") { spdlog::set_async_mode(queue_size); m_internal_logger = spdlog::stdout_color_mt(ident); } Loading @@ -50,32 +55,96 @@ public: m_internal_logger = spdlog::syslog_logger("syslog", ident, LOG_PID); } #endif else if(type == "file") { m_internal_logger = spdlog::basic_logger_mt(ident, logfile); } else { // FIXME: add custom exceptions here! std::cerr << "Unknown logger type: '" << type << "'\n"; abort(); throw std::invalid_argument("Unknown logger type: '" + type + "'"); } assert(m_internal_logger != nullptr); // %Y - Year in 4 digits // %m - month 1-12 // %d - day 1-31 // %T - ISO 8601 time format (HH:MM:SS) // %f - microsecond part of the current second // %E - epoch (microseconds precision) // %n - logger's name // %t - thread id // %l - log level // %v - message //m_internal_logger->set_pattern("[%Y-%m-%d %T.%f] [%E] [%n] [%t] [%l] %v"); m_internal_logger->set_pattern("[%Y-%m-%d %T.%f] [%n] [%t] [%l] %v"); spdlog::drop_all(); // globally register the logger so that it can be accessed // using spdlog::get(logger_name) spdlog::register_logger(m_internal_logger); //spdlog::register_logger(m_internal_logger); } catch(const spdlog::spdlog_ex& ex) { // FIXME: add custom exceptions here! std::cerr << "spdlog initialization failed!: " << ex.what() << std::endl; abort(); throw std::runtime_error("logger initialization failed: " + std::string(ex.what())); } } logger(const logger& rhs) = delete; logger& operator=(const logger& rhs) = delete; logger(logger&& other) = default; logger& operator=(logger&& other) = default; ~logger(){ // std::cerr << "XXXXXXXXXX called!\n"; spdlog::drop_all(); } // the following static functions can be used to interact // with a globally registered logger instance template <typename... Args> static inline void create_global_logger(Args&&... args) { global_logger() = std::make_shared<logger>(args...); } static inline void register_global_logger(logger&& lg) { global_logger() = std::make_shared<logger>(std::move(lg)); } static inline std::shared_ptr<logger>& get_global_logger() { return global_logger(); } // some macros to make it more convenient to use the global logger #define LOGGER_INFO(...) \ efsng::logger::get_global_logger()->info(__VA_ARGS__) #ifdef __LOGGER_ENABLE_DEBUG__ #define LOGGER_DEBUG(...) \ efsng::logger::get_global_logger()->debug(__VA_ARGS__) #else #define LOGGER_DEBUG(...) \ do {} while(0) #endif #define LOGGER_WARN(...) \ efsng::logger::get_global_logger()->warn(__VA_ARGS__) #define LOGGER_ERROR(...) \ efsng::logger::get_global_logger()->error(__VA_ARGS__) #define LOGGER_CRITICAL(...) \ efsng::logger::get_global_logger()->critical(__VA_ARGS__) // the following member functions can be used to interact // with a specific logger instance inline void enable_debug() const { m_internal_logger->set_level(spdlog::level::debug); } inline void flush() { m_internal_logger->flush(); } template <typename... Args> inline void info(const char* fmt, const Args&... args) { m_internal_logger->info(fmt, args...); Loading Loading @@ -126,10 +195,31 @@ public: m_internal_logger->critical(msg); } template <typename... Args> static inline std::string build_message(Args&&... args) { // see: // 1. https://stackoverflow.com/questions/27375089/what-is-the-easiest-way-to-print-a-variadic-parameter-pack-using-stdostream // 2. https://stackoverflow.com/questions/25680461/variadic-template-pack-expansion/25683817#25683817 std::stringstream ss; using expander = int[]; (void) expander{0, (void(ss << std::forward<Args>(args)),0)...}; return ss.str(); } private: static std::shared_ptr<logger>& global_logger() { static std::shared_ptr<logger> s_global_logger; return s_global_logger; } private: std::shared_ptr<spdlog::logger> m_internal_logger; std::string m_type; }; #endif /* __LOGGER_HPP__ */ src/spdlog/async_logger.h +5 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,11 @@ public: //Wait for the queue to be empty, and flush synchronously //Warning: this can potentialy last forever as we wait it to complete void flush() override; // Error handler virtual void set_error_handler(log_err_handler) override; virtual log_err_handler error_handler() override; protected: void _sink_it(details::log_msg& msg) override; void _set_formatter(spdlog::formatter_ptr msg_formatter) override; Loading src/spdlog/details/async_log_helper.h +32 −19 Original line number Diff line number Diff line Loading @@ -135,6 +135,7 @@ public: void flush(bool wait_for_q); void set_error_handler(spdlog::log_err_handler err_handler); private: formatter_ptr _formatter; Loading Loading @@ -221,7 +222,8 @@ inline spdlog::details::async_log_helper::~async_log_helper() _worker_thread.join(); } catch (...) // don't crash in destructor {} { } } Loading Loading @@ -255,14 +257,16 @@ inline void spdlog::details::async_log_helper::flush(bool wait_for_q) } inline void spdlog::details::async_log_helper::worker_loop() { try { if (_worker_warmup_cb) _worker_warmup_cb(); auto last_pop = details::os::now(); auto last_flush = last_pop; while(process_next_msg(last_pop, last_flush)); if (_worker_teardown_cb) _worker_teardown_cb(); auto active = true; while (active) { try { active = process_next_msg(last_pop, last_flush); } catch (const std::exception &ex) { Loading @@ -273,6 +277,10 @@ inline void spdlog::details::async_log_helper::worker_loop() _err_handler("Unknown exception"); } } if (_worker_teardown_cb) _worker_teardown_cb(); } // process next message in the queue // return true if this thread should still be active (while no terminate msg was received) Loading Loading @@ -374,5 +382,10 @@ inline void spdlog::details::async_log_helper::wait_empty_q() } } inline void spdlog::details::async_log_helper::set_error_handler(spdlog::log_err_handler err_handler) { _err_handler = err_handler; } src/spdlog/details/async_logger_impl.h +13 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,19 @@ inline void spdlog::async_logger::flush() _async_log_helper->flush(true); } // Error handler inline void spdlog::async_logger::set_error_handler(spdlog::log_err_handler err_handler) { _err_handler = err_handler; _async_log_helper->set_error_handler(err_handler); } inline spdlog::log_err_handler spdlog::async_logger::error_handler() { return _err_handler; } inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) { _formatter = msg_formatter; Loading src/spdlog/details/logger_impl.h +18 −20 Original line number Diff line number Diff line Loading @@ -121,44 +121,42 @@ inline void spdlog::logger::log(level::level_enum lvl, const T& msg) } template <typename... Args> inline void spdlog::logger::trace(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::trace(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::trace, fmt, args...); log(level::trace, fmt, arg1, args...); } template <typename... Args> inline void spdlog::logger::debug(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::debug(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::debug, fmt, args...); log(level::debug, fmt, arg1, args...); } template <typename... Args> inline void spdlog::logger::info(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::info(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::info, fmt, args...); log(level::info, fmt, arg1, args...); } template <typename... Args> inline void spdlog::logger::warn(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::warn(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::warn, fmt, args...); log(level::warn, fmt, arg1, args...); } template <typename... Args> inline void spdlog::logger::error(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::error(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::err, fmt, args...); log(level::err, fmt, arg1, args...); } template <typename... Args> inline void spdlog::logger::critical(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::critical(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::critical, fmt, args...); log(level::critical, fmt, arg1, args...); } template<typename T> inline void spdlog::logger::trace(const T& msg) { Loading Loading
src/logger.hpp +126 −36 Original line number Diff line number Diff line // // Copyright (C) 2017 Barcelona Supercomputing Center // Centro Nacional de Supercomputacion // // This file is part of the Data Scheduler, a daemon for tracking and managing // requests for asynchronous data transfer in a hierarchical storage environment. // // See AUTHORS file in the top level directory for information // regarding developers and contributors. // // The Data Scheduler is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Data Scheduler is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with Data Scheduler. If not, see <http://www.gnu.org/licenses/>. // // /************************************************************************* * Copyright (C) 2017-2018 Barcelona Supercomputing Center * * Centro Nacional de Supercomputacion * * * * This file is part of the Data Scheduler, a daemon for tracking and * * managing requests for asynchronous data transfer in a hierarchical * * storage environment. * * * * See AUTHORS file in the top level directory for information * * regarding developers and contributors. * * * * The Data Scheduler is free software: you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public License * * as published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version. * * * * The Data Scheduler is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General * * Public License along with Data Scheduler. If not, see * * <http://www.gnu.org/licenses/>. * * * *************************************************************************/ #ifndef __LOGGER_HPP__ #define __LOGGER_HPP__ #include <spdlog/spdlog.h> #include <spdlog/fmt/ostr.h> #include <sstream> class logger { static const int32_t queue_size = 8192; // must be a power of 2 public: logger(const std::string& ident, const std::string& type) { logger(const std::string& ident, const std::string& type, const std::string& logfile="") { try { if(type == "stdout") { if(type == "console") { spdlog::set_async_mode(queue_size); m_internal_logger = spdlog::stdout_logger_mt(ident); } else if(type == "stdout color") { else if(type == "console color") { spdlog::set_async_mode(queue_size); m_internal_logger = spdlog::stdout_color_mt(ident); } Loading @@ -50,32 +55,96 @@ public: m_internal_logger = spdlog::syslog_logger("syslog", ident, LOG_PID); } #endif else if(type == "file") { m_internal_logger = spdlog::basic_logger_mt(ident, logfile); } else { // FIXME: add custom exceptions here! std::cerr << "Unknown logger type: '" << type << "'\n"; abort(); throw std::invalid_argument("Unknown logger type: '" + type + "'"); } assert(m_internal_logger != nullptr); // %Y - Year in 4 digits // %m - month 1-12 // %d - day 1-31 // %T - ISO 8601 time format (HH:MM:SS) // %f - microsecond part of the current second // %E - epoch (microseconds precision) // %n - logger's name // %t - thread id // %l - log level // %v - message //m_internal_logger->set_pattern("[%Y-%m-%d %T.%f] [%E] [%n] [%t] [%l] %v"); m_internal_logger->set_pattern("[%Y-%m-%d %T.%f] [%n] [%t] [%l] %v"); spdlog::drop_all(); // globally register the logger so that it can be accessed // using spdlog::get(logger_name) spdlog::register_logger(m_internal_logger); //spdlog::register_logger(m_internal_logger); } catch(const spdlog::spdlog_ex& ex) { // FIXME: add custom exceptions here! std::cerr << "spdlog initialization failed!: " << ex.what() << std::endl; abort(); throw std::runtime_error("logger initialization failed: " + std::string(ex.what())); } } logger(const logger& rhs) = delete; logger& operator=(const logger& rhs) = delete; logger(logger&& other) = default; logger& operator=(logger&& other) = default; ~logger(){ // std::cerr << "XXXXXXXXXX called!\n"; spdlog::drop_all(); } // the following static functions can be used to interact // with a globally registered logger instance template <typename... Args> static inline void create_global_logger(Args&&... args) { global_logger() = std::make_shared<logger>(args...); } static inline void register_global_logger(logger&& lg) { global_logger() = std::make_shared<logger>(std::move(lg)); } static inline std::shared_ptr<logger>& get_global_logger() { return global_logger(); } // some macros to make it more convenient to use the global logger #define LOGGER_INFO(...) \ efsng::logger::get_global_logger()->info(__VA_ARGS__) #ifdef __LOGGER_ENABLE_DEBUG__ #define LOGGER_DEBUG(...) \ efsng::logger::get_global_logger()->debug(__VA_ARGS__) #else #define LOGGER_DEBUG(...) \ do {} while(0) #endif #define LOGGER_WARN(...) \ efsng::logger::get_global_logger()->warn(__VA_ARGS__) #define LOGGER_ERROR(...) \ efsng::logger::get_global_logger()->error(__VA_ARGS__) #define LOGGER_CRITICAL(...) \ efsng::logger::get_global_logger()->critical(__VA_ARGS__) // the following member functions can be used to interact // with a specific logger instance inline void enable_debug() const { m_internal_logger->set_level(spdlog::level::debug); } inline void flush() { m_internal_logger->flush(); } template <typename... Args> inline void info(const char* fmt, const Args&... args) { m_internal_logger->info(fmt, args...); Loading Loading @@ -126,10 +195,31 @@ public: m_internal_logger->critical(msg); } template <typename... Args> static inline std::string build_message(Args&&... args) { // see: // 1. https://stackoverflow.com/questions/27375089/what-is-the-easiest-way-to-print-a-variadic-parameter-pack-using-stdostream // 2. https://stackoverflow.com/questions/25680461/variadic-template-pack-expansion/25683817#25683817 std::stringstream ss; using expander = int[]; (void) expander{0, (void(ss << std::forward<Args>(args)),0)...}; return ss.str(); } private: static std::shared_ptr<logger>& global_logger() { static std::shared_ptr<logger> s_global_logger; return s_global_logger; } private: std::shared_ptr<spdlog::logger> m_internal_logger; std::string m_type; }; #endif /* __LOGGER_HPP__ */
src/spdlog/async_logger.h +5 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,11 @@ public: //Wait for the queue to be empty, and flush synchronously //Warning: this can potentialy last forever as we wait it to complete void flush() override; // Error handler virtual void set_error_handler(log_err_handler) override; virtual log_err_handler error_handler() override; protected: void _sink_it(details::log_msg& msg) override; void _set_formatter(spdlog::formatter_ptr msg_formatter) override; Loading
src/spdlog/details/async_log_helper.h +32 −19 Original line number Diff line number Diff line Loading @@ -135,6 +135,7 @@ public: void flush(bool wait_for_q); void set_error_handler(spdlog::log_err_handler err_handler); private: formatter_ptr _formatter; Loading Loading @@ -221,7 +222,8 @@ inline spdlog::details::async_log_helper::~async_log_helper() _worker_thread.join(); } catch (...) // don't crash in destructor {} { } } Loading Loading @@ -255,14 +257,16 @@ inline void spdlog::details::async_log_helper::flush(bool wait_for_q) } inline void spdlog::details::async_log_helper::worker_loop() { try { if (_worker_warmup_cb) _worker_warmup_cb(); auto last_pop = details::os::now(); auto last_flush = last_pop; while(process_next_msg(last_pop, last_flush)); if (_worker_teardown_cb) _worker_teardown_cb(); auto active = true; while (active) { try { active = process_next_msg(last_pop, last_flush); } catch (const std::exception &ex) { Loading @@ -273,6 +277,10 @@ inline void spdlog::details::async_log_helper::worker_loop() _err_handler("Unknown exception"); } } if (_worker_teardown_cb) _worker_teardown_cb(); } // process next message in the queue // return true if this thread should still be active (while no terminate msg was received) Loading Loading @@ -374,5 +382,10 @@ inline void spdlog::details::async_log_helper::wait_empty_q() } } inline void spdlog::details::async_log_helper::set_error_handler(spdlog::log_err_handler err_handler) { _err_handler = err_handler; }
src/spdlog/details/async_logger_impl.h +13 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,19 @@ inline void spdlog::async_logger::flush() _async_log_helper->flush(true); } // Error handler inline void spdlog::async_logger::set_error_handler(spdlog::log_err_handler err_handler) { _err_handler = err_handler; _async_log_helper->set_error_handler(err_handler); } inline spdlog::log_err_handler spdlog::async_logger::error_handler() { return _err_handler; } inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) { _formatter = msg_formatter; Loading
src/spdlog/details/logger_impl.h +18 −20 Original line number Diff line number Diff line Loading @@ -121,44 +121,42 @@ inline void spdlog::logger::log(level::level_enum lvl, const T& msg) } template <typename... Args> inline void spdlog::logger::trace(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::trace(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::trace, fmt, args...); log(level::trace, fmt, arg1, args...); } template <typename... Args> inline void spdlog::logger::debug(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::debug(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::debug, fmt, args...); log(level::debug, fmt, arg1, args...); } template <typename... Args> inline void spdlog::logger::info(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::info(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::info, fmt, args...); log(level::info, fmt, arg1, args...); } template <typename... Args> inline void spdlog::logger::warn(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::warn(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::warn, fmt, args...); log(level::warn, fmt, arg1, args...); } template <typename... Args> inline void spdlog::logger::error(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::error(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::err, fmt, args...); log(level::err, fmt, arg1, args...); } template <typename... Args> inline void spdlog::logger::critical(const char* fmt, const Args&... args) template <typename Arg1, typename... Args> inline void spdlog::logger::critical(const char* fmt, const Arg1 &arg1, const Args&... args) { log(level::critical, fmt, args...); log(level::critical, fmt, arg1, args...); } template<typename T> inline void spdlog::logger::trace(const T& msg) { Loading