Asink sink (#3309)

Replace async logger with async sink
This commit is contained in:
Gabi Melman
2025-01-05 02:17:31 +02:00
committed by GitHub
parent 166843ff3a
commit 83c9ede9e6
82 changed files with 986 additions and 1789 deletions

View File

@@ -1,85 +0,0 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
//
// Async logging using global thread pool
// All loggers created here share same global thread pool.
// Each log message is pushed to a queue along with a shared pointer to the
// logger.
// If a logger deleted while having pending messages in the queue, it's actual
// destruction will defer
// until all its messages are processed by the thread pool.
// This is because each message in the queue holds a shared_ptr to the
// originating logger.
#include <functional>
#include <memory>
#include <mutex>
#include "./async_logger.h"
#include "./details/context.h"
#include "./details/thread_pool.h"
#include "spdlog.h"
namespace spdlog {
namespace details {
static constexpr size_t default_async_q_size = 8192;
}
// async logger factory - creates async loggers backed with thread pool.
// if a global thread pool doesn't already exist, create it with default queue
// size of 8192 items and single thread.
template <async_overflow_policy OverflowPolicy = async_overflow_policy::block>
struct async_factory_impl {
template <typename Sink, typename... SinkArgs>
static std::shared_ptr<async_logger> create(std::string logger_name, SinkArgs &&...args) {
auto context = spdlog::context();
// create global thread pool if not already exists
auto &mutex = context->tp_mutex();
std::lock_guard<std::recursive_mutex> tp_lock(mutex);
auto tp = context->get_tp();
if (tp == nullptr) {
tp = std::make_shared<details::thread_pool>(details::default_async_q_size, 1U);
context->set_tp(tp);
}
auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);
auto new_logger = std::make_shared<async_logger>(std::move(logger_name), std::move(sink), std::move(tp), OverflowPolicy);
return new_logger;
}
};
using async_factory = async_factory_impl<async_overflow_policy::block>;
using async_factory_nonblock = async_factory_impl<async_overflow_policy::overrun_oldest>;
template <typename Sink, typename... SinkArgs>
std::shared_ptr<spdlog::logger> create_async(std::string logger_name, SinkArgs &&...sink_args) {
return async_factory::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...);
}
template <typename Sink, typename... SinkArgs>
std::shared_ptr<spdlog::logger> create_async_nb(std::string logger_name, SinkArgs &&...sink_args) {
return async_factory_nonblock::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...);
}
// set global thread pool.
inline void init_thread_pool(size_t q_size,
size_t thread_count,
std::function<void()> on_thread_start,
std::function<void()> on_thread_stop) {
auto tp = std::make_shared<details::thread_pool>(q_size, thread_count, on_thread_start, on_thread_stop);
spdlog::context()->set_tp(std::move(tp));
}
inline void init_thread_pool(size_t q_size, size_t thread_count, std::function<void()> on_thread_start) {
init_thread_pool(q_size, thread_count, on_thread_start, [] {});
}
inline void init_thread_pool(size_t q_size, size_t thread_count) {
init_thread_pool(q_size, thread_count, [] {}, [] {});
}
// get the global thread pool.
inline std::shared_ptr<spdlog::details::thread_pool> thread_pool() { return spdlog::context()->get_tp(); }
} // namespace spdlog

View File

@@ -1,69 +0,0 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
// Fast asynchronous logger.
// Uses pre allocated queue.
// Creates a single back thread to pop messages from the queue and log them.
//
// Upon each log write the logger:
// 1. Checks if its log level is enough to log the message
// 2. Push a new copy of the message to a queue (or block the caller until
// space is available in the queue)
// Upon destruction, logs all remaining messages in the queue before
// destructing
#include "./logger.h"
namespace spdlog {
// Async overflow policy - block by default.
enum class async_overflow_policy {
block, // Block until message can be enqueued
overrun_oldest, // Discard the oldest message in the queue if full when trying to
// add new item.
discard_new // Discard new message if the queue is full when trying to add new item.
};
namespace details {
class thread_pool;
}
class SPDLOG_API async_logger final : public std::enable_shared_from_this<async_logger>, public logger {
friend class details::thread_pool;
public:
template <typename It>
async_logger(std::string logger_name,
It begin,
It end,
std::weak_ptr<details::thread_pool> tp,
async_overflow_policy overflow_policy = async_overflow_policy::block)
: logger(std::move(logger_name), begin, end),
thread_pool_(std::move(tp)),
overflow_policy_(overflow_policy) {}
async_logger(std::string logger_name,
sinks_init_list sinks_list,
std::weak_ptr<details::thread_pool> tp,
async_overflow_policy overflow_policy = async_overflow_policy::block);
async_logger(std::string logger_name,
sink_ptr single_sink,
std::weak_ptr<details::thread_pool> tp,
async_overflow_policy overflow_policy = async_overflow_policy::block);
std::shared_ptr<logger> clone(std::string new_name) override;
protected:
void sink_it_(const details::log_msg &msg) override;
void flush_() override;
void backend_sink_it_(const details::log_msg &incoming_log_msg);
void backend_flush_();
private:
std::weak_ptr<details::thread_pool> thread_pool_;
async_overflow_policy overflow_policy_;
};
} // namespace spdlog

View File

@@ -7,7 +7,7 @@
#include <cctype>
#include "../common.h"
#include "common.h"
#if defined(__has_include)
#if __has_include(<version>)

View File

