mirror of
https://github.com/gabime/spdlog.git
synced 2025-04-30 12:23:53 +00:00
thread_pool and refactoring async
This commit is contained in:
parent
5e08950ed2
commit
6f4cd8d397
@ -6,10 +6,10 @@
|
|||||||
//
|
//
|
||||||
// bench.cpp : spdlog benchmarks
|
// bench.cpp : spdlog benchmarks
|
||||||
//
|
//
|
||||||
#include "spdlog/async_logger.h"
|
#include "spdlog/async.h"
|
||||||
#include "spdlog/sinks/file_sinks.h"
|
|
||||||
#include "spdlog/sinks/null_sink.h"
|
#include "spdlog/sinks/null_sink.h"
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstdlib> // EXIT_FAILURE
|
#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 << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations " << endl;
|
||||||
cout << "*******************************************************************************\n";
|
cout << "*******************************************************************************\n";
|
||||||
|
|
||||||
spdlog::set_async_mode(queue_size);
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
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);
|
bench_mt(howmany, as, threads);
|
||||||
spdlog::drop("as");
|
spdlog::drop("as");
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#define SPDLOG_TRACE_ON
|
#define SPDLOG_TRACE_ON
|
||||||
#define SPDLOG_DEBUG_ON
|
#define SPDLOG_DEBUG_ON
|
||||||
|
|
||||||
|
#include "spdlog/async.h"
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -27,9 +28,10 @@ int main(int, char *[])
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Console logger with color
|
// 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->info("Welcome to spdlog!");
|
||||||
console->error("Some error message with arg{}..", 1);
|
console->error("Some error message with arg: {}", 1);
|
||||||
|
|
||||||
// Formatting examples
|
// Formatting examples
|
||||||
console->warn("Easy padding in numbers like {:08d}", 12);
|
console->warn("Easy padding in numbers like {:08d}", 12);
|
||||||
@ -105,13 +107,16 @@ int main(int, char *[])
|
|||||||
|
|
||||||
void async_example()
|
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::basic_logger_mt<spdlog::create_async>("async_file_logger", "logs/async_log.txt");
|
||||||
auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
|
|
||||||
for (int i = 0; i < 100; ++i)
|
for (int i = 0; i < 100; ++i)
|
||||||
{
|
{
|
||||||
async_file->info("Async message #{}", 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)
|
// syslog example (linux/osx/freebsd)
|
||||||
|
@ -20,52 +20,39 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace spdlog {
|
namespace spdlog {
|
||||||
|
|
||||||
namespace details {
|
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:
|
public:
|
||||||
template<class It>
|
template<class It>
|
||||||
async_logger(const std::string &logger_name, const It &begin, const It &end, size_t queue_size,
|
async_logger(const std::string &logger_name, const It &begin, const It &end, std::weak_ptr<details::thread_pool> tp,
|
||||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
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, size_t queue_size,
|
async_logger(const std::string &logger_name, sinks_init_list sinks, std::weak_ptr<details::thread_pool> tp,
|
||||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
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, sink_ptr single_sink, size_t queue_size,
|
async_logger(const std::string &logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp,
|
||||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
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;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _sink_it(details::log_msg &msg) override;
|
void _sink_it(details::log_msg &msg) override;
|
||||||
void _set_formatter(spdlog::formatter_ptr msg_formatter) override;
|
void _flush() override;
|
||||||
void _set_pattern(const std::string &pattern, pattern_time_type pattern_time) override;
|
|
||||||
|
void _backend_log(details::log_msg &incoming_log_msg);
|
||||||
|
void _backend_flush();
|
||||||
|
|
||||||
private:
|
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
|
} // 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)
|
msg_id(other.msg_id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
dsdfsfs async_msg &operator=(async_msg &&other) SPDLOG_NOEXCEPT
|
||||||
async_msg &operator=(async_msg &&other) SPDLOG_NOEXCEPT
|
|
||||||
{
|
{
|
||||||
logger_name = std::move(other.logger_name);
|
logger_name = std::move(other.logger_name);
|
||||||
level = other.level;
|
level = other.level;
|
||||||
|
@ -5,71 +5,37 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Async Logger implementation
|
// async logger implementation
|
||||||
// Use an async_sink (queue per logger) to perform the logging in a worker thread
|
// uses a thread pool to perform the actual logging
|
||||||
|
|
||||||
#include "../async_logger.h"
|
#include "../details/thread_pool.h"
|
||||||
#include "../details/async_log_helper.h"
|
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
template<class It>
|
template<class It>
|
||||||
inline spdlog::async_logger::async_logger(const std::string &logger_name, const It &begin, const It &end, size_t queue_size,
|
inline spdlog::async_logger::async_logger(const std::string &logger_name, const It &begin, const It &end,
|
||||||
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
|
std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)
|
||||||
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
|
|
||||||
: logger(logger_name, begin, end)
|
: logger(logger_name, begin, end)
|
||||||
, _async_log_helper(new details::async_log_helper(
|
, _thread_pool(tp)
|
||||||
_formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb))
|
, _overflow_policy(overflow_policy)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::async_logger::async_logger(const std::string &logger_name, sinks_init_list sinks_list, size_t queue_size,
|
inline spdlog::async_logger::async_logger(const std::string &logger_name, sinks_init_list sinks_list,
|
||||||
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
|
std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)
|
||||||
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
|
: async_logger(logger_name, sinks_list.begin(), sinks_list.end(), tp, overflow_policy)
|
||||||
: 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, sink_ptr single_sink, size_t queue_size,
|
inline spdlog::async_logger::async_logger(
|
||||||
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
|
const std::string &logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)
|
||||||
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
|
: async_logger(logger_name, {single_sink}, tp, overflow_policy)
|
||||||
: async_logger(
|
|
||||||
logger_name, {std::move(single_sink)}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::async_logger::flush()
|
// send the log message to the thread pool
|
||||||
{
|
|
||||||
_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void spdlog::async_logger::_sink_it(details::log_msg &msg)
|
inline void spdlog::async_logger::_sink_it(details::log_msg &msg)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -77,10 +43,13 @@ inline void spdlog::async_logger::_sink_it(details::log_msg &msg)
|
|||||||
#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
|
#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
|
||||||
_incr_msg_counter(msg);
|
_incr_msg_counter(msg);
|
||||||
#endif
|
#endif
|
||||||
_async_log_helper->log(msg);
|
if (auto pool_ptr = _thread_pool.lock())
|
||||||
if (_should_flush_on(msg))
|
|
||||||
{
|
{
|
||||||
_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)
|
catch (const std::exception &ex)
|
||||||
@ -89,7 +58,65 @@ inline void spdlog::async_logger::_sink_it(details::log_msg &msg)
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
_err_handler("Unknown exception in logger " + _name);
|
_err_handler("Unknown exception in async logger " + _name);
|
||||||
throw;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(const log_msg &other) = delete;
|
||||||
log_msg &operator=(log_msg &&other) = delete;
|
|
||||||
log_msg(log_msg &&other) = delete;
|
log_msg(log_msg &&other) = delete;
|
||||||
|
log_msg &operator=(log_msg &&other) = delete;
|
||||||
|
|
||||||
const std::string *logger_name{nullptr};
|
const std::string *logger_name{nullptr};
|
||||||
level::level_enum level;
|
level::level_enum level;
|
||||||
@ -40,7 +40,7 @@ struct log_msg
|
|||||||
fmt::MemoryWriter raw;
|
fmt::MemoryWriter raw;
|
||||||
fmt::MemoryWriter formatted;
|
fmt::MemoryWriter formatted;
|
||||||
size_t msg_id{0};
|
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_start{0};
|
||||||
size_t color_range_end{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)
|
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)
|
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>
|
template<typename... Args>
|
||||||
@ -282,11 +282,22 @@ inline spdlog::log_err_handler spdlog::logger::error_handler()
|
|||||||
return _err_handler;
|
return _err_handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void spdlog::logger::flush()
|
||||||
|
{
|
||||||
|
_flush();
|
||||||
|
}
|
||||||
|
|
||||||
inline void spdlog::logger::flush_on(level::level_enum log_level)
|
inline void spdlog::logger::flush_on(level::level_enum log_level)
|
||||||
{
|
{
|
||||||
_flush_level.store(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
|
inline spdlog::level::level_enum spdlog::logger::level() const
|
||||||
{
|
{
|
||||||
return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
|
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();
|
flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::logger::_set_pattern(const std::string &pattern, pattern_time_type pattern_time)
|
inline void spdlog::logger::_flush()
|
||||||
{
|
|
||||||
_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()
|
|
||||||
{
|
{
|
||||||
for (auto &sink : _sinks)
|
for (auto &sink : _sinks)
|
||||||
{
|
{
|
||||||
@ -345,19 +346,11 @@ inline void spdlog::logger::_default_err_handler(const std::string &msg)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_last_err_time = now;
|
||||||
auto tm_time = details::os::localtime(now);
|
auto tm_time = details::os::localtime(now);
|
||||||
char date_buf[100];
|
char date_buf[100];
|
||||||
std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
|
std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
|
||||||
details::log_msg err_msg;
|
fmt::print(stderr, "[*** LOG ERROR ***] [{}] [{}] {}\n", date_buf, name(), 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::logger::_incr_msg_counter(details::log_msg &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
|
// If user requests a non existing logger, nullptr will be returned
|
||||||
// This class is thread safe
|
// This class is thread safe
|
||||||
|
|
||||||
#include "../async_logger.h"
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "../details/null_mutex.h"
|
|
||||||
#include "../logger.h"
|
#include "../logger.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace spdlog {
|
namespace spdlog {
|
||||||
namespace details {
|
namespace details {
|
||||||
|
class thread_pool;
|
||||||
|
|
||||||
template<class Mutex>
|
template<class Mutex>
|
||||||
class registry_t
|
class registry_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using MutexT = Mutex;
|
||||||
|
|
||||||
registry_t<Mutex>(const registry_t<Mutex> &) = delete;
|
registry_t<Mutex>(const registry_t<Mutex> &) = delete;
|
||||||
registry_t<Mutex> &operator=(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);
|
std::lock_guard<Mutex> lock(_mutex);
|
||||||
auto logger_name = logger->name();
|
auto logger_name = new_logger->name();
|
||||||
throw_if_exists(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)
|
std::shared_ptr<logger> get(const std::string &logger_name)
|
||||||
@ -46,116 +70,19 @@ public:
|
|||||||
return found == _loggers.end() ? nullptr : found->second;
|
return found == _loggers.end() ? nullptr : found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class It>
|
void set_thread_pool(std::shared_ptr<thread_pool> tp)
|
||||||
std::shared_ptr<logger> create(const std::string &logger_name, const It &sinks_begin, const It &sinks_end)
|
|
||||||
{
|
{
|
||||||
std::lock_guard<Mutex> lock(_mutex);
|
std::lock_guard<Mutex> lock(_mutex);
|
||||||
throw_if_exists(logger_name);
|
_tp = std::move(tp);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class It>
|
std::shared_ptr<thread_pool> get_thread_pool()
|
||||||
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::lock_guard<Mutex> lock(_mutex);
|
std::lock_guard<Mutex> lock(_mutex);
|
||||||
throw_if_exists(logger_name);
|
return _tp;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_all(std::function<void(std::shared_ptr<logger>)> fun)
|
void set_formatter(formatter_ptr f)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
std::lock_guard<Mutex> lock(_mutex);
|
std::lock_guard<Mutex> lock(_mutex);
|
||||||
_formatter = f;
|
_formatter = f;
|
||||||
@ -204,22 +131,30 @@ public:
|
|||||||
_err_handler = handler;
|
_err_handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
|
void apply_all(std::function<void(std::shared_ptr<logger>)> fun)
|
||||||
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
|
|
||||||
{
|
{
|
||||||
std::lock_guard<Mutex> lock(_mutex);
|
std::lock_guard<Mutex> lock(_mutex);
|
||||||
_async_mode = true;
|
for (auto &l : _loggers)
|
||||||
_async_q_size = q_size;
|
{
|
||||||
_overflow_policy = overflow_policy;
|
fun(l.second);
|
||||||
_worker_warmup_cb = worker_warmup_cb;
|
}
|
||||||
_flush_interval_ms = flush_interval_ms;
|
|
||||||
_worker_teardown_cb = worker_teardown_cb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_sync_mode()
|
void drop(const std::string &logger_name)
|
||||||
{
|
{
|
||||||
std::lock_guard<Mutex> lock(_mutex);
|
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()
|
static registry_t<Mutex> &instance()
|
||||||
@ -240,24 +175,22 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Mutex _mutex;
|
Mutex _mutex;
|
||||||
|
Mutex _tp_mutex;
|
||||||
std::unordered_map<std::string, std::shared_ptr<logger>> _loggers;
|
std::unordered_map<std::string, std::shared_ptr<logger>> _loggers;
|
||||||
formatter_ptr _formatter;
|
formatter_ptr _formatter;
|
||||||
level::level_enum _level = level::info;
|
level::level_enum _level = level::info;
|
||||||
level::level_enum _flush_level = level::off;
|
level::level_enum _flush_level = level::off;
|
||||||
log_err_handler _err_handler;
|
log_err_handler _err_handler;
|
||||||
bool _async_mode = false;
|
std::shared_ptr<thread_pool> _tp;
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef SPDLOG_NO_REGISTRY_MUTEX
|
#ifdef SPDLOG_NO_REGISTRY_MUTEX
|
||||||
|
#include "../details/null_mutex.h"
|
||||||
using registry = registry_t<spdlog::details::null_mutex>;
|
using registry = registry_t<spdlog::details::null_mutex>;
|
||||||
#else
|
#else
|
||||||
|
#include <mutex>
|
||||||
using registry = registry_t<std::mutex>;
|
using registry = registry_t<std::mutex>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace details
|
} // namespace details
|
||||||
} // namespace spdlog
|
} // namespace spdlog
|
@ -1,278 +1,201 @@
|
|||||||
|
////
|
||||||
|
//// Copyright(c) 2015 Gabi Melman.
|
||||||
|
//// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
////
|
||||||
//
|
//
|
||||||
// Copyright(c) 2015 Gabi Melman.
|
//#pragma once
|
||||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
|
||||||
//
|
//
|
||||||
|
////
|
||||||
#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"
|
//#ifdef __ANDROID__
|
||||||
#include "../sinks/file_sinks.h"
|
//#include "../sinks/android_sink.h"
|
||||||
#include "../sinks/stdout_sinks.h"
|
//#endif
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// 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)
|
// inline void spdlog::register_logger(std::shared_ptr<logger> logger)
|
||||||
{
|
//{
|
||||||
return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance());
|
// return details::registry::instance().register_logger(std::move(logger));
|
||||||
}
|
//}
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// stdout/stderr color loggers
|
|
||||||
//
|
//
|
||||||
#if defined _WIN32 && !defined(__cplusplus_winrt)
|
// inline void spdlog::drop(const std::string &name)
|
||||||
|
//{
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string &logger_name)
|
// details::registry::instance().drop(name);
|
||||||
{
|
//}
|
||||||
auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>();
|
//
|
||||||
return spdlog::details::registry::instance().create(logger_name, sink);
|
//// 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)
|
||||||
|
//{
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string &logger_name)
|
// return create_and_register<sinks::simple_file_sink_mt>(logger_name, filename, truncate);
|
||||||
{
|
//}
|
||||||
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::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);
|
||||||
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>();
|
//// Create multi/single threaded rotating file logger
|
||||||
return spdlog::details::registry::instance().create(logger_name, sink);
|
// 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)
|
||||||
|
//{
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string &logger_name)
|
// return create_and_register<sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files);
|
||||||
{
|
//}
|
||||||
auto sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_st>();
|
//
|
||||||
return spdlog::details::registry::instance().create(logger_name, sink);
|
// 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)
|
||||||
|
//{
|
||||||
#else // ansi terminal colors
|
// return create_and_register<sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files);
|
||||||
|
//}
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string &logger_name)
|
//
|
||||||
{
|
//// Create file logger which creates new file at midnight):
|
||||||
auto sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
|
// inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(
|
||||||
return spdlog::details::registry::instance().create(logger_name, sink);
|
// 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::stdout_color_st(const std::string &logger_name)
|
//}
|
||||||
{
|
//
|
||||||
auto sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_st>();
|
// inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(
|
||||||
return spdlog::details::registry::instance().create(logger_name, sink);
|
// 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);
|
||||||
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);
|
//// stdout/stderr loggers
|
||||||
}
|
////
|
||||||
|
// inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string &logger_name)
|
||||||
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>();
|
// auto new_logger = std::make_shared<logger>(logger_name, sinks::stdout_sink_mt::instance());
|
||||||
return spdlog::details::registry::instance().create(logger_name, sink);
|
// details::registry::instance().register_and_init(new_logger);
|
||||||
}
|
// return new_logger;
|
||||||
#endif
|
// //return details::registry::instance().create(logger_name, sinks::stdout_sink_mt::instance());
|
||||||
|
//}
|
||||||
#ifdef SPDLOG_ENABLE_SYSLOG
|
//
|
||||||
// Create syslog logger
|
// inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string &logger_name)
|
||||||
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)
|
// auto new_logger = std::make_shared<logger>(logger_name, sinks::stdout_sink_st::instance());
|
||||||
{
|
// details::registry::instance().register_and_init(new_logger);
|
||||||
return create<spdlog::sinks::syslog_sink>(logger_name, syslog_ident, syslog_option, syslog_facility);
|
// return new_logger;
|
||||||
}
|
//}
|
||||||
#endif
|
//
|
||||||
|
// inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string &logger_name)
|
||||||
#ifdef __ANDROID__
|
//{
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string &logger_name, const std::string &tag)
|
// auto new_logger = std::make_shared<logger>(logger_name, sinks::stderr_sink_mt::instance());
|
||||||
{
|
// details::registry::instance().register_and_init(new_logger);
|
||||||
return create<spdlog::sinks::android_sink>(logger_name, tag);
|
// return new_logger;
|
||||||
}
|
//}
|
||||||
#endif
|
//
|
||||||
|
// inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string &logger_name)
|
||||||
// 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)
|
// auto new_logger = std::make_shared<logger>(logger_name, sinks::stderr_sink_st::instance());
|
||||||
{
|
// details::registry::instance().register_and_init(new_logger);
|
||||||
return details::registry::instance().create(logger_name, sink);
|
// return new_logger;
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
// Create logger with multiple sinks
|
////
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string &logger_name, spdlog::sinks_init_list sinks)
|
//// stdout/stderr color loggers
|
||||||
{
|
////
|
||||||
return details::registry::instance().create(logger_name, sinks);
|
//#if defined _WIN32 && !defined(__cplusplus_winrt)
|
||||||
}
|
//
|
||||||
|
// inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string &logger_name)
|
||||||
template<typename Sink, typename... Args>
|
//{
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string &logger_name, Args... args)
|
// return create_and_register<sinks::wincolor_stdout_sink_mt>(logger_name);
|
||||||
{
|
//}
|
||||||
sink_ptr sink = std::make_shared<Sink>(args...);
|
//
|
||||||
return details::registry::instance().create(logger_name, {sink});
|
// 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);
|
||||||
template<class It>
|
//}
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string &logger_name, const It &sinks_begin, const It &sinks_end)
|
//
|
||||||
{
|
// inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string &logger_name)
|
||||||
return details::registry::instance().create(logger_name, sinks_begin, sinks_end);
|
//{
|
||||||
}
|
// return create_and_register<sinks::wincolor_stderr_sink_mt>(logger_name);
|
||||||
|
//}
|
||||||
// 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,
|
// inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string &logger_name)
|
||||||
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 create_and_register<sinks::wincolor_stderr_sink_st>(logger_name);
|
||||||
return details::registry::instance().create_async(
|
//}
|
||||||
logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sink);
|
//
|
||||||
}
|
//#else // ansi terminal colors
|
||||||
|
//
|
||||||
// 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,
|
// inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string &logger_name)
|
||||||
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 create_and_register<sinks::ansicolor_stdout_sink_mt>(logger_name);
|
||||||
{
|
//}
|
||||||
return details::registry::instance().create_async(
|
//
|
||||||
logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks);
|
// 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);
|
||||||
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,
|
// inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string &logger_name)
|
||||||
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
|
//{
|
||||||
{
|
// return create_and_register<sinks::ansicolor_stderr_sink_mt>(logger_name);
|
||||||
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 std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string &logger_name)
|
||||||
|
//{
|
||||||
inline void spdlog::set_formatter(spdlog::formatter_ptr f)
|
// return create_and_register<sinks::ansicolor_stderr_sink_st>(logger_name);
|
||||||
{
|
//}
|
||||||
details::registry::instance().formatter(std::move(f));
|
//#endif
|
||||||
}
|
//
|
||||||
|
//#ifdef SPDLOG_ENABLE_SYSLOG
|
||||||
inline void spdlog::set_pattern(const std::string &format_string)
|
//// Create syslog logger
|
||||||
{
|
// inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(
|
||||||
return details::registry::instance().set_pattern(format_string);
|
// 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);
|
||||||
|
//}
|
||||||
inline void spdlog::set_level(level::level_enum log_level)
|
//#endif
|
||||||
{
|
//
|
||||||
return details::registry::instance().set_level(log_level);
|
//#ifdef __ANDROID__
|
||||||
}
|
// inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string &logger_name, const std::string &tag)
|
||||||
|
//{
|
||||||
inline void spdlog::flush_on(level::level_enum log_level)
|
// return create_and_register<sinks::android_sink>(logger_name, tag);
|
||||||
{
|
//}
|
||||||
return details::registry::instance().flush_on(log_level);
|
//#endif
|
||||||
}
|
//
|
||||||
|
//
|
||||||
inline void spdlog::set_error_handler(log_err_handler handler)
|
//
|
||||||
{
|
//
|
||||||
return details::registry::instance().set_error_handler(std::move(handler));
|
// inline void spdlog::flush_on(level::level_enum log_level)
|
||||||
}
|
//{
|
||||||
|
// details::registry::instance().flush_on(log_level);
|
||||||
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)
|
// inline void spdlog::set_error_handler(log_err_handler handler)
|
||||||
{
|
//{
|
||||||
details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb);
|
// details::registry::instance().set_error_handler(std::move(handler));
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
inline void spdlog::set_sync_mode()
|
// inline void spdlog::apply_all(std::function<void(std::shared_ptr<logger>)> fun)
|
||||||
{
|
//{
|
||||||
details::registry::instance().set_sync_mode();
|
// details::registry::instance().apply_all(std::move(fun));
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
inline void spdlog::apply_all(std::function<void(std::shared_ptr<logger>)> fun)
|
// inline void spdlog::drop_all()
|
||||||
{
|
//{
|
||||||
details::registry::instance().apply_all(std::move(fun));
|
// details::registry::instance().drop_all();
|
||||||
}
|
//}
|
||||||
|
|
||||||
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.
|
// to avoid dynamic memory allocation.
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
INLINE_BUFFER_SIZE = 500
|
INLINE_BUFFER_SIZE = 500 // TODO reduce to 250
|
||||||
};
|
};
|
||||||
|
|
||||||
#if FMT_SECURE_SCL
|
#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)
|
// 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_pattern(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local);
|
||||||
void set_formatter(formatter_ptr msg_formatter);
|
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);
|
void flush_on(level::level_enum log_level);
|
||||||
|
|
||||||
virtual void flush();
|
|
||||||
|
|
||||||
const std::vector<sink_ptr> &sinks() const;
|
const std::vector<sink_ptr> &sinks() const;
|
||||||
|
|
||||||
// error handler
|
// error handler
|
||||||
virtual void set_error_handler(log_err_handler err_handler);
|
void set_error_handler(log_err_handler err_handler);
|
||||||
virtual log_err_handler error_handler();
|
log_err_handler error_handler();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _sink_it(details::log_msg &msg);
|
virtual void _sink_it(details::log_msg &msg);
|
||||||
virtual void _set_pattern(const std::string &pattern, pattern_time_type pattern_time);
|
virtual void _flush();
|
||||||
virtual void _set_formatter(formatter_ptr msg_formatter);
|
|
||||||
|
bool _should_flush(const details::log_msg &msg);
|
||||||
|
|
||||||
// default error handler: print the error to stderr with the max rate of 1 message/minute
|
// 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);
|
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);
|
|
||||||
|
|
||||||
// increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER))
|
// increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER))
|
||||||
void _incr_msg_counter(details::log_msg &msg);
|
void _incr_msg_counter(details::log_msg &msg);
|
||||||
|
@ -94,7 +94,7 @@ protected:
|
|||||||
// after color range
|
// after color range
|
||||||
_print_range(msg, msg.color_range_end, msg.formatted.size());
|
_print_range(msg, msg.color_range_end, msg.formatted.size());
|
||||||
}
|
}
|
||||||
else
|
else // no color
|
||||||
{
|
{
|
||||||
_print_range(msg, 0, msg.formatted.size());
|
_print_range(msg, 0, msg.formatted.size());
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,6 @@ class stdout_sink SPDLOG_FINAL : public base_sink<Mutex>
|
|||||||
public:
|
public:
|
||||||
explicit stdout_sink() = default;
|
explicit stdout_sink() = default;
|
||||||
|
|
||||||
static std::shared_ptr<MyType> instance()
|
|
||||||
{
|
|
||||||
static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _sink_it(const details::log_msg &msg) override
|
void _sink_it(const details::log_msg &msg) override
|
||||||
{
|
{
|
||||||
@ -53,12 +47,6 @@ class stderr_sink SPDLOG_FINAL : public base_sink<Mutex>
|
|||||||
public:
|
public:
|
||||||
explicit stderr_sink() = default;
|
explicit stderr_sink() = default;
|
||||||
|
|
||||||
static std::shared_ptr<MyType> instance()
|
|
||||||
{
|
|
||||||
static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _sink_it(const details::log_msg &msg) override
|
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)
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
//
|
//
|
||||||
// spdlog main header file.
|
// spdlog main header file.
|
||||||
@ -7,9 +7,23 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "details/registry.h"
|
||||||
|
#include "sinks/file_sinks.h"
|
||||||
|
#include "sinks/stdout_sinks.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "logger.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 <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -17,157 +31,213 @@
|
|||||||
|
|
||||||
namespace spdlog {
|
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.
|
// Return an existing logger or nullptr if a logger with such name doesn't exist.
|
||||||
// example: spdlog::get("my_logger")->info("hello {}", "world");
|
// 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
|
// Set global formatting
|
||||||
// example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v");
|
// example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v");
|
||||||
//
|
//
|
||||||
void set_pattern(const std::string &format_string);
|
inline void set_pattern(const std::string &format_string)
|
||||||
void set_formatter(formatter_ptr f);
|
{
|
||||||
|
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
|
// 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
|
// 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
|
// 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));
|
||||||
|
}
|
||||||
|
|
||||||
//
|
// Register the given logger with the given name
|
||||||
// Turn on async mode (off by default) and set the queue size for each async_logger.
|
inline void register_logger(std::shared_ptr<logger> logger)
|
||||||
// effective only for loggers created after this call.
|
{
|
||||||
// queue_size: size of queue (must be power of 2):
|
details::registry::instance().register_logger(std::move(logger));
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Turn off async mode
|
// Apply a user defined function on all registered loggers
|
||||||
void set_sync_mode();
|
// 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.
|
// Create and register multi/single threaded basic file logger.
|
||||||
// Basic logger simply writes to given file without any limitations or rotations.
|
// 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);
|
template<typename Factory = default_factory>
|
||||||
std::shared_ptr<logger> basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false);
|
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
|
// Create and register multi/single threaded rotating file logger
|
||||||
//
|
//
|
||||||
std::shared_ptr<logger> rotating_logger_mt(
|
template<typename Factory = default_factory>
|
||||||
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files);
|
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(
|
template<typename Factory = default_factory>
|
||||||
const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files);
|
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):
|
// 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);
|
template<typename Factory = default_factory>
|
||||||
std::shared_ptr<logger> daily_logger_st(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
template<typename Factory = default_factory>
|
||||||
// Create and register stdout/stderr loggers
|
inline std::shared_ptr<logger> daily_logger_st(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0)
|
||||||
//
|
{
|
||||||
std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name);
|
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute);
|
||||||
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);
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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
|
#ifdef SPDLOG_ENABLE_SYSLOG
|
||||||
std::shared_ptr<logger> syslog_logger(
|
// Create and register a syslog logger
|
||||||
const std::string &logger_name, const std::string &ident = "", int syslog_option = 0, int syslog_facilty = (1 << 3));
|
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
|
#endif
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#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
|
#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.
|
// Trace & Debug can be switched on/off at compile time for zero cost debug statements.
|
||||||
@ -200,5 +270,3 @@ void drop_all();
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace spdlog
|
} // namespace spdlog
|
||||||
|
|
||||||
#include "details/spdlog_impl.h"
|
|
||||||
|
@ -67,10 +67,11 @@ TEST_CASE("async_error_handler", "[errors]]")
|
|||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string err_msg("log failed with some msg");
|
std::string err_msg("log failed with some msg");
|
||||||
spdlog::set_async_mode(128);
|
|
||||||
std::string filename = "logs/simple_async_log.txt";
|
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) {
|
logger->set_error_handler([=](const std::string &msg) {
|
||||||
std::ofstream ofs("logs/custom_err.txt");
|
std::ofstream ofs("logs/custom_err.txt");
|
||||||
if (!ofs)
|
if (!ofs)
|
||||||
@ -85,8 +86,8 @@ TEST_CASE("async_error_handler", "[errors]]")
|
|||||||
#endif
|
#endif
|
||||||
logger->info("Good message #2");
|
logger->info("Good message #2");
|
||||||
spdlog::drop("logger"); // force logger to drain the queue and shutdown
|
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(count_lines(filename) == 2);
|
||||||
REQUIRE(file_contents("logs/custom_err.txt") == err_msg);
|
REQUIRE(file_contents("logs/custom_err.txt") == err_msg);
|
||||||
}
|
}
|
||||||
@ -96,9 +97,9 @@ TEST_CASE("async_error_handler2", "[errors]]")
|
|||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string err_msg("This is async handler error message");
|
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) {
|
logger->set_error_handler([=](const std::string &msg) {
|
||||||
std::ofstream ofs("logs/custom_err2.txt");
|
std::ofstream ofs("logs/custom_err2.txt");
|
||||||
if (!ofs)
|
if (!ofs)
|
||||||
@ -107,8 +108,8 @@ TEST_CASE("async_error_handler2", "[errors]]")
|
|||||||
});
|
});
|
||||||
logger->info("Hello failure");
|
logger->info("Hello failure");
|
||||||
spdlog::drop("failed_logger"); // force logger to drain the queue and shutdown
|
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);
|
REQUIRE(file_contents("logs/custom_err2.txt") == err_msg);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#define SPDLOG_TRACE_ON
|
#define SPDLOG_TRACE_ON
|
||||||
#define SPDLOG_DEBUG_ON
|
#define SPDLOG_DEBUG_ON
|
||||||
|
|
||||||
|
#include "../include/spdlog/async.h"
|
||||||
#include "../include/spdlog/sinks/null_sink.h"
|
#include "../include/spdlog/sinks/null_sink.h"
|
||||||
#include "../include/spdlog/sinks/ostream_sink.h"
|
#include "../include/spdlog/sinks/ostream_sink.h"
|
||||||
#include "../include/spdlog/spdlog.h"
|
#include "../include/spdlog/spdlog.h"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user