mirror of
https://github.com/gabime/spdlog.git
synced 2024-11-15 16:35:45 +08:00
thread_pool and refactoring async
This commit is contained in:
parent
5e08950ed2
commit
6f4cd8d397
@ -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");
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
Please put here your contribs. Popular contribs will be moved to main tree after stablization
|
1
include/spdlog/contrib/sinks/.gitignore
vendored
1
include/spdlog/contrib/sinks/.gitignore
vendored
@ -1 +0,0 @@
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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};
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
//}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user