@@ -12,8 +12,11 @@
#include <memory>
#include <string>
#include <string_view>
#include <cstdint>
#include "./source_loc.h"
#include "fmt/base.h"
#include "fmt/xchar.h"
#if defined(SPDLOG_SHARED_LIB)
#if defined(_WIN32)
@@ -29,8 +32,6 @@
#define SPDLOG_API
#endif
#include "fmt/fmt.h"
#define SPDLOG_FMT_RUNTIME(format_string) fmt::runtime(format_string)
#define SPDLOG_FMT_STRING(format_string) FMT_STRING(format_string)
@@ -73,7 +74,7 @@ using format_string_t = fmt::format_string<Args...>;
#endif
// Log level enum
enum class level {
enum class level : std::uint8_t {
trace = SPDLOG_LEVEL_TRACE,
debug = SPDLOG_LEVEL_DEBUG,
info = SPDLOG_LEVEL_INFO,
@@ -81,7 +82,7 @@ enum class level {
err = SPDLOG_LEVEL_ERROR,
critical = SPDLOG_LEVEL_CRITICAL,
off = SPDLOG_LEVEL_OFF,
n_levels
n_levels = SPDLOG_LEVEL_OFF + 1
};
using atomic_level_t = std::atomic<level>;

View File

@@ -0,0 +1,37 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <cstdint>
#include "./log_msg.h"
namespace spdlog {
namespace details {
// Extend log_msg with internal buffer to store its payload.
// This is needed since log_msg holds string_views that points to stack data.
class SPDLOG_API async_log_msg : public log_msg {
public:
enum class type:std::uint8_t { log, flush, terminate };
async_log_msg() = default;
explicit async_log_msg(type type);
async_log_msg(type type, const log_msg &orig_msg);
~async_log_msg() = default;
async_log_msg(const async_log_msg &other);
async_log_msg(async_log_msg &&other) noexcept;
async_log_msg &operator=(const async_log_msg &other);
async_log_msg &operator=(async_log_msg &&other) noexcept;
type message_type() const {return msg_type_;}
private:
type msg_type_{type::log};
memory_buf_t buffer_;
void update_string_views();
};
} // namespace details
} // namespace spdlog

View File

@@ -7,8 +7,6 @@
#include <cassert>
#include <vector>
#include "spdlog/common.h"
namespace spdlog {
namespace details {
template <typename T>

View File

@@ -1,59 +0,0 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
// Loggers registry of unique name->logger pointer
// An attempt to create a logger with an already existing name will result with spdlog_ex exception.
// If user requests a non-existing logger, nullptr will be returned
// This class is thread safe
#include <memory>
#include <mutex>
#include <string>
#include "../common.h"
#include "./periodic_worker.h"
namespace spdlog {
class logger;
namespace details {
class thread_pool;
class SPDLOG_API context {
public:
context() = default;
explicit context(std::unique_ptr<logger> global_logger);
~context() = default;
context(const context &) = delete;
context &operator=(const context &) = delete;
[[nodiscard]] std::shared_ptr<logger> global_logger();
// Return raw ptr to the global logger.
// To be used directly by the spdlog global api (e.g. spdlog::info)
// This make the global API faster, but cannot be used concurrently with set_global_logger().
// e.g do not call set_global_logger() from one thread while calling spdlog::info() from
// another.
[[nodiscard]] logger *global_logger_raw() const noexcept;
// set logger instance.
void set_logger(std::shared_ptr<logger> new_logger);
void set_tp(std::shared_ptr<thread_pool> tp);
[[nodiscard]] std::shared_ptr<thread_pool> get_tp();
// clean all resources
void shutdown();
[[nodiscard]] std::recursive_mutex &tp_mutex();
private:
std::recursive_mutex tp_mutex_;
std::shared_ptr<thread_pool> tp_;
std::shared_ptr<logger> global_logger_;
};
} // namespace details
} // namespace spdlog

View File

@@ -0,0 +1,23 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <string>
#include <mutex>
#include <exception>
#include "spdlog/common.h"
// by default, prints the error to stderr, thread safe
namespace spdlog {
namespace details {
class SPDLOG_API err_helper {
err_handler custom_err_handler_;
public:
void handle_ex(const std::string& origin, const source_loc& loc, const std::exception& ex) const;
void handle_unknown_ex(const std::string& origin, const source_loc& loc) const;
void set_err_handler(err_handler handler);
};
}} // namespace spdlog::details

View File

@@ -7,7 +7,6 @@
#include <type_traits>
#include "../common.h"
#include "../fmt/fmt.h"
// Some fmt helpers to efficiently format and pad ints and strings
namespace spdlog {

View File

@@ -1,28 +0,0 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include "./log_msg.h"
namespace spdlog {
namespace details {
// Extend log_msg with internal buffer to store its payload.
// This is needed since log_msg holds string_views that points to stack data.
class SPDLOG_API log_msg_buffer : public log_msg {
memory_buf_t buffer;
void update_string_views();
public:
log_msg_buffer() = default;
explicit log_msg_buffer(const log_msg &orig_msg);
log_msg_buffer(const log_msg_buffer &other);
log_msg_buffer(log_msg_buffer &&other) noexcept;
log_msg_buffer &operator=(const log_msg_buffer &other);
log_msg_buffer &operator=(log_msg_buffer &&other) noexcept;
};
} // namespace details
} // namespace spdlog

View File

@@ -37,7 +37,7 @@ public:
push_cv_.notify_one();
}
// enqueue immediately. overrun oldest message in the queue if no room left.
// enqueue immediately. overrun the oldest message in the queue if no room left.
void enqueue_nowait(T &&item) {
{
std::unique_lock<std::mutex> lock(queue_mutex_);

View File

@@ -1,57 +0,0 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
// periodic worker thread - periodically executes the given callback function.
//
// RAII over the owned thread:
// creates the thread on construction.
// stops and joins the thread on destruction (if the thread is executing a callback, wait for it
// to finish first).
#include <chrono>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <thread>
#include "../common.h"
namespace spdlog {
namespace details {
class SPDLOG_API periodic_worker {
public:
template <typename Rep, typename Period>
periodic_worker(const std::function<void()> &callback_fun, std::chrono::duration<Rep, Period> interval) {
active_ = (interval > std::chrono::duration<Rep, Period>::zero());
if (!active_) {
return;
}
worker_thread_ = std::thread([this, callback_fun, interval]() {
for (;;) {
std::unique_lock<std::mutex> lock(this->mutex_);
if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; })) {
return; // active_ == false, so exit this thread
}
callback_fun();
}
});
}
std::thread &get_thread() { return worker_thread_; }
periodic_worker(const periodic_worker &) = delete;
periodic_worker &operator=(const periodic_worker &) = delete;
// stop the worker thread and join it
~periodic_worker();
private:
bool active_;
std::thread worker_thread_;
std::mutex mutex_;
std::condition_variable cv_;
};
} // namespace details
} // namespace spdlog

View File

@@ -1,21 +0,0 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include "./context.h"
namespace spdlog {
// Default logger factory- creates synchronous loggers
class logger;
struct synchronous_factory {
template <typename Sink, typename... SinkArgs>
static std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs &&...args) {
auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);
auto new_logger = std::make_shared<spdlog::logger>(std::move(logger_name), std::move(sink));
return new_logger;
}
};
} // namespace spdlog

View File

@@ -1,112 +0,0 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#pragma once
#include <chrono>
#include <functional>
#include <memory>
#include <thread>
#include <vector>
#include "../async.h"
#include "./log_msg_buffer.h"
#include "./mpmc_blocking_q.h"
#include "./os.h"
namespace spdlog {
class async_logger;
namespace details {
using async_logger_ptr = std::shared_ptr<spdlog::async_logger>;
enum class async_msg_type { log, flush, terminate };
// Async msg to move to/from the queue
// Movable only. should never be copied
struct async_msg : log_msg_buffer {
async_msg_type msg_type{async_msg_type::log};
async_logger_ptr worker_ptr;
async_msg() = default;
~async_msg() = default;
// should only be moved in or out of the queue..
async_msg(const async_msg &) = delete;
// support for vs2013 move
#if defined(_MSC_VER) && _MSC_VER <= 1800
async_msg(async_msg &&other)
: log_msg_buffer(std::move(other)),
msg_type(other.msg_type),
worker_ptr(std::move(other.worker_ptr)) {}
async_msg &operator=(async_msg &&other) {
*static_cast<log_msg_buffer *>(this) = std::move(other);
msg_type = other.msg_type;
worker_ptr = std::move(other.worker_ptr);
return *this;
}
#else // (_MSC_VER) && _MSC_VER <= 1800
async_msg(async_msg &&) = default;
async_msg &operator=(async_msg &&) = default;
#endif
// construct from log_msg with given type
async_msg(async_logger_ptr &&worker, async_msg_type the_type, const details::log_msg &m)
: log_msg_buffer{m},
msg_type{the_type},
worker_ptr{std::move(worker)} {}
async_msg(async_logger_ptr &&worker, async_msg_type the_type)
: log_msg_buffer{},
msg_type{the_type},
worker_ptr{std::move(worker)} {}
explicit async_msg(async_msg_type the_type)
: async_msg{nullptr, the_type} {}
};
class SPDLOG_API thread_pool {
public:
using item_type = async_msg;
using q_type = details::mpmc_blocking_queue<item_type>;
thread_pool(size_t q_max_items,
size_t threads_n,
std::function<void()> on_thread_start,
std::function<void()> on_thread_stop);
thread_pool(size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start);
thread_pool(size_t q_max_items, size_t threads_n);
// message all threads to terminate gracefully and join them
~thread_pool();
thread_pool(const thread_pool &) = delete;
thread_pool &operator=(thread_pool &&) = delete;
void post_log(async_logger_ptr &&worker_ptr, const details::log_msg &msg, async_overflow_policy overflow_policy);
void post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy);
size_t overrun_counter();
void reset_overrun_counter();
size_t discard_counter();
void reset_discard_counter();
size_t queue_size();
private:
q_type q_;
std::vector<std::thread> threads_;
void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy);
void worker_loop_();
// process next message in the queue
// return true if this thread should still be active (while no terminate msg
// was received)
bool process_next_msg_();
};
} // namespace details
} // namespace spdlog

