diff --git a/example/bench.cpp b/example/bench.cpp index 49385e0f..9780e85f 100644 --- a/example/bench.cpp +++ b/example/bench.cpp @@ -6,10 +6,10 @@ // // bench.cpp : spdlog benchmarks // -#include "spdlog/async_logger.h" -#include "spdlog/sinks/file_sinks.h" +#include "spdlog/async.h" #include "spdlog/sinks/null_sink.h" #include "spdlog/spdlog.h" + #include "utils.h" #include #include // EXIT_FAILURE @@ -71,11 +71,10 @@ int main(int argc, char *argv[]) cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations " << endl; cout << "*******************************************************************************\n"; - spdlog::set_async_mode(queue_size); - for (int i = 0; i < 3; ++i) { - auto as = spdlog::daily_logger_st("as", "logs/daily_async.log"); + spdlog::init_thread_pool(queue_size, 1); + auto as = spdlog::daily_logger_mt("as", "logs/daily_async.log"); bench_mt(howmany, as, threads); spdlog::drop("as"); } diff --git a/example/example.cpp b/example/example.cpp index 6144c065..f1d20fbe 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -10,6 +10,7 @@ #define SPDLOG_TRACE_ON #define SPDLOG_DEBUG_ON +#include "spdlog/async.h" #include "spdlog/spdlog.h" #include @@ -27,9 +28,10 @@ int main(int, char *[]) try { // Console logger with color - auto console = spd::stdout_color_mt("console"); + auto console = spdlog::console("console"); + auto console2 = spdlog::console("console"); console->info("Welcome to spdlog!"); - console->error("Some error message with arg{}..", 1); + console->error("Some error message with arg: {}", 1); // Formatting examples console->warn("Easy padding in numbers like {:08d}", 12); @@ -105,13 +107,16 @@ int main(int, char *[]) void async_example() { - size_t q_size = 4096; // queue size must be power of 2 - spdlog::set_async_mode(q_size); - auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt"); + + auto async_file = spd::basic_logger_mt("async_file_logger", "logs/async_log.txt"); for (int i = 0; i < 100; ++i) { async_file->info("Async message #{}", i); } + + // optional change thread pool settings *before* creating the logger: + // spdlog::init_thread_pool(8192, 1); + // if not called a defaults are: 8192 queue size and 1 worker thread. } // syslog example (linux/osx/freebsd) diff --git a/include/spdlog/async_logger.h b/include/spdlog/async_logger.h index 75641d26..ca4a6ef2 100644 --- a/include/spdlog/async_logger.h +++ b/include/spdlog/async_logger.h @@ -20,52 +20,39 @@ #include #include +#include #include #include - namespace spdlog { - namespace details { -class async_log_helper; +class thread_pool; } -class async_logger SPDLOG_FINAL : public logger +class async_logger SPDLOG_FINAL : public std::enable_shared_from_this, public logger { + friend class details::thread_pool; + public: template - async_logger(const std::string &logger_name, const It &begin, const It &end, size_t queue_size, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function &worker_warmup_cb = nullptr, - const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function &worker_teardown_cb = nullptr); + async_logger(const std::string &logger_name, const It &begin, const It &end, std::weak_ptr tp, + async_overflow_policy overflow_policy = async_overflow_policy::block_retry); - async_logger(const std::string &logger_name, sinks_init_list sinks, size_t queue_size, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function &worker_warmup_cb = nullptr, - const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function &worker_teardown_cb = nullptr); + async_logger(const std::string &logger_name, sinks_init_list sinks, std::weak_ptr tp, + async_overflow_policy overflow_policy = async_overflow_policy::block_retry); - async_logger(const std::string &logger_name, sink_ptr single_sink, size_t queue_size, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function &worker_warmup_cb = nullptr, - const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function &worker_teardown_cb = nullptr); - - // Wait for the queue to be empty, and flush synchronously - // Warning: this can potentially last forever as we wait it to complete - void flush() override; - - // Error handler - void set_error_handler(log_err_handler) override; - log_err_handler error_handler() override; + async_logger(const std::string &logger_name, sink_ptr single_sink, std::weak_ptr tp, + async_overflow_policy overflow_policy = async_overflow_policy::block_retry); protected: void _sink_it(details::log_msg &msg) override; - void _set_formatter(spdlog::formatter_ptr msg_formatter) override; - void _set_pattern(const std::string &pattern, pattern_time_type pattern_time) override; + void _flush() override; + + void _backend_log(details::log_msg &incoming_log_msg); + void _backend_flush(); private: - std::unique_ptr _async_log_helper; + std::weak_ptr _thread_pool; + async_overflow_policy _overflow_policy; }; } // namespace spdlog diff --git a/include/spdlog/contrib/README.md b/include/spdlog/contrib/README.md deleted file mode 100644 index e3abc34d..00000000 --- a/include/spdlog/contrib/README.md +++ /dev/null @@ -1 +0,0 @@ -Please put here your contribs. Popular contribs will be moved to main tree after stablization diff --git a/include/spdlog/contrib/sinks/.gitignore b/include/spdlog/contrib/sinks/.gitignore deleted file mode 100644 index 8b137891..00000000 --- a/include/spdlog/contrib/sinks/.gitignore +++ /dev/null @@ -1 +0,0 @@ - diff --git a/include/spdlog/details/async_log_helper.h b/include/spdlog/details/async_log_helper.h index a7780740..d2f72b68 100644 --- a/include/spdlog/details/async_log_helper.h +++ b/include/spdlog/details/async_log_helper.h @@ -72,8 +72,7 @@ class async_log_helper msg_id(other.msg_id) { } - - async_msg &operator=(async_msg &&other) SPDLOG_NOEXCEPT + dsdfsfs async_msg &operator=(async_msg &&other) SPDLOG_NOEXCEPT { logger_name = std::move(other.logger_name); level = other.level; diff --git a/include/spdlog/details/async_logger_impl.h b/include/spdlog/details/async_logger_impl.h index 748a53ac..aa617fa2 100644 --- a/include/spdlog/details/async_logger_impl.h +++ b/include/spdlog/details/async_logger_impl.h @@ -5,71 +5,37 @@ #pragma once -// Async Logger implementation -// Use an async_sink (queue per logger) to perform the logging in a worker thread +// async logger implementation +// uses a thread pool to perform the actual logging -#include "../async_logger.h" -#include "../details/async_log_helper.h" +#include "../details/thread_pool.h" #include -#include #include #include template -inline spdlog::async_logger::async_logger(const std::string &logger_name, const It &begin, const It &end, size_t queue_size, - const async_overflow_policy overflow_policy, const std::function &worker_warmup_cb, - const std::chrono::milliseconds &flush_interval_ms, const std::function &worker_teardown_cb) +inline spdlog::async_logger::async_logger(const std::string &logger_name, const It &begin, const It &end, + std::weak_ptr tp, async_overflow_policy overflow_policy) : logger(logger_name, begin, end) - , _async_log_helper(new details::async_log_helper( - _formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb)) + , _thread_pool(tp) + , _overflow_policy(overflow_policy) { } -inline spdlog::async_logger::async_logger(const std::string &logger_name, sinks_init_list sinks_list, size_t queue_size, - const async_overflow_policy overflow_policy, const std::function &worker_warmup_cb, - const std::chrono::milliseconds &flush_interval_ms, const std::function &worker_teardown_cb) - : async_logger(logger_name, sinks_list.begin(), sinks_list.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, - worker_teardown_cb) +inline spdlog::async_logger::async_logger(const std::string &logger_name, sinks_init_list sinks_list, + std::weak_ptr tp, async_overflow_policy overflow_policy) + : async_logger(logger_name, sinks_list.begin(), sinks_list.end(), tp, overflow_policy) { } -inline spdlog::async_logger::async_logger(const std::string &logger_name, sink_ptr single_sink, size_t queue_size, - const async_overflow_policy overflow_policy, const std::function &worker_warmup_cb, - const std::chrono::milliseconds &flush_interval_ms, const std::function &worker_teardown_cb) - : async_logger( - logger_name, {std::move(single_sink)}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) +inline spdlog::async_logger::async_logger( + const std::string &logger_name, sink_ptr single_sink, std::weak_ptr tp, async_overflow_policy overflow_policy) + : async_logger(logger_name, {single_sink}, tp, overflow_policy) { } -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; - _async_log_helper->set_formatter(_formatter); -} - -inline void spdlog::async_logger::_set_pattern(const std::string &pattern, pattern_time_type pattern_time) -{ - _formatter = std::make_shared(pattern, pattern_time); - _async_log_helper->set_formatter(_formatter); -} - +// send the log message to the thread pool inline void spdlog::async_logger::_sink_it(details::log_msg &msg) { try @@ -77,10 +43,13 @@ inline void spdlog::async_logger::_sink_it(details::log_msg &msg) #if defined(SPDLOG_ENABLE_MESSAGE_COUNTER) _incr_msg_counter(msg); #endif - _async_log_helper->log(msg); - if (_should_flush_on(msg)) + if (auto pool_ptr = _thread_pool.lock()) { - _async_log_helper->flush(false); // do async flush + pool_ptr->post_log(shared_from_this(), std::move(msg), _overflow_policy); + } + else + { + throw spdlog_ex("async log: thread pool doens't exist anymore"); } } catch (const std::exception &ex) @@ -89,7 +58,65 @@ inline void spdlog::async_logger::_sink_it(details::log_msg &msg) } catch (...) { - _err_handler("Unknown exception in logger " + _name); - throw; + _err_handler("Unknown exception in async logger " + _name); + } +} + +// send flush request to the thread pool +inline void spdlog::async_logger::_flush() +{ + if (auto pool_ptr = _thread_pool.lock()) + { + pool_ptr->post_flush(shared_from_this(), _overflow_policy); + } + else + { + throw spdlog_ex("async flush: thread pool doens't exist anymore"); + } +} + +// +// backend functions - called from the thread pool to do the actual job +// +inline void spdlog::async_logger::_backend_log(details::log_msg &incoming_log_msg) +{ + try + { + _formatter->format(incoming_log_msg); + for (auto &s : _sinks) + { + if (s->should_log(incoming_log_msg.level)) + { + s->log(incoming_log_msg); + } + } + } + catch (const std::exception &ex) + { + _err_handler(ex.what()); + } + catch (...) + { + _err_handler("Unknown exception in async logger " + _name); + } +} + +inline void spdlog::async_logger::_backend_flush() +{ + try + { + + for (auto &sink : _sinks) + { + sink->flush(); + } + } + catch (const std::exception &ex) + { + _err_handler(ex.what()); + } + catch (...) + { + _err_handler("Unknown exception in async logger " + _name); } } diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 1d079aaf..ee471e6a 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -30,8 +30,8 @@ struct log_msg } log_msg(const log_msg &other) = delete; - log_msg &operator=(log_msg &&other) = delete; log_msg(log_msg &&other) = delete; + log_msg &operator=(log_msg &&other) = delete; const std::string *logger_name{nullptr}; level::level_enum level; @@ -40,7 +40,7 @@ struct log_msg fmt::MemoryWriter raw; fmt::MemoryWriter formatted; size_t msg_id{0}; - // wrap this range with color codes + // info about wrapping the formatted text with color size_t color_range_start{0}; size_t color_range_end{0}; }; diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index d5487249..f2e0f8e1 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -42,12 +42,12 @@ inline spdlog::logger::~logger() = default; inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter) { - _set_formatter(std::move(msg_formatter)); + _formatter = std::move(msg_formatter); } inline void spdlog::logger::set_pattern(const std::string &pattern, pattern_time_type pattern_time) { - _set_pattern(pattern, pattern_time); + _formatter = std::make_shared(pattern, pattern_time); } template @@ -282,11 +282,22 @@ inline spdlog::log_err_handler spdlog::logger::error_handler() return _err_handler; } +inline void spdlog::logger::flush() +{ + _flush(); +} + inline void spdlog::logger::flush_on(level::level_enum log_level) { _flush_level.store(log_level); } +inline bool spdlog::logger::_should_flush(const details::log_msg &msg) +{ + auto flush_level = _flush_level.load(std::memory_order_relaxed); + return (msg.level >= flush_level) && (msg.level != level::off); +} + inline spdlog::level::level_enum spdlog::logger::level() const { return static_cast(_level.load(std::memory_order_relaxed)); @@ -314,23 +325,13 @@ inline void spdlog::logger::_sink_it(details::log_msg &msg) } } - if (_should_flush_on(msg)) + if (_should_flush(msg)) { flush(); } } -inline void spdlog::logger::_set_pattern(const std::string &pattern, pattern_time_type pattern_time) -{ - _formatter = std::make_shared(pattern, pattern_time); -} - -inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter) -{ - _formatter = std::move(msg_formatter); -} - -inline void spdlog::logger::flush() +inline void spdlog::logger::_flush() { for (auto &sink : _sinks) { @@ -345,19 +346,11 @@ inline void spdlog::logger::_default_err_handler(const std::string &msg) { return; } + _last_err_time = now; auto tm_time = details::os::localtime(now); char date_buf[100]; std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); - details::log_msg err_msg; - err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::default_eol); - sinks::stderr_sink_mt::instance()->log(err_msg); - _last_err_time = now; -} - -inline bool spdlog::logger::_should_flush_on(const details::log_msg &msg) -{ - const auto flush_level = _flush_level.load(std::memory_order_relaxed); - return (msg.level >= flush_level) && (msg.level != level::off); + fmt::print(stderr, "[*** LOG ERROR ***] [{}] [{}] {}\n", date_buf, name(), msg); } inline void spdlog::logger::_incr_msg_counter(details::log_msg &msg) diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 614220d5..bda9bb7b 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -10,33 +10,57 @@ // If user requests a non existing logger, nullptr will be returned // This class is thread safe -#include "../async_logger.h" #include "../common.h" -#include "../details/null_mutex.h" #include "../logger.h" #include #include #include -#include #include #include namespace spdlog { namespace details { +class thread_pool; + template class registry_t { public: + using MutexT = Mutex; + registry_t(const registry_t &) = delete; registry_t &operator=(const registry_t &) = delete; - void register_logger(std::shared_ptr logger) + void register_logger(std::shared_ptr new_logger) { std::lock_guard lock(_mutex); - auto logger_name = logger->name(); + auto logger_name = new_logger->name(); throw_if_exists(logger_name); - _loggers[logger_name] = logger; + _loggers[logger_name] = new_logger; + } + + void register_and_init(std::shared_ptr new_logger) + { + std::lock_guard lock(_mutex); + auto logger_name = new_logger->name(); + throw_if_exists(logger_name); + + if (_formatter) + { + new_logger->set_formatter(_formatter); + } + + if (_err_handler) + { + new_logger->set_error_handler(_err_handler); + } + + new_logger->set_level(_level); + new_logger->flush_on(_flush_level); + + // Add to registry + _loggers[logger_name] = new_logger; } std::shared_ptr get(const std::string &logger_name) @@ -46,116 +70,19 @@ public: return found == _loggers.end() ? nullptr : found->second; } - template - std::shared_ptr create(const std::string &logger_name, const It &sinks_begin, const It &sinks_end) + void set_thread_pool(std::shared_ptr tp) { std::lock_guard lock(_mutex); - throw_if_exists(logger_name); - std::shared_ptr new_logger; - if (_async_mode) - { - new_logger = std::make_shared(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, - _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb); - } - else - { - new_logger = std::make_shared(logger_name, sinks_begin, sinks_end); - } - - if (_formatter) - { - new_logger->set_formatter(_formatter); - } - - if (_err_handler) - { - new_logger->set_error_handler(_err_handler); - } - - new_logger->set_level(_level); - new_logger->flush_on(_flush_level); - - // Add to registry - _loggers[logger_name] = new_logger; - return new_logger; + _tp = std::move(tp); } - template - std::shared_ptr create_async(const std::string &logger_name, size_t queue_size, - const async_overflow_policy overflow_policy, const std::function &worker_warmup_cb, - const std::chrono::milliseconds &flush_interval_ms, const std::function &worker_teardown_cb, const It &sinks_begin, - const It &sinks_end) + std::shared_ptr get_thread_pool() { std::lock_guard lock(_mutex); - throw_if_exists(logger_name); - auto new_logger = std::make_shared( - logger_name, sinks_begin, sinks_end, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb); - - if (_formatter) - { - new_logger->set_formatter(_formatter); - } - - if (_err_handler) - { - new_logger->set_error_handler(_err_handler); - } - - new_logger->set_level(_level); - new_logger->flush_on(_flush_level); - - // Add to registry - _loggers[logger_name] = new_logger; - return new_logger; + return _tp; } - void apply_all(std::function)> fun) - { - std::lock_guard lock(_mutex); - for (auto &l : _loggers) - { - fun(l.second); - } - } - - void drop(const std::string &logger_name) - { - std::lock_guard lock(_mutex); - _loggers.erase(logger_name); - } - - void drop_all() - { - std::lock_guard lock(_mutex); - _loggers.clear(); - } - - std::shared_ptr create(const std::string &logger_name, sinks_init_list sinks) - { - return create(logger_name, sinks.begin(), sinks.end()); - } - - std::shared_ptr create(const std::string &logger_name, sink_ptr sink) - { - return create(logger_name, {sink}); - } - - std::shared_ptr create_async(const std::string &logger_name, size_t queue_size, - const async_overflow_policy overflow_policy, const std::function &worker_warmup_cb, - const std::chrono::milliseconds &flush_interval_ms, const std::function &worker_teardown_cb, sinks_init_list sinks) - { - return create_async( - logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks.begin(), sinks.end()); - } - - std::shared_ptr create_async(const std::string &logger_name, size_t queue_size, - const async_overflow_policy overflow_policy, const std::function &worker_warmup_cb, - const std::chrono::milliseconds &flush_interval_ms, const std::function &worker_teardown_cb, sink_ptr sink) - { - return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, {sink}); - } - - void formatter(formatter_ptr f) + void set_formatter(formatter_ptr f) { std::lock_guard lock(_mutex); _formatter = f; @@ -204,22 +131,30 @@ public: _err_handler = handler; } - void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function &worker_warmup_cb, - const std::chrono::milliseconds &flush_interval_ms, const std::function &worker_teardown_cb) + void apply_all(std::function)> fun) { std::lock_guard lock(_mutex); - _async_mode = true; - _async_q_size = q_size; - _overflow_policy = overflow_policy; - _worker_warmup_cb = worker_warmup_cb; - _flush_interval_ms = flush_interval_ms; - _worker_teardown_cb = worker_teardown_cb; + for (auto &l : _loggers) + { + fun(l.second); + } } - void set_sync_mode() + void drop(const std::string &logger_name) { std::lock_guard lock(_mutex); - _async_mode = false; + _loggers.erase(logger_name); + } + + void drop_all() + { + std::lock_guard lock(_mutex); + _loggers.clear(); + } + + Mutex &tp_mutex() + { + return _tp_mutex; } static registry_t &instance() @@ -240,24 +175,22 @@ private: } Mutex _mutex; + Mutex _tp_mutex; std::unordered_map> _loggers; formatter_ptr _formatter; level::level_enum _level = level::info; level::level_enum _flush_level = level::off; log_err_handler _err_handler; - bool _async_mode = false; - size_t _async_q_size = 0; - async_overflow_policy _overflow_policy = async_overflow_policy::block_retry; - std::function _worker_warmup_cb; - std::chrono::milliseconds _flush_interval_ms{std::chrono::milliseconds::zero()}; - std::function _worker_teardown_cb; + std::shared_ptr _tp; }; #ifdef SPDLOG_NO_REGISTRY_MUTEX +#include "../details/null_mutex.h" using registry = registry_t; #else +#include using registry = registry_t; #endif } // namespace details -} // namespace spdlog +} // namespace spdlog \ No newline at end of file diff --git a/include/spdlog/details/spdlog_impl.h b/include/spdlog/details/spdlog_impl.h index 4c363834..570756b7 100644 --- a/include/spdlog/details/spdlog_impl.h +++ b/include/spdlog/details/spdlog_impl.h @@ -1,278 +1,201 @@ +//// +//// Copyright(c) 2015 Gabi Melman. +//// Distributed under the MIT License (http://opensource.org/licenses/MIT) +//// // -// Copyright(c) 2015 Gabi Melman. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) +//#pragma once // - -#pragma once - +//// +//// Global registry functions +//// +//#include "../details/registry.h" +//#include "../sinks/file_sinks.h" +//#include "../sinks/stdout_sinks.h" +//#include "../spdlog.h" +//#ifdef SPDLOG_ENABLE_SYSLOG +//#include "../sinks/syslog_sink.h" +//#endif // -// Global registry functions +//#if defined _WIN32 && !defined(__cplusplus_winrt) +//#include "../sinks/wincolor_sink.h" +//#else +//#include "../sinks/ansicolor_sink.h" +//#endif // -#include "../details/registry.h" -#include "../sinks/file_sinks.h" -#include "../sinks/stdout_sinks.h" -#include "../spdlog.h" -#ifdef SPDLOG_ENABLE_SYSLOG -#include "../sinks/syslog_sink.h" -#endif - -#if defined _WIN32 && !defined(__cplusplus_winrt) -#include "../sinks/wincolor_sink.h" -#else -#include "../sinks/ansicolor_sink.h" -#endif - -#ifdef __ANDROID__ -#include "../sinks/android_sink.h" -#endif - -#include -#include -#include -#include - -inline void spdlog::register_logger(std::shared_ptr logger) -{ - return details::registry::instance().register_logger(std::move(logger)); -} - -inline std::shared_ptr spdlog::get(const std::string &name) -{ - return details::registry::instance().get(name); -} - -inline void spdlog::drop(const std::string &name) -{ - details::registry::instance().drop(name); -} - -// Create multi/single threaded simple file logger -inline std::shared_ptr spdlog::basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate) -{ - return create(logger_name, filename, truncate); -} - -inline std::shared_ptr spdlog::basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate) -{ - return create(logger_name, filename, truncate); -} - -// Create multi/single threaded rotating file logger -inline std::shared_ptr spdlog::rotating_logger_mt( - const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files) -{ - return create(logger_name, filename, max_file_size, max_files); -} - -inline std::shared_ptr spdlog::rotating_logger_st( - const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files) -{ - return create(logger_name, filename, max_file_size, max_files); -} - -// Create file logger which creates new file at midnight): -inline std::shared_ptr spdlog::daily_logger_mt( - const std::string &logger_name, const filename_t &filename, int hour, int minute) -{ - return create(logger_name, filename, hour, minute); -} - -inline std::shared_ptr spdlog::daily_logger_st( - const std::string &logger_name, const filename_t &filename, int hour, int minute) -{ - return create(logger_name, filename, hour, minute); -} - +//#ifdef __ANDROID__ +//#include "../sinks/android_sink.h" +//#endif // -// stdout/stderr loggers +//#include +//#include +//#include +//#include // -inline std::shared_ptr spdlog::stdout_logger_mt(const std::string &logger_name) -{ - return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance()); -} - -inline std::shared_ptr spdlog::stdout_logger_st(const std::string &logger_name) -{ - return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_st::instance()); -} - -inline std::shared_ptr spdlog::stderr_logger_mt(const std::string &logger_name) -{ - return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_mt::instance()); -} - -inline std::shared_ptr spdlog::stderr_logger_st(const std::string &logger_name) -{ - return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_st::instance()); -} - +// inline void spdlog::register_logger(std::shared_ptr logger) +//{ +// return details::registry::instance().register_logger(std::move(logger)); +//} // -// stdout/stderr color loggers // -#if defined _WIN32 && !defined(__cplusplus_winrt) - -inline std::shared_ptr spdlog::stdout_color_mt(const std::string &logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); -} - -inline std::shared_ptr spdlog::stdout_color_st(const std::string &logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); -} - -inline std::shared_ptr spdlog::stderr_color_mt(const std::string &logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); -} - -inline std::shared_ptr spdlog::stderr_color_st(const std::string &logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); -} - -#else // ansi terminal colors - -inline std::shared_ptr spdlog::stdout_color_mt(const std::string &logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); -} - -inline std::shared_ptr spdlog::stdout_color_st(const std::string &logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); -} - -inline std::shared_ptr spdlog::stderr_color_mt(const std::string &logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); -} - -inline std::shared_ptr spdlog::stderr_color_st(const std::string &logger_name) -{ - auto sink = std::make_shared(); - return spdlog::details::registry::instance().create(logger_name, sink); -} -#endif - -#ifdef SPDLOG_ENABLE_SYSLOG -// Create syslog logger -inline std::shared_ptr spdlog::syslog_logger( - const std::string &logger_name, const std::string &syslog_ident, int syslog_option, int syslog_facility) -{ - return create(logger_name, syslog_ident, syslog_option, syslog_facility); -} -#endif - -#ifdef __ANDROID__ -inline std::shared_ptr spdlog::android_logger(const std::string &logger_name, const std::string &tag) -{ - return create(logger_name, tag); -} -#endif - -// Create and register a logger a single sink -inline std::shared_ptr spdlog::create(const std::string &logger_name, const spdlog::sink_ptr &sink) -{ - return details::registry::instance().create(logger_name, sink); -} - -// Create logger with multiple sinks -inline std::shared_ptr spdlog::create(const std::string &logger_name, spdlog::sinks_init_list sinks) -{ - return details::registry::instance().create(logger_name, sinks); -} - -template -inline std::shared_ptr spdlog::create(const std::string &logger_name, Args... args) -{ - sink_ptr sink = std::make_shared(args...); - return details::registry::instance().create(logger_name, {sink}); -} - -template -inline std::shared_ptr spdlog::create(const std::string &logger_name, const It &sinks_begin, const It &sinks_end) -{ - return details::registry::instance().create(logger_name, sinks_begin, sinks_end); -} - -// Create and register an async logger with a single sink -inline std::shared_ptr spdlog::create_async(const std::string &logger_name, const sink_ptr &sink, size_t queue_size, - const async_overflow_policy overflow_policy, const std::function &worker_warmup_cb, - const std::chrono::milliseconds &flush_interval_ms, const std::function &worker_teardown_cb) -{ - return details::registry::instance().create_async( - logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sink); -} - -// Create and register an async logger with multiple sinks -inline std::shared_ptr spdlog::create_async(const std::string &logger_name, sinks_init_list sinks, size_t queue_size, - const async_overflow_policy overflow_policy, const std::function &worker_warmup_cb, - const std::chrono::milliseconds &flush_interval_ms, const std::function &worker_teardown_cb) -{ - return details::registry::instance().create_async( - logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks); -} - -template -inline std::shared_ptr spdlog::create_async(const std::string &logger_name, const It &sinks_begin, const It &sinks_end, - size_t queue_size, const async_overflow_policy overflow_policy, const std::function &worker_warmup_cb, - const std::chrono::milliseconds &flush_interval_ms, const std::function &worker_teardown_cb) -{ - return details::registry::instance().create_async( - logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks_begin, sinks_end); -} - -inline void spdlog::set_formatter(spdlog::formatter_ptr f) -{ - details::registry::instance().formatter(std::move(f)); -} - -inline void spdlog::set_pattern(const std::string &format_string) -{ - return details::registry::instance().set_pattern(format_string); -} - -inline void spdlog::set_level(level::level_enum log_level) -{ - return details::registry::instance().set_level(log_level); -} - -inline void spdlog::flush_on(level::level_enum log_level) -{ - return details::registry::instance().flush_on(log_level); -} - -inline void spdlog::set_error_handler(log_err_handler handler) -{ - return details::registry::instance().set_error_handler(std::move(handler)); -} - -inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, - const std::function &worker_warmup_cb, const std::chrono::milliseconds &flush_interval_ms, - const std::function &worker_teardown_cb) -{ - details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb); -} - -inline void spdlog::set_sync_mode() -{ - details::registry::instance().set_sync_mode(); -} - -inline void spdlog::apply_all(std::function)> fun) -{ - details::registry::instance().apply_all(std::move(fun)); -} - -inline void spdlog::drop_all() -{ - details::registry::instance().drop_all(); -} +// inline void spdlog::drop(const std::string &name) +//{ +// details::registry::instance().drop(name); +//} +// +//// Create multi/single threaded simple file logger +// inline std::shared_ptr spdlog::basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate) +//{ +// return create_and_register(logger_name, filename, truncate); +//} +// +// inline std::shared_ptr spdlog::basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate) +//{ +// return create_and_register(logger_name, filename, truncate); +//} +// +//// Create multi/single threaded rotating file logger +// inline std::shared_ptr spdlog::rotating_logger_mt( +// const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files) +//{ +// return create_and_register(logger_name, filename, max_file_size, max_files); +//} +// +// inline std::shared_ptr spdlog::rotating_logger_st( +// const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files) +//{ +// return create_and_register(logger_name, filename, max_file_size, max_files); +//} +// +//// Create file logger which creates new file at midnight): +// inline std::shared_ptr spdlog::daily_logger_mt( +// const std::string &logger_name, const filename_t &filename, int hour, int minute) +//{ +// return create_and_register(logger_name, filename, hour, minute); +//} +// +// inline std::shared_ptr spdlog::daily_logger_st( +// const std::string &logger_name, const filename_t &filename, int hour, int minute) +//{ +// return create_and_register(logger_name, filename, hour, minute); +//} +// +//// +//// stdout/stderr loggers +//// +// inline std::shared_ptr spdlog::stdout_logger_mt(const std::string &logger_name) +//{ +// +// auto new_logger = std::make_shared(logger_name, sinks::stdout_sink_mt::instance()); +// details::registry::instance().register_and_init(new_logger); +// return new_logger; +// //return details::registry::instance().create(logger_name, sinks::stdout_sink_mt::instance()); +//} +// +// inline std::shared_ptr spdlog::stdout_logger_st(const std::string &logger_name) +//{ +// auto new_logger = std::make_shared(logger_name, sinks::stdout_sink_st::instance()); +// details::registry::instance().register_and_init(new_logger); +// return new_logger; +//} +// +// inline std::shared_ptr spdlog::stderr_logger_mt(const std::string &logger_name) +//{ +// auto new_logger = std::make_shared(logger_name, sinks::stderr_sink_mt::instance()); +// details::registry::instance().register_and_init(new_logger); +// return new_logger; +//} +// +// inline std::shared_ptr spdlog::stderr_logger_st(const std::string &logger_name) +//{ +// auto new_logger = std::make_shared(logger_name, sinks::stderr_sink_st::instance()); +// details::registry::instance().register_and_init(new_logger); +// return new_logger; +//} +// +//// +//// stdout/stderr color loggers +//// +//#if defined _WIN32 && !defined(__cplusplus_winrt) +// +// inline std::shared_ptr spdlog::stdout_color_mt(const std::string &logger_name) +//{ +// return create_and_register(logger_name); +//} +// +// inline std::shared_ptr spdlog::stdout_color_st(const std::string &logger_name) +//{ +// return create_and_register(logger_name); +//} +// +// inline std::shared_ptr spdlog::stderr_color_mt(const std::string &logger_name) +//{ +// return create_and_register(logger_name); +//} +// +// inline std::shared_ptr spdlog::stderr_color_st(const std::string &logger_name) +//{ +// +// return create_and_register(logger_name); +//} +// +//#else // ansi terminal colors +// +// +// inline std::shared_ptr spdlog::stdout_color_mt(const std::string &logger_name) +//{ +// return create_and_register(logger_name); +//} +// +// inline std::shared_ptr spdlog::stdout_color_st(const std::string &logger_name) +//{ +// return create_and_register(logger_name); +//} +// +// inline std::shared_ptr spdlog::stderr_color_mt(const std::string &logger_name) +//{ +// return create_and_register(logger_name); +//} +// +// inline std::shared_ptr spdlog::stderr_color_st(const std::string &logger_name) +//{ +// return create_and_register(logger_name); +//} +//#endif +// +//#ifdef SPDLOG_ENABLE_SYSLOG +//// Create syslog logger +// inline std::shared_ptr spdlog::syslog_logger( +// const std::string &logger_name, const std::string &syslog_ident, int syslog_option, int syslog_facility) { +// return create_and_register(logger_name, syslog_ident, syslog_option, syslog_facility); +//} +//#endif +// +//#ifdef __ANDROID__ +// inline std::shared_ptr spdlog::android_logger(const std::string &logger_name, const std::string &tag) +//{ +// return create_and_register(logger_name, tag); +//} +//#endif +// +// +// +// +// inline void spdlog::flush_on(level::level_enum log_level) +//{ +// details::registry::instance().flush_on(log_level); +//} +// +// inline void spdlog::set_error_handler(log_err_handler handler) +//{ +// details::registry::instance().set_error_handler(std::move(handler)); +//} +// +// inline void spdlog::apply_all(std::function)> fun) +//{ +// details::registry::instance().apply_all(std::move(fun)); +//} +// +// inline void spdlog::drop_all() +//{ +// details::registry::instance().drop_all(); +//} diff --git a/include/spdlog/fmt/bundled/format.h b/include/spdlog/fmt/bundled/format.h index b4295cd7..d39751f3 100644 --- a/include/spdlog/fmt/bundled/format.h +++ b/include/spdlog/fmt/bundled/format.h @@ -785,7 +785,7 @@ inline typename MakeUnsigned::Type to_unsigned(Int value) // to avoid dynamic memory allocation. enum { - INLINE_BUFFER_SIZE = 500 + INLINE_BUFFER_SIZE = 500 // TODO reduce to 250 }; #if FMT_SECURE_SCL diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index aa4a2c5d..9c53e90e 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -1,5 +1,5 @@ // -// Copyright(c) 2015 Gabi Melman. +// Copyright(c) 2015-2108 Gabi Melman. // Distributed under the MIT License (http://opensource.org/licenses/MIT) // @@ -113,27 +113,23 @@ public: void set_pattern(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local); void set_formatter(formatter_ptr msg_formatter); - // automatically call flush() if message level >= log_level + void flush(); void flush_on(level::level_enum log_level); - virtual void flush(); - const std::vector &sinks() const; // error handler - virtual void set_error_handler(log_err_handler err_handler); - virtual log_err_handler error_handler(); + void set_error_handler(log_err_handler err_handler); + log_err_handler error_handler(); protected: virtual void _sink_it(details::log_msg &msg); - virtual void _set_pattern(const std::string &pattern, pattern_time_type pattern_time); - virtual void _set_formatter(formatter_ptr msg_formatter); + virtual void _flush(); + + bool _should_flush(const details::log_msg &msg); // default error handler: print the error to stderr with the max rate of 1 message/minute - virtual void _default_err_handler(const std::string &msg); - - // return true if the given message level should trigger a flush - bool _should_flush_on(const details::log_msg &msg); + void _default_err_handler(const std::string &msg); // increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)) void _incr_msg_counter(details::log_msg &msg); diff --git a/include/spdlog/sinks/ansicolor_sink.h b/include/spdlog/sinks/ansicolor_sink.h index e74389c9..aaa09205 100644 --- a/include/spdlog/sinks/ansicolor_sink.h +++ b/include/spdlog/sinks/ansicolor_sink.h @@ -94,7 +94,7 @@ protected: // after color range _print_range(msg, msg.color_range_end, msg.formatted.size()); } - else + else // no color { _print_range(msg, 0, msg.formatted.size()); } diff --git a/include/spdlog/sinks/stdout_sinks.h b/include/spdlog/sinks/stdout_sinks.h index b15d0803..f0911f4a 100644 --- a/include/spdlog/sinks/stdout_sinks.h +++ b/include/spdlog/sinks/stdout_sinks.h @@ -23,12 +23,6 @@ class stdout_sink SPDLOG_FINAL : public base_sink public: explicit stdout_sink() = default; - static std::shared_ptr instance() - { - static std::shared_ptr instance = std::make_shared(); - return instance; - } - protected: void _sink_it(const details::log_msg &msg) override { @@ -53,12 +47,6 @@ class stderr_sink SPDLOG_FINAL : public base_sink public: explicit stderr_sink() = default; - static std::shared_ptr instance() - { - static std::shared_ptr instance = std::make_shared(); - return instance; - } - protected: void _sink_it(const details::log_msg &msg) override { diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index 21f5951b..a7544926 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -1,5 +1,5 @@ // -// Copyright(c) 2015 Gabi Melman. +// Copyright(c) 2015-2018 Gabi Melman. // Distributed under the MIT License (http://opensource.org/licenses/MIT) // // spdlog main header file. @@ -7,9 +7,23 @@ #pragma once +#include "details/registry.h" +#include "sinks/file_sinks.h" +#include "sinks/stdout_sinks.h" + #include "common.h" #include "logger.h" +#if defined _WIN32 +#include "sinks/wincolor_sink.h" +#else +#include "sinks/ansicolor_sink.h" +#endif + +#ifdef __ANDROID__ +#include "sinks/android_sink.h" +#endif + #include #include #include @@ -17,157 +31,213 @@ namespace spdlog { +// Default logger factory- creates synchronous loggers +struct default_factory +{ + template + + static std::shared_ptr create(const std::string &logger_name, SinkArgs &&... args) + { + auto sink = std::make_shared(std::forward(args)...); + auto new_logger = std::make_shared(logger_name, std::move(sink)); + details::registry::instance().register_and_init(new_logger); + return new_logger; + } +}; + +// Create and register a logger with a templated sink type +// The logger's level, formatter and flush level will be set according the global settings. +// Example: +// spdlog::create("logger_name", "dailylog_filename", 11, 59); +template +inline std::shared_ptr create(const std::string &logger_name, SinkArgs &&... sink_args) +{ + return default_factory::create(logger_name, std::forward(sink_args)...); +} + // // Return an existing logger or nullptr if a logger with such name doesn't exist. // example: spdlog::get("my_logger")->info("hello {}", "world"); // -std::shared_ptr get(const std::string &name); +inline std::shared_ptr get(const std::string &name) +{ + return details::registry::instance().get(name); +} // // Set global formatting // example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v"); // -void set_pattern(const std::string &format_string); -void set_formatter(formatter_ptr f); +inline void set_pattern(const std::string &format_string) +{ + details::registry::instance().set_pattern(format_string); +} + +inline void set_formatter(formatter_ptr f) +{ + details::registry::instance().set_formatter(std::move(f)); +} // // Set global logging level // -void set_level(level::level_enum log_level); +inline void set_level(level::level_enum log_level) +{ + details::registry::instance().set_level(log_level); +} // // Set global flush level // -void flush_on(level::level_enum log_level); +inline void flush_on(level::level_enum log_level) +{ + details::registry::instance().flush_on(log_level); +} // // Set global error handler // -void set_error_handler(log_err_handler handler); +inline void set_error_handler(log_err_handler handler) +{ + details::registry::instance().set_error_handler(std::move(handler)); +} -// -// Turn on async mode (off by default) and set the queue size for each async_logger. -// effective only for loggers created after this call. -// queue_size: size of queue (must be power of 2): -// Each logger will pre-allocate a dedicated queue with queue_size entries upon construction. -// -// async_overflow_policy (optional, block_retry by default): -// async_overflow_policy::block_retry - if queue is full, block until queue has room for the new log entry. -// async_overflow_policy::discard_log_msg - never block and discard any new messages when queue overflows. -// -// worker_warmup_cb (optional): -// callback function that will be called in worker thread upon start (can be used to init stuff like thread affinity) -// -// worker_teardown_cb (optional): -// callback function that will be called in worker thread upon exit -// -void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function &worker_warmup_cb = nullptr, - const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function &worker_teardown_cb = nullptr); +// Register the given logger with the given name +inline void register_logger(std::shared_ptr logger) +{ + details::registry::instance().register_logger(std::move(logger)); +} -// Turn off async mode -void set_sync_mode(); +// Apply a user defined function on all registered loggers +// Example: +// spdlog::apply_all([&](std::shared_ptr l) {l->flush();}); +inline void apply_all(std::function)> fun) +{ + details::registry::instance().apply_all(std::move(fun)); +} + +// Drop the reference to the given logger +inline void drop(const std::string &name) +{ + details::registry::instance().drop(name); +} + +// Drop all references from the registry +inline void drop_all() +{ + details::registry::instance().drop_all(); +} // // Create and register multi/single threaded basic file logger. // Basic logger simply writes to given file without any limitations or rotations. // -std::shared_ptr basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false); -std::shared_ptr basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false); +template +inline std::shared_ptr basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false) +{ + return Factory::template create(logger_name, filename, truncate); +} + +template +inline std::shared_ptr basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false) +{ + return Factory::template create(logger_name, filename, truncate); +} // // Create and register multi/single threaded rotating file logger // -std::shared_ptr rotating_logger_mt( - const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files); +template +inline std::shared_ptr rotating_logger_mt( + const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files) +{ + return Factory::template create(logger_name, filename, max_file_size, max_files); +} -std::shared_ptr rotating_logger_st( - const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files); +template +inline std::shared_ptr rotating_logger_st( + const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files) +{ + return Factory::template create(logger_name, filename, max_file_size, max_files); +} // // Create file logger which creates new file on the given time (default in midnight): // -std::shared_ptr daily_logger_mt(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0); -std::shared_ptr daily_logger_st(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0); +template +inline std::shared_ptr daily_logger_mt(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0) +{ + return Factory::template create(logger_name, filename, hour, minute); +} -// -// Create and register stdout/stderr loggers -// -std::shared_ptr stdout_logger_mt(const std::string &logger_name); -std::shared_ptr stdout_logger_st(const std::string &logger_name); -std::shared_ptr stderr_logger_mt(const std::string &logger_name); -std::shared_ptr stderr_logger_st(const std::string &logger_name); -// -// Create and register colored stdout/stderr loggers -// -std::shared_ptr stdout_color_mt(const std::string &logger_name); -std::shared_ptr stdout_color_st(const std::string &logger_name); -std::shared_ptr stderr_color_mt(const std::string &logger_name); -std::shared_ptr stderr_color_st(const std::string &logger_name); +template +inline std::shared_ptr daily_logger_st(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0) +{ + return Factory::template create(logger_name, filename, hour, minute); +} +/////////////////////////////////////////////////////////////////////////////// +// stdout and stderr loggers // -// Create and register a syslog logger +// multi threaded and colored: +// spdlog::console("name") +// spdlog::console("name") // +// single threaded and colored: +// spdlog::console("name") +// spdlog::console("name") +// +// multi threaded, no color: +// spdlog::console("name") +// spdlog::console("name") +// +// single threaded, no color: +// spdlog::console("name") +// spdlog::console("name") +/////////////////////////////////////////////////////////////////////////////// + +#if defined _WIN32 // window color console +using stdout_color_mt = sinks::wincolor_stdout_sink_mt; +using stdout_color_st = sinks::wincolor_stdout_sink_st; +using stderr_color_mt = sinks::wincolor_stderr_sink_mt; +using stderr_color_st = sinks::wincolor_stderr_sink_st; +#else // ansi color console +using stdout_color_mt = sinks::ansicolor_stdout_sink_mt; +using stdout_color_st = sinks::ansicolor_stdout_sink_st; +using stderr_color_mt = sinks::ansicolor_stderr_sink_mt; +using stderr_color_st = sinks::ansicolor_stderr_sink_st; +#endif +// no color console +using stdout_mt = sinks::stdout_sink_mt; +using stdout_st = sinks::stdout_sink_st; +using stderr_mt = sinks::stderr_sink_mt; +using stderr_st = sinks::stderr_sink_st; + +template +inline std::shared_ptr console(const std::string &logger_name) +{ + return Factory::template create(logger_name); +} + #ifdef SPDLOG_ENABLE_SYSLOG -std::shared_ptr syslog_logger( - const std::string &logger_name, const std::string &ident = "", int syslog_option = 0, int syslog_facilty = (1 << 3)); +// Create and register a syslog logger +template +inline std::shared_ptr syslog_logger( + const std::string &logger_name, const std::string &ident = "", int syslog_option = 0, int syslog_facilty = (1 << 3)) +{ + return return Factory::template create(logger_name, syslog_ident, syslog_option, syslog_facility); +} #endif #if defined(__ANDROID__) -std::shared_ptr android_logger(const std::string &logger_name, const std::string &tag = "spdlog"); +// Create and register android syslog logger +template +inline std::shared_ptr android_logger(const std::string &logger_name, const std::string &tag = "spdlog") +{ + return return Factory::template create(logger_name, tag); +} #endif -// Create and register a logger with a single sink -std::shared_ptr create(const std::string &logger_name, const sink_ptr &sink); - -// Create and register a logger with multiple sinks -std::shared_ptr create(const std::string &logger_name, sinks_init_list sinks); - -template -std::shared_ptr create(const std::string &logger_name, const It &sinks_begin, const It &sinks_end); - -// Create and register a logger with templated sink type -// Example: -// spdlog::create("mylog", "dailylog_filename"); -template -std::shared_ptr create(const std::string &logger_name, Args... args); - -// Create and register an async logger with a single sink -std::shared_ptr create_async(const std::string &logger_name, const sink_ptr &sink, size_t queue_size, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function &worker_warmup_cb = nullptr, - const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function &worker_teardown_cb = nullptr); - -// Create and register an async logger with multiple sinks -std::shared_ptr create_async(const std::string &logger_name, sinks_init_list sinks, size_t queue_size, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function &worker_warmup_cb = nullptr, - const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function &worker_teardown_cb = nullptr); - -template -std::shared_ptr create_async(const std::string &logger_name, const It &sinks_begin, const It &sinks_end, size_t queue_size, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function &worker_warmup_cb = nullptr, - const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function &worker_teardown_cb = nullptr); - -// Register the given logger with the given name -void register_logger(std::shared_ptr logger); - -// Apply a user defined function on all registered loggers -// Example: -// spdlog::apply_all([&](std::shared_ptr l) {l->flush();}); -void apply_all(std::function)> fun); - -// Drop the reference to the given logger -void drop(const std::string &name); - -// Drop all references from the registry -void drop_all(); - /////////////////////////////////////////////////////////////////////////////// // // Trace & Debug can be switched on/off at compile time for zero cost debug statements. @@ -200,5 +270,3 @@ void drop_all(); #endif } // namespace spdlog - -#include "details/spdlog_impl.h" diff --git a/tests/errors.cpp b/tests/errors.cpp index 1e1826fb..0e0375db 100644 --- a/tests/errors.cpp +++ b/tests/errors.cpp @@ -67,10 +67,11 @@ TEST_CASE("async_error_handler", "[errors]]") { prepare_logdir(); std::string err_msg("log failed with some msg"); - spdlog::set_async_mode(128); + std::string filename = "logs/simple_async_log.txt"; { - auto logger = spdlog::create("logger", filename, true); + spdlog::init_thread_pool(128, 1); + auto logger = spdlog::create_as("logger", filename, true); logger->set_error_handler([=](const std::string &msg) { std::ofstream ofs("logs/custom_err.txt"); if (!ofs) @@ -85,8 +86,8 @@ TEST_CASE("async_error_handler", "[errors]]") #endif logger->info("Good message #2"); spdlog::drop("logger"); // force logger to drain the queue and shutdown - spdlog::set_sync_mode(); } + spdlog::init_thread_pool(128, 1); REQUIRE(count_lines(filename) == 2); REQUIRE(file_contents("logs/custom_err.txt") == err_msg); } @@ -96,9 +97,9 @@ TEST_CASE("async_error_handler2", "[errors]]") { prepare_logdir(); std::string err_msg("This is async handler error message"); - spdlog::set_async_mode(128); { - auto logger = spdlog::create("failed_logger"); + spdlog::init_thread_pool(128, 1); + auto logger = spdlog::create_as("failed_logger"); logger->set_error_handler([=](const std::string &msg) { std::ofstream ofs("logs/custom_err2.txt"); if (!ofs) @@ -107,8 +108,8 @@ TEST_CASE("async_error_handler2", "[errors]]") }); logger->info("Hello failure"); spdlog::drop("failed_logger"); // force logger to drain the queue and shutdown - spdlog::set_sync_mode(); } + spdlog::init_thread_pool(128, 1); REQUIRE(file_contents("logs/custom_err2.txt") == err_msg); } diff --git a/tests/includes.h b/tests/includes.h index ccc62d16..d3d7d9a8 100644 --- a/tests/includes.h +++ b/tests/includes.h @@ -12,6 +12,7 @@ #define SPDLOG_TRACE_ON #define SPDLOG_DEBUG_ON +#include "../include/spdlog/async.h" #include "../include/spdlog/sinks/null_sink.h" #include "../include/spdlog/sinks/ostream_sink.h" #include "../include/spdlog/spdlog.h"