thread_pool and refactoring async

This commit is contained in:
gabime 2018-04-14 03:34:57 +03:00
parent 5e08950ed2
commit 6f4cd8d397
18 changed files with 575 additions and 657 deletions

View File

@ -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 <atomic>
#include <cstdlib> // 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<spdlog::create_async>("as", "logs/daily_async.log");
bench_mt(howmany, as, threads);
spdlog::drop("as");
}

View File

@ -10,6 +10,7 @@
#define SPDLOG_TRACE_ON
#define SPDLOG_DEBUG_ON
#include "spdlog/async.h"
#include "spdlog/spdlog.h"
#include <iostream>
@ -27,9 +28,10 @@ int main(int, char *[])
try
{
// Console logger with color
auto console = spd::stdout_color_mt("console");
auto console = spdlog::console<spd::stdout_color_mt>("console");
auto console2 = spdlog::console<spd::stdout_color_mt>("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<spdlog::create_async>("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)

View File

@ -20,52 +20,39 @@
#include <chrono>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
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<async_logger>, public logger
{
friend class details::thread_pool;
public:
template<class It>
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<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
async_logger(const std::string &logger_name, const It &begin, const It &end, std::weak_ptr<details::thread_pool> 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<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
async_logger(const std::string &logger_name, sinks_init_list sinks, std::weak_ptr<details::thread_pool> 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<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &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<details::thread_pool> 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<details::async_log_helper> _async_log_helper;
std::weak_ptr<details::thread_pool> _thread_pool;
async_overflow_policy _overflow_policy;
};
} // namespace spdlog

View File

@ -1 +0,0 @@
Please put here your contribs. Popular contribs will be moved to main tree after stablization

View File

@ -1 +0,0 @@

View File

@ -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;

View File

@ -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 <chrono>
#include <functional>
#include <memory>
#include <string>
template<class It>
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<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
inline spdlog::async_logger::async_logger(const std::string &logger_name, const It &begin, const It &end,
std::weak_ptr<details::thread_pool> 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<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &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<details::thread_pool> 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<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &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<details::thread_pool> 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_formatter>(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);
}
}

View File

@ -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};
};

View File