View File

@@ -1,9 +0,0 @@
//
// Copyright(c) 2016-2018 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#pragma once
#include "fmt/format.h"
#include "fmt/xchar.h"

View File

@@ -3,37 +3,22 @@
#pragma once
// Thread safe logger (except for set_error_handler())
// Has name, log level, vector of std::shared sink pointers and formatter
// Upon each log write the logger:
// 1. Checks if its log level is enough to log the message and if yes:
// 2. Call the underlying sinks to do the job.
// 3. Each sink use its own private copy of a formatter to format the message
// and send to its destination.
//
// The use of private formatter per sink provides the opportunity to cache some
// formatted data, and support for different format per sink.
// Thread-safe logger, with exceptions for these non-thread-safe methods:
// set_pattern() - Modifies the log pattern.
// set_formatter() - Sets a new formatter.
// set_error_handler() - Assigns a new error handler.
// sinks() (non-const) - Accesses and potentially modifies the sinks directly.
// By default, the logger does not throw exceptions during logging.
// To enable exception throwing for logging errors, set a custom error handler.
#include <cassert>
#include <iterator>
#include <vector>
#include "./common.h"
#include "./details/log_msg.h"
#include "./sinks/sink.h"
#define SPDLOG_LOGGER_CATCH(location) \
catch (const std::exception &ex) { \
if (!location.empty()) { \
err_handler_(fmt_lib::format(SPDLOG_FMT_STRING("{} [{}({})]"), ex.what(), location.filename, location.line)); \
} else { \
err_handler_(ex.what()); \
} \
} \
catch (...) { \
err_handler_("Rethrowing unknown exception in logger"); \
throw; \
}
#include "common.h"
#include "details/err_helper.h"
#include "details/log_msg.h"
#include "sinks/sink.h"
namespace spdlog {
@@ -60,7 +45,7 @@ public:
logger(const logger &other) noexcept;
logger(logger &&other) noexcept;
virtual ~logger() = default;
~logger() = default;
template <typename... Args>
void log(source_loc loc, level lvl, format_string_t<Args...> fmt, Args &&...args) {
@@ -168,14 +153,14 @@ public:
void set_error_handler(err_handler);
// create new logger with same sinks and configuration.
virtual std::shared_ptr<logger> clone(std::string logger_name);
std::shared_ptr<logger> clone(std::string logger_name);
protected:
private:
std::string name_;
std::vector<sink_ptr> sinks_;
spdlog::atomic_level_t level_{level::info};
spdlog::atomic_level_t flush_level_{level::off};
err_handler custom_err_handler_{nullptr};
atomic_level_t level_{level::info};
atomic_level_t flush_level_{level::off};
details::err_helper err_helper_;
// common implementation for after templated public api has been resolved to format string and
// args
@@ -186,19 +171,25 @@ protected:
memory_buf_t buf;
fmt::vformat_to(std::back_inserter(buf), format_string, fmt::make_format_args(args...));
sink_it_(details::log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())));
} catch (const std::exception &ex) {
err_helper_.handle_ex(name_, loc, ex);
} catch (...) {
err_helper_.handle_unknown_ex(name_, loc);
}
SPDLOG_LOGGER_CATCH(loc)
}
// log the given message (if the given log level is high enough)
virtual void sink_it_(const details::log_msg &msg) {
void sink_it_(const details::log_msg &msg) {
assert(should_log(msg.log_level));
for (auto &sink : sinks_) {
if (sink->should_log(msg.log_level)) {
try {
sink->log(msg);
} catch (const std::exception &ex) {
err_helper_.handle_ex(name_, msg.source, ex);
} catch (...) {
err_helper_.handle_unknown_ex(name_, msg.source);
}
SPDLOG_LOGGER_CATCH(msg.source)
}
}
@@ -206,12 +197,8 @@ protected:
flush_();
}
}
virtual void flush_();
void flush_();
[[nodiscard]] bool should_flush_(const details::log_msg &msg) const;
// handle errors during logging.
// default handler prints the error to stderr at max rate of 1 message/sec.
void err_handler_(const std::string &msg);
};
} // namespace spdlog

