mirror of
https://github.com/gabime/spdlog.git
synced 2025-09-29 01:29:35 +08:00
@@ -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
|
@@ -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
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <cctype>
|
||||
|
||||
#include "../common.h"
|
||||
#include "common.h"
|
||||
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<version>)
|
@@ -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>;
|
||||
|
37
include/spdlog/details/async_log_msg.h
Normal file
37
include/spdlog/details/async_log_msg.h
Normal 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
|
@@ -7,8 +7,6 @@
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "spdlog/common.h"
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
template <typename T>
|
||||
|
@@ -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
|
23
include/spdlog/details/err_helper.h
Normal file
23
include/spdlog/details/err_helper.h
Normal 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
|
@@ -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 {
|
||||
|
@@ -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
|
@@ -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_);
|
||||
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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"
|
@@ -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
|
||||
|
@@ -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__
|
||||
|
@@ -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>;
|
||||
|
||||
|
86
include/spdlog/sinks/async_sink.h
Normal file
86
include/spdlog/sinks/async_sink.h
Normal 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
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -4,7 +4,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "../details/null_mutex.h"
|
||||
#include "./base_sink.h"
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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>;
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
Reference in New Issue
Block a user