@ -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_formatter>(pattern, pattern_time);
}
template<typename... Args>
@ -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<spdlog::level::level_enum>(_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_formatter>(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)

View File

@ -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 <chrono>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
namespace spdlog {
namespace details {
class thread_pool;
template<class Mutex>
class registry_t
{
public:
using MutexT = Mutex;
registry_t<Mutex>(const registry_t<Mutex> &) = delete;
registry_t<Mutex> &operator=(const registry_t<Mutex> &) = delete;
void register_logger(std::shared_ptr<logger> logger)
void register_logger(std::shared_ptr<logger> new_logger)
{
std::lock_guard<Mutex> 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<logger> new_logger)
{
std::lock_guard<Mutex> 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<logger> get(const std::string &logger_name)
@ -46,116 +70,19 @@ public:
return found == _loggers.end() ? nullptr : found->second;
}
template<class It>
std::shared_ptr<logger> create(const std::string &logger_name, const It &sinks_begin, const It &sinks_end)
void set_thread_pool(std::shared_ptr<thread_pool> tp)
{
std::lock_guard<Mutex> lock(_mutex);
throw_if_exists(logger_name);
std::shared_ptr<logger> new_logger;
if (_async_mode)
{
new_logger = std::make_shared<async_logger>(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>(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<class It>
std::shared_ptr<async_logger> create_async(const std::string &logger_name, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb, const It &sinks_begin,
const It &sinks_end)
std::shared_ptr<thread_pool> get_thread_pool()
{
std::lock_guard<Mutex> lock(_mutex);
throw_if_exists(logger_name);
auto new_logger = std::make_shared<async_logger>(
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<void(std::shared_ptr<logger>)> fun)
{
std::lock_guard<Mutex> lock(_mutex);
for (auto &l : _loggers)
{
fun(l.second);
}
}
void drop(const std::string &logger_name)
{
std::lock_guard<Mutex> lock(_mutex);
_loggers.erase(logger_name);
}
void drop_all()
{
std::lock_guard<Mutex> lock(_mutex);
_loggers.clear();
}
std::shared_ptr<logger> create(const std::string &logger_name, sinks_init_list sinks)
{
return create(logger_name, sinks.begin(), sinks.end());
}
std::shared_ptr<logger> create(const std::string &logger_name, sink_ptr sink)
{
return create(logger_name, {sink});
}
std::shared_ptr<async_logger> create_async(const std::string &logger_name, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &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<async_logger> create_async(const std::string &logger_name, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &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<Mutex> 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<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
void apply_all(std::function<void(std::shared_ptr<logger>)> fun)
{
std::lock_guard<Mutex> 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<Mutex> lock(_mutex);
_async_mode = false;
_loggers.erase(logger_name);
}
void drop_all()
{
std::lock_guard<Mutex> lock(_mutex);
_loggers.clear();
}
Mutex &tp_mutex()
{
return _tp_mutex;
}
static registry_t<Mutex> &instance()
@ -240,22 +175,20 @@ private:
}
Mutex _mutex;
Mutex _tp_mutex;
std::unordered_map<std::string, std::shared_ptr<logger>> _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<void()> _worker_warmup_cb;
std::chrono::milliseconds _flush_interval_ms{std::chrono::milliseconds::zero()};
std::function<void()> _worker_teardown_cb;
std::shared_ptr<thread_pool> _tp;
};
#ifdef SPDLOG_NO_REGISTRY_MUTEX
#include "../details/null_mutex.h"
using registry = registry_t<spdlog::details::null_mutex>;
#else
#include <mutex>
using registry = registry_t<std::mutex>;
#endif

View File

@ -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 <chrono>
#include <functional>
#include <memory>
#include <string>
inline void spdlog::register_logger(std::shared_ptr<logger> logger)
{
return details::registry::instance().register_logger(std::move(logger));
}
inline std::shared_ptr<spdlog::logger> 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::logger> spdlog::basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate)
{
return create<spdlog::sinks::simple_file_sink_mt>(logger_name, filename, truncate);
}
inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate)
{
return create<spdlog::sinks::simple_file_sink_st>(logger_name, filename, truncate);
}
// Create multi/single threaded rotating file logger
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files)
{
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files);
}
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files)
{
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files);
}
// Create file logger which creates new file at midnight):
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(
const std::string &logger_name, const filename_t &filename, int hour, int minute)
{
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, hour, minute);
}
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(
const std::string &logger_name, const filename_t &filename, int hour, int minute)
{
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, hour, minute);
}
//#ifdef __ANDROID__
//#include "../sinks/android_sink.h"
//#endif
//
// stdout/stderr loggers
//#include <chrono>
//#include <functional>
//#include <memory>
//#include <string>
//
inline std::shared_ptr<spdlog::logger> 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::logger> 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::logger> 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::logger> 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> 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::logger> spdlog::stdout_color_mt(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_st>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_mt>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_st>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
#else // ansi terminal colors
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_st>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_stderr_sink_mt>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string &logger_name)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_stderr_sink_st>();
return spdlog::details::registry::instance().create(logger_name, sink);
}
#endif
#ifdef SPDLOG_ENABLE_SYSLOG
// Create syslog logger
inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(
const std::string &logger_name, const std::string &syslog_ident, int syslog_option, int syslog_facility)
{
return create<spdlog::sinks::syslog_sink>(logger_name, syslog_ident, syslog_option, syslog_facility);
}
#endif
#ifdef __ANDROID__
inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string &logger_name, const std::string &tag)
{
return create<spdlog::sinks::android_sink>(logger_name, tag);
}
#endif
// Create and register a logger a single sink
inline std::shared_ptr<spdlog::logger> 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::logger> spdlog::create(const std::string &logger_name, spdlog::sinks_init_list sinks)
{
return details::registry::instance().create(logger_name, sinks);
}
template<typename Sink, typename... Args>
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string &logger_name, Args... args)
{
sink_ptr sink = std::make_shared<Sink>(args...);
return details::registry::instance().create(logger_name, {sink});
}
template<class It>
inline std::shared_ptr<spdlog::logger> 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::logger> 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<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &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::logger> 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<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &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<class It>
inline std::shared_ptr<spdlog::logger> 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<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &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<void()> &worker_warmup_cb, const std::chrono::milliseconds &flush_interval_ms,
const std::function<void()> &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<void(std::shared_ptr<logger>)> 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::logger> spdlog::basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate)
//{
// return create_and_register<sinks::simple_file_sink_mt>(logger_name, filename, truncate);
//}
//
// inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate)
//{
// return create_and_register<sinks::simple_file_sink_st>(logger_name, filename, truncate);
//}
//
//// Create multi/single threaded rotating file logger
// inline std::shared_ptr<spdlog::logger> 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<sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files);
//}
//
// inline std::shared_ptr<spdlog::logger> 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<sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files);
//}
//
//// Create file logger which creates new file at midnight):
// inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(
// const std::string &logger_name, const filename_t &filename, int hour, int minute)
//{
// return create_and_register<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute);
//}
//
// inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(
// const std::string &logger_name, const filename_t &filename, int hour, int minute)
//{
// return create_and_register<sinks::daily_file_sink_st>(logger_name, filename, hour, minute);
//}
//
////
//// stdout/stderr loggers
////
// inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string &logger_name)
//{
//
// auto new_logger = std::make_shared<logger>(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::logger> spdlog::stdout_logger_st(const std::string &logger_name)
//{
// auto new_logger = std::make_shared<logger>(logger_name, sinks::stdout_sink_st::instance());
// details::registry::instance().register_and_init(new_logger);
// return new_logger;
//}
//
// inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string &logger_name)
//{
// auto new_logger = std::make_shared<logger>(logger_name, sinks::stderr_sink_mt::instance());
// details::registry::instance().register_and_init(new_logger);
// return new_logger;
//}
//
// inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string &logger_name)
//{
// auto new_logger = std::make_shared<logger>(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::logger> spdlog::stdout_color_mt(const std::string &logger_name)
//{
// return create_and_register<sinks::wincolor_stdout_sink_mt>(logger_name);
//}
//
// inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string &logger_name)
//{
// return create_and_register<sinks::wincolor_stdout_sink_st>(logger_name);
//}
//
// inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string &logger_name)
//{
// return create_and_register<sinks::wincolor_stderr_sink_mt>(logger_name);
//}
//
// inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string &logger_name)
//{
//
// return create_and_register<sinks::wincolor_stderr_sink_st>(logger_name);
//}
//
//#else // ansi terminal colors
//
//
// inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string &logger_name)
//{
// return create_and_register<sinks::ansicolor_stdout_sink_mt>(logger_name);
//}
//
// inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string &logger_name)
//{
// return create_and_register<sinks::ansicolor_stdout_sink_st>(logger_name);
//}
//
// inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string &logger_name)
//{
// return create_and_register<sinks::ansicolor_stderr_sink_mt>(logger_name);
//}
//
// inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string &logger_name)
//{
// return create_and_register<sinks::ansicolor_stderr_sink_st>(logger_name);
//}
//#endif
//
//#ifdef SPDLOG_ENABLE_SYSLOG
//// Create syslog logger
// inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(
// const std::string &logger_name, const std::string &syslog_ident, int syslog_option, int syslog_facility) {
// return create_and_register<sinks::syslog_sink>(logger_name, syslog_ident, syslog_option, syslog_facility);
//}
//#endif
//
//#ifdef __ANDROID__
// inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string &logger_name, const std::string &tag)
//{
// return create_and_register<sinks::android_sink>(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<void(std::shared_ptr<logger>)> fun)
//{
// details::registry::instance().apply_all(std::move(fun));
//}
//
// inline void spdlog::drop_all()
//{
// details::registry::instance().drop_all();
//}