View File

@@ -16,7 +16,6 @@
#include "../details/fmt_helper.h"
#include "../details/null_mutex.h"
#include "../details/os.h"
#include "../details/synchronous_factory.h"
#include "./base_sink.h"
#if !defined(SPDLOG_ANDROID_RETRIES)
@@ -120,19 +119,6 @@ template <int BufferId = log_id::LOG_ID_MAIN>
using android_sink_buf_st = android_sink<details::null_mutex, BufferId>;
} // namespace sinks
// Create and register android syslog logger
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> android_logger_mt(const std::string &logger_name, const std::string &tag = "spdlog") {
return Factory::template create<sinks::android_sink_mt>(logger_name, tag);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> android_logger_st(const std::string &logger_name, const std::string &tag = "spdlog") {
return Factory::template create<sinks::android_sink_st>(logger_name, tag);
}
} // namespace spdlog
#endif // __ANDROID__

View File

@@ -94,7 +94,6 @@ public:
using ansicolor_stdout_sink_mt = ansicolor_stdout_sink<std::mutex>;
using ansicolor_stdout_sink_st = ansicolor_stdout_sink<details::null_mutex>;
using ansicolor_stderr_sink_mt = ansicolor_stderr_sink<std::mutex>;
using ansicolor_stderr_sink_st = ansicolor_stderr_sink<details::null_mutex>;

View File

@@ -0,0 +1,86 @@
#pragma once
#include <atomic>
#include <cstdint>
#include <functional>
#include <memory>
#include <thread>
#include <vector>
#include "../details/async_log_msg.h"
#include "../details/err_helper.h"
#include "sink.h"
// async_sink is a sink that sends log messages to a dist_sink in a separate thread using a queue.
// The worker thread dequeues the messages and sends them to the dist_sink to perform the actual logging.
// Once the sink is destroyed, the worker thread empties the queue and exits.
namespace spdlog::details { // forward declaration
template <typename T>
class mpmc_blocking_queue;
}
namespace spdlog {
namespace sinks {
class SPDLOG_API async_sink final : public sink {
public:
enum class overflow_policy : std::uint8_t {
block, // Block until the log message can be enqueued (default).
overrun_oldest, // Overrun the oldest message in the queue if full.
discard_new // Discard the log message if the queue is full
};
enum { default_queue_size = 8192, max_queue_size = 10 * 1024 * 1024 };
struct config {
size_t queue_size = default_queue_size;
overflow_policy policy = overflow_policy::block;
std::vector<std::shared_ptr<sink>> sinks;
std::function<void()> on_thread_start = nullptr;
std::function<void()> on_thread_stop = nullptr;
err_handler custom_err_handler = nullptr;
};
explicit async_sink(config async_config);
// create an async_sink with one backend sink
template <typename Sink, typename... SinkArgs>
static std::shared_ptr<async_sink> with(SinkArgs &&...sink_args) {
config cfg{};
cfg.sinks.emplace_back(std::make_shared<Sink>(std::forward<SinkArgs>(sink_args)...));
return std::make_shared<async_sink>(cfg);
}
~async_sink() override;
// sink interface implementation
void log(const details::log_msg &msg) override;
void flush() override;
void set_pattern(const std::string &pattern) override;
void set_formatter(std::unique_ptr<formatter> sink_formatter) override;
// async sink specific methods
[[nodiscard]] size_t get_overrun_counter() const;
void reset_overrun_counter() const;
[[nodiscard]] size_t get_discard_counter() const;
void reset_discard_counter() const;
[[nodiscard]] const config &get_config() const;
private:
using async_log_msg = details::async_log_msg;
using queue_t = details::mpmc_blocking_queue<async_log_msg>;
void send_message_(async_log_msg::type msg_type, const details::log_msg &msg) const;
void backend_loop_();
void backend_log_(const details::log_msg &msg) ;
void backend_flush_();
config config_;
std::unique_ptr<queue_t> q_;
std::thread worker_thread_;
details::err_helper err_helper_;
};
} // namespace sinks
} // namespace spdlog

View File

@@ -43,5 +43,6 @@ protected:
virtual void set_pattern_(const std::string &pattern);
virtual void set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter);
};
} // namespace sinks
} // namespace spdlog

View File

@@ -8,7 +8,6 @@
#include "../details/file_helper.h"
#include "../details/null_mutex.h"
#include "../details/synchronous_factory.h"
#include "./base_sink.h"
namespace spdlog {
@@ -34,24 +33,4 @@ using basic_file_sink_mt = basic_file_sink<std::mutex>;
using basic_file_sink_st = basic_file_sink<details::null_mutex>;
} // namespace sinks
//
// factory functions
//
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> basic_logger_mt(const std::string &logger_name,
const filename_t &filename,
bool truncate = false,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::basic_file_sink_mt>(logger_name, filename, truncate, event_handlers);
}
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> basic_logger_st(const std::string &logger_name,
const filename_t &filename,
bool truncate = false,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::basic_file_sink_st>(logger_name, filename, truncate, event_handlers);
}
} // namespace spdlog

View File

@@ -7,7 +7,6 @@
#include <string>
#include "../details/null_mutex.h"
#include "../details/synchronous_factory.h"
#include "./base_sink.h"
namespace spdlog {
@@ -37,18 +36,4 @@ using callback_sink_mt = callback_sink<std::mutex>;
using callback_sink_st = callback_sink<details::null_mutex>;
} // namespace sinks
//
// factory functions
//
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> callback_logger_mt(const std::string &logger_name, const custom_log_callback &callback) {
return Factory::template create<sinks::callback_sink_mt>(logger_name, callback);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> callback_logger_st(const std::string &logger_name, const custom_log_callback &callback) {
return Factory::template create<sinks::callback_sink_st>(logger_name, callback);
}
} // namespace spdlog

View File

@@ -15,7 +15,6 @@
#include "../details/file_helper.h"
#include "../details/null_mutex.h"
#include "../details/os.h"
#include "../details/synchronous_factory.h"
#include "./base_sink.h"
namespace spdlog {
@@ -190,55 +189,4 @@ using daily_file_format_sink_mt = daily_file_sink<std::mutex, daily_filename_for
using daily_file_format_sink_st = daily_file_sink<details::null_mutex, daily_filename_format_calculator>;
} // namespace sinks
//
// factory functions
//
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_mt(const std::string &logger_name,
const filename_t &filename,
int hour = 0,
int minute = 0,
bool truncate = false,
uint16_t max_files = 0,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files,
event_handlers);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_format_mt(const std::string &logger_name,
const filename_t &filename,
int hour = 0,
int minute = 0,
bool truncate = false,
uint16_t max_files = 0,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::daily_file_format_sink_mt>(logger_name, filename, hour, minute, truncate, max_files,
event_handlers);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_st(const std::string &logger_name,
const filename_t &filename,
int hour = 0,
int minute = 0,
bool truncate = false,
uint16_t max_files = 0,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files,
event_handlers);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_format_st(const std::string &logger_name,
const filename_t &filename,
int hour = 0,
int minute = 0,
bool truncate = false,
uint16_t max_files = 0,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::daily_file_format_sink_st>(logger_name, filename, hour, minute, truncate, max_files,
event_handlers);
}
} // namespace spdlog

View File