View File

@ -785,7 +785,7 @@ inline typename MakeUnsigned<Int>::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

View File

@ -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<sink_ptr> &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);

View File

@ -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());
}

View File

@ -23,12 +23,6 @@ class stdout_sink SPDLOG_FINAL : public base_sink<Mutex>
public:
explicit stdout_sink() = default;
static std::shared_ptr<MyType> instance()
{
static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
return instance;
}
protected:
void _sink_it(const details::log_msg &msg) override
{
@ -53,12 +47,6 @@ class stderr_sink SPDLOG_FINAL : public base_sink<Mutex>
public:
explicit stderr_sink() = default;
static std::shared_ptr<MyType> instance()
{
static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
return instance;
}
protected:
void _sink_it(const details::log_msg &msg) override
{

View File

@ -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 <chrono>
#include <functional>
#include <memory>
@ -17,157 +31,213 @@
namespace spdlog {
// Default logger factory- creates synchronous loggers
struct default_factory
{
template<typename Sink, typename... SinkArgs>
static std::shared_ptr<spdlog::logger> create(const std::string &logger_name, SinkArgs &&... args)
{
auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);
auto new_logger = std::make_shared<logger>(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<daily_file_sink_st>("logger_name", "dailylog_filename", 11, 59);
template<typename Sink, typename... SinkArgs>
inline std::shared_ptr<spdlog::logger> create(const std::string &logger_name, SinkArgs &&... sink_args)
{
return default_factory::create<Sink>(logger_name, std::forward<SinkArgs>(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<logger> get(const std::string &name);
inline std::shared_ptr<logger> 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<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
// Register the given logger with the given name
inline void register_logger(std::shared_ptr<logger> 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<spdlog::logger> l) {l->flush();});
inline void apply_all(std::function<void(std::shared_ptr<logger>)> 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<logger> basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false);
std::shared_ptr<logger> basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false);
template<typename Factory = default_factory>
inline std::shared_ptr<logger> basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false)
{
return Factory::template create<sinks::simple_file_sink_mt>(logger_name, filename, truncate);
}
template<typename Factory = default_factory>
inline std::shared_ptr<logger> basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false)
{
return Factory::template create<sinks::simple_file_sink_st>(logger_name, filename, truncate);
}
//
// Create and register multi/single threaded rotating file logger
//
std::shared_ptr<logger> rotating_logger_mt(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files);
template<typename Factory = default_factory>
inline std::shared_ptr<logger> 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<sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files);
}
std::shared_ptr<logger> rotating_logger_st(
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files);
template<typename Factory = default_factory>
inline std::shared_ptr<logger> 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<sinks::rotating_file_sink_st>(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<logger> daily_logger_mt(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0);
std::shared_ptr<logger> daily_logger_st(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0);
template<typename Factory = default_factory>
inline std::shared_ptr<logger> daily_logger_mt(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0)
{
return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute);
}
//
// Create and register stdout/stderr loggers
//
std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name);
std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name);
std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name);
std::shared_ptr<logger> stderr_logger_st(const std::string &logger_name);
//
// Create and register colored stdout/stderr loggers
//
std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name);
std::shared_ptr<logger> stdout_color_st(const std::string &logger_name);
std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name);
std::shared_ptr<logger> stderr_color_st(const std::string &logger_name);
template<typename Factory = default_factory>
inline std::shared_ptr<logger> daily_logger_st(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0)
{
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute);
}
///////////////////////////////////////////////////////////////////////////////
// stdout and stderr loggers
//
// Create and register a syslog logger
// multi threaded and colored:
// spdlog::console<stdout_color_mt>("name")
// spdlog::console<stderr_color_mt>("name")
//
// single threaded and colored:
// spdlog::console<stdout_color_st>("name")
// spdlog::console<stderr_color_st>("name")
//
// multi threaded, no color:
// spdlog::console<stdout_mt>("name")
// spdlog::console<stderr_mt>("name")
//
// single threaded, no color:
// spdlog::console<stdout_st>("name")
// spdlog::console<stderr_st>("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<typename Sink, typename Factory = default_factory>
inline std::shared_ptr<logger> console(const std::string &logger_name)
{
return Factory::template create<Sink>(logger_name);
}
#ifdef SPDLOG_ENABLE_SYSLOG
std::shared_ptr<logger> 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<typename Factory = default_factory>
inline std::shared_ptr<logger> 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<sinks::syslog_sink>(logger_name, syslog_ident, syslog_option, syslog_facility);
}
#endif
#if defined(__ANDROID__)
std::shared_ptr<logger> android_logger(const std::string &logger_name, const std::string &tag = "spdlog");
// Create and register android syslog logger
template<typename Factory = default_factory>
inline std::shared_ptr<logger> android_logger(const std::string &logger_name, const std::string &tag = "spdlog")
{
return return Factory::template create<sinks::android_sink>(logger_name, tag);
}
#endif
// Create and register a logger with a single sink
std::shared_ptr<logger> create(const std::string &logger_name, const sink_ptr &sink);
// Create and register a logger with multiple sinks
std::shared_ptr<logger> create(const std::string &logger_name, sinks_init_list sinks);
template<class It>
std::shared_ptr<logger> 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<daily_file_sink_st>("mylog", "dailylog_filename");
template<typename Sink, typename... Args>
std::shared_ptr<spdlog::logger> create(const std::string &logger_name, Args... args);
// Create and register an async logger with a single sink
std::shared_ptr<logger> 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<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
// Create and register an async logger with multiple sinks
std::shared_ptr<logger> 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<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
template<class It>
std::shared_ptr<logger> 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<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()> &worker_teardown_cb = nullptr);
// Register the given logger with the given name
void register_logger(std::shared_ptr<logger> logger);
// Apply a user defined function on all registered loggers
// Example:
// spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) {l->flush();});
void apply_all(std::function<void(std::shared_ptr<logger>)> 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"

View File

@ -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<spdlog::sinks::simple_file_sink_mt>("logger", filename, true);
spdlog::init_thread_pool(128, 1);
auto logger = spdlog::create_as<spdlog::sinks::simple_file_sink_mt>("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<failing_sink>("failed_logger");
spdlog::init_thread_pool(128, 1);
auto logger = spdlog::create_as<failing_sink>("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);
}

View File

@ -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"