@@ -24,14 +24,14 @@ class dist_sink : public base_sink<Mutex> {
public:
dist_sink() = default;
explicit dist_sink(std::vector<std::shared_ptr<sink>> sinks)
: sinks_(sinks) {}
: sinks_(std::move(sinks)) {}
dist_sink(const dist_sink &) = delete;
dist_sink &operator=(const dist_sink &) = delete;
void add_sink(std::shared_ptr<sink> sub_sink) {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
sinks_.push_back(sub_sink);
sinks_.push_back(std::move(sub_sink));
}
void remove_sink(std::shared_ptr<sink> sub_sink) {
@@ -48,7 +48,7 @@ public:
protected:
void sink_it_(const details::log_msg &msg) override {
for (auto &sub_sink : sinks_) {
for (const auto &sub_sink : sinks_) {
if (sub_sink->should_log(msg.log_level)) {
sub_sink->log(msg);
}

View File

@@ -14,8 +14,6 @@
#include "../details/file_helper.h"
#include "../details/null_mutex.h"
#include "../details/os.h"
#include "../details/synchronous_factory.h"
#include "../fmt/fmt.h"
#include "./base_sink.h"
namespace spdlog {
@@ -167,25 +165,4 @@ using hourly_file_sink_mt = hourly_file_sink<std::mutex>;
using hourly_file_sink_st = hourly_file_sink<details::null_mutex>;
} // namespace sinks
//
// factory functions
//
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> hourly_logger_mt(const std::string &logger_name,
const filename_t &filename,
bool truncate = false,
uint16_t max_files = 0,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::hourly_file_sink_mt>(logger_name, filename, truncate, max_files, event_handlers);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> hourly_logger_st(const std::string &logger_name,
const filename_t &filename,
bool truncate = false,
uint16_t max_files = 0,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::hourly_file_sink_st>(logger_name, filename, truncate, max_files, event_handlers);
}
} // namespace spdlog

View File

@@ -12,11 +12,9 @@
#include <mutex>
#include "../async.h"
#include "../common.h"
#include "../details/log_msg.h"
#include "../details/null_mutex.h"
#include "../details/synchronous_factory.h"
#include "./base_sink.h"
// kafka header
@@ -89,25 +87,4 @@ using kafka_sink_mt = kafka_sink<std::mutex>;
using kafka_sink_st = kafka_sink<spdlog::details::null_mutex>;
} // namespace sinks
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> kafka_logger_mt(const std::string &logger_name, spdlog::sinks::kafka_sink_config config) {
return Factory::template create<sinks::kafka_sink_mt>(logger_name, config);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> kafka_logger_st(const std::string &logger_name, spdlog::sinks::kafka_sink_config config) {
return Factory::template create<sinks::kafka_sink_st>(logger_name, config);
}
template <typename Factory = spdlog::async_factory>
inline std::shared_ptr<spdlog::logger> kafka_logger_async_mt(std::string logger_name, spdlog::sinks::kafka_sink_config config) {
return Factory::template create<sinks::kafka_sink_mt>(logger_name, config);
}
template <typename Factory = spdlog::async_factory>
inline std::shared_ptr<spdlog::logger> kafka_logger_async_st(std::string logger_name, spdlog::sinks::kafka_sink_config config) {
return Factory::template create<sinks::kafka_sink_st>(logger_name, config);
}
} // namespace spdlog

View File

@@ -17,9 +17,10 @@
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>
#include <mutex>
#include "../details/null_mutex.h"
#include "../common.h"
#include "../details/log_msg.h"
#include "../details/synchronous_factory.h"
#include "./base_sink.h"
namespace spdlog {
@@ -75,28 +76,8 @@ private:
std::unique_ptr<mongocxx::client> client_ = nullptr;
};
#include <mutex>
#include "../details/null_mutex.h"
using mongo_sink_mt = mongo_sink<std::mutex>;
using mongo_sink_st = mongo_sink<spdlog::details::null_mutex>;
using mongo_sink_st = mongo_sink<details::null_mutex>;
} // namespace sinks
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> mongo_logger_mt(const std::string &logger_name,
const std::string &db_name,
const std::string &collection_name,
const std::string &uri = "mongodb://localhost:27017") {
return Factory::template create<sinks::mongo_sink_mt>(logger_name, db_name, collection_name, uri);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> mongo_logger_st(const std::string &logger_name,
const std::string &db_name,
const std::string &collection_name,
const std::string &uri = "mongodb://localhost:27017") {
return Factory::template create<sinks::mongo_sink_st>(logger_name, db_name, collection_name, uri);
}
} // namespace spdlog

View File

@@ -4,7 +4,6 @@
#pragma once
#include <mutex>
#include "../details/null_mutex.h"
#include "./base_sink.h"

View File

@@ -4,7 +4,6 @@
#pragma once
#include "../details/null_mutex.h"
#include "../details/synchronous_factory.h"
#include "./base_sink.h"
namespace spdlog {
@@ -21,19 +20,4 @@ using null_sink_mt = null_sink<details::null_mutex>;
using null_sink_st = null_sink<details::null_mutex>;
} // namespace sinks
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> null_logger_mt(const std::string &logger_name) {
auto null_logger = Factory::template create<sinks::null_sink_mt>(logger_name);
null_logger->set_level(level::off);
return null_logger;
}
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> null_logger_st(const std::string &logger_name) {
auto null_logger = Factory::template create<sinks::null_sink_st>(logger_name);
null_logger->set_level(level::off);
return null_logger;
}
} // namespace spdlog

View File

@@ -17,7 +17,6 @@
#include "../common.h"
#include "../details/log_msg.h"
#include "../details/synchronous_factory.h"
#include "./base_sink.h"
//
@@ -218,75 +217,10 @@ protected:
std::array<QTextCharFormat, level::n_levels> colors_;
};
#include <mutex>
#include "../details/null_mutex.h"
using qt_sink_mt = qt_sink<std::mutex>;
using qt_sink_st = qt_sink<details::null_mutex>;
using qt_color_sink_mt = qt_color_sink<std::mutex>;
using qt_color_sink_st = qt_color_sink<details::null_mutex>;
} // namespace sinks
//
// Factory functions
//
// log to QTextEdit
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_mt(const std::string &logger_name,
QTextEdit *qt_object,
const std::string &meta_method = "append") {
return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_st(const std::string &logger_name,
QTextEdit *qt_object,
const std::string &meta_method = "append") {
return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method);
}
// log to QPlainTextEdit
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_mt(const std::string &logger_name,
QPlainTextEdit *qt_object,
const std::string &meta_method = "appendPlainText") {
return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_st(const std::string &logger_name,
QPlainTextEdit *qt_object,
const std::string &meta_method = "appendPlainText") {
return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method);
}
// log to QObject
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_mt(const std::string &logger_name, QObject *qt_object, const std::string &meta_method) {
return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_logger_st(const std::string &logger_name, QObject *qt_object, const std::string &meta_method) {
return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method);
}
// log to QTextEdit with colorized output
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_color_logger_mt(const std::string &logger_name,
QTextEdit *qt_text_edit,
int max_lines,
bool is_utf8 = false) {
return Factory::template create<sinks::qt_color_sink_mt>(logger_name, qt_text_edit, max_lines, false, is_utf8);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> qt_color_logger_st(const std::string &logger_name,
QTextEdit *qt_text_edit,
int max_lines,
bool is_utf8 = false) {
return Factory::template create<sinks::qt_color_sink_st>(logger_name, qt_text_edit, max_lines, false, is_utf8);
}
} // namespace spdlog

View File

@@ -7,10 +7,10 @@
#include <mutex>
#include <string_view>
#include "../details/async_log_msg.h"
#include "../details/circular_q.h"
#include "../details/log_msg_buffer.h"
#include "../details/null_mutex.h"
#include "./base_sink.h"
#include "base_sink.h"
namespace spdlog {
namespace sinks {
@@ -26,7 +26,7 @@ public:
explicit ringbuffer_sink(size_t n_items)
: q_{n_items} {}
void drain_raw(std::function<void(const details::log_msg_buffer &)> callback) {
void drain_raw(std::function<void(const details::async_log_msg &)> callback) {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
while (!q_.empty()) {
callback(q_.front());
@@ -46,11 +46,11 @@ public:
}
protected:
void sink_it_(const details::log_msg &msg) override { q_.push_back(details::log_msg_buffer{msg}); }
void sink_it_(const details::log_msg &msg) override { q_.push_back(details::async_log_msg{details::async_log_msg::type::log, msg}); }
void flush_() override {}
private:
details::circular_q<details::log_msg_buffer> q_;
details::circular_q<details::async_log_msg> q_;
};
using ringbuffer_sink_mt = ringbuffer_sink<std::mutex>;

View File

@@ -8,14 +8,12 @@
#include "../details/file_helper.h"
#include "../details/null_mutex.h"
#include "../details/synchronous_factory.h"
#include "./base_sink.h"
// Rotating file sink based on size
namespace spdlog {
namespace sinks {
//
// Rotating file sink based on size
//
template <typename Mutex>
class rotating_file_sink final : public base_sink<Mutex> {
public:
@@ -56,30 +54,4 @@ using rotating_file_sink_mt = rotating_file_sink<std::mutex>;
using rotating_file_sink_st = rotating_file_sink<details::null_mutex>;
} // namespace sinks
//
// factory functions
//
template <typename Factory = spdlog::synchronous_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,
bool rotate_on_open = false,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files, rotate_on_open,
event_handlers);
}
template <typename Factory = spdlog::synchronous_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,
bool rotate_on_open = false,
const file_event_handlers &event_handlers = {}) {
return Factory::template create<sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files, rotate_on_open,
event_handlers);
}
} // namespace spdlog

View File

@@ -16,9 +16,9 @@ public:
virtual void set_pattern(const std::string &pattern) = 0;
virtual void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) = 0;
void set_level(level level);
level log_level() const;
bool should_log(level msg_level) const;
void set_level(level level) { level_.store(level, std::memory_order_relaxed); }
level log_level() const { return level_.load(std::memory_order_relaxed);}
bool should_log(level msg_level) const {return msg_level >= level_.load(std::memory_order_relaxed);}
protected:
// sink log level - default is all

View File

@@ -9,9 +9,6 @@
#include "./ansicolor_sink.h"
#endif
#include "../async.h"
#include "../details/synchronous_factory.h"
namespace spdlog {
namespace sinks {
#ifdef _WIN32
@@ -25,19 +22,6 @@ using stdout_color_sink_st = ansicolor_stdout_sink_st;
using stderr_color_sink_mt = ansicolor_stderr_sink_mt;
using stderr_color_sink_st = ansicolor_stderr_sink_st;
#endif
} // namespace sinks
// logger factory functions
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic);
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic);
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic);
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic);
} // namespace spdlog

View File

@@ -4,9 +4,9 @@
#pragma once
#include <cstdio>
#include <mutex>
#include "../details/null_mutex.h"
#include "../details/synchronous_factory.h"
#include "./base_sink.h"
#include "./sink.h"
@@ -58,18 +58,4 @@ using stderr_sink_mt = stderr_sink<std::mutex>;
using stderr_sink_st = stderr_sink<details::null_mutex>;
} // namespace sinks
// factory methods
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name);
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name);
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name);
template <typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_logger_st(const std::string &logger_name);
} // namespace spdlog

View File

@@ -4,12 +4,12 @@
#pragma once
#include <spdlog/details/null_mutex.h>
#include <spdlog/details/synchronous_factory.h>
#include <spdlog/sinks/base_sink.h>
#include <syslog.h>
#include <array>
#include <string>
#include <mutex>
namespace spdlog {
namespace sinks {
@@ -19,7 +19,7 @@ namespace sinks {
template <typename Mutex>
class syslog_sink final : public base_sink<Mutex> {
public:
syslog_sink(std::string ident, int syslog_option, int syslog_facility, bool enable_formatting)
syslog_sink(std::string ident = "", int syslog_option = 0, int syslog_facility = LOG_USER, bool enable_formatting=false)
: enable_formatting_{enable_formatting},
syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG,
/* spdlog::level::debug */ LOG_DEBUG,
@@ -79,26 +79,6 @@ private:
using syslog_sink_mt = syslog_sink<std::mutex>;
using syslog_sink_st = syslog_sink<details::null_mutex>;
} // namespace sinks
// Create and register a syslog logger
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> syslog_logger_mt(const std::string &logger_name,
const std::string &syslog_ident = "",
int syslog_option = 0,
int syslog_facility = LOG_USER,
bool enable_formatting = false) {
return Factory::template create<sinks::syslog_sink_mt>(logger_name, syslog_ident, syslog_option, syslog_facility,
enable_formatting);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> syslog_logger_st(const std::string &logger_name,
const std::string &syslog_ident = "",
int syslog_option = 0,
int syslog_facility = LOG_USER,
bool enable_formatting = false) {
return Factory::template create<sinks::syslog_sink_st>(logger_name, syslog_ident, syslog_option, syslog_facility,
enable_formatting);
}
} // namespace spdlog

View File

@@ -7,7 +7,6 @@
#include "../details/null_mutex.h"
#include "../details/os.h"
#include "../details/synchronous_factory.h"
#include "./base_sink.h"
#ifndef SD_JOURNAL_SUPPRESS_LOCATION
#define SD_JOURNAL_SUPPRESS_LOCATION
@@ -90,20 +89,6 @@ protected:
using systemd_sink_mt = systemd_sink<std::mutex>;
using systemd_sink_st = systemd_sink<details::null_mutex>;
} // namespace sinks
// Create and register a syslog logger
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> systemd_logger_mt(const std::string &logger_name,
const std::string &ident = "",
bool enable_formatting = false) {
return Factory::template create<sinks::systemd_sink_mt>(logger_name, ident, enable_formatting);
}
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> systemd_logger_st(const std::string &logger_name,
const std::string &ident = "",
bool enable_formatting = false) {
return Factory::template create<sinks::systemd_sink_st>(logger_name, ident, enable_formatting);
}
} // namespace spdlog

View File

@@ -69,7 +69,7 @@ protected:
};
using tcp_sink_mt = tcp_sink<std::mutex>;
using tcp_sink_st = tcp_sink<spdlog::details::null_mutex>;
using tcp_sink_st = tcp_sink<details::null_mutex>;
} // namespace sinks
} // namespace spdlog

View File

@@ -33,7 +33,7 @@ struct udp_sink_config {
};
template <typename Mutex>
class udp_sink final : public spdlog::sinks::base_sink<Mutex> {
class udp_sink final : public base_sink<Mutex> {
public:
// host can be hostname or ip address
explicit udp_sink(udp_sink_config sink_config)
@@ -53,16 +53,7 @@ protected:
};
using udp_sink_mt = udp_sink<std::mutex>;
using udp_sink_st = udp_sink<spdlog::details::null_mutex>;
using udp_sink_st = udp_sink<details::null_mutex>;
} // namespace sinks
//
// factory functions
//
template <typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> udp_logger_mt(const std::string &logger_name, sinks::udp_sink_config skin_config) {
return Factory::template create<sinks::udp_sink_mt>(logger_name, skin_config);
}
} // namespace spdlog

View File

@@ -66,8 +66,8 @@ public:
using wincolor_stdout_sink_mt = wincolor_stdout_sink<std::mutex>;
using wincolor_stdout_sink_st = wincolor_stdout_sink<details::null_mutex>;
using wincolor_stderr_sink_mt = wincolor_stderr_sink<std::mutex>;
using wincolor_stderr_sink_st = wincolor_stderr_sink<details::null_mutex>;
} // namespace sinks
} // namespace spdlog

View File

@@ -14,24 +14,16 @@
#include <string_view>
#include "./common.h"
#include "./details/context.h"
#include "./details/synchronous_factory.h"
#include "./logger.h"
namespace spdlog {
using default_factory = synchronous_factory;
SPDLOG_API void set_context(std::shared_ptr<details::context> context);
SPDLOG_API std::shared_ptr<details::context> context();
SPDLOG_API const std::shared_ptr<details::context> &context_ref();
// Create a logger with a templated sink type
// Example:
// spdlog::create<daily_file_sink_st>("logger_name", "dailylog_filename", 11, 59);
template <typename Sink, typename... SinkArgs>
std::shared_ptr<logger> create(std::string logger_name, SinkArgs &&...sink_args) {
return default_factory::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...);
return std::make_shared<logger>(std::move(logger_name), std::make_shared<Sink>(std::forward<SinkArgs>(sink_args)...));
}
// Set formatter of the global logger. Each sink in each logger will get a clone of this object

View File

@@ -5,7 +5,7 @@
#include <chrono>
#include "fmt/fmt.h"
#include "fmt/base.h"
// Stopwatch support for spdlog (using std::chrono::steady_clock).
// Displays elapsed seconds since construction as double.