mirror of
https://github.com/gabime/spdlog.git
synced 2025-09-29 01:29:35 +08:00
@@ -1,79 +0,0 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#include "spdlog/async_logger.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "spdlog/details/thread_pool.h"
|
||||
#include "spdlog/sinks/sink.h"
|
||||
|
||||
spdlog::async_logger::async_logger(std::string logger_name,
|
||||
sinks_init_list sinks_list,
|
||||
std::weak_ptr<details::thread_pool> tp,
|
||||
async_overflow_policy overflow_policy)
|
||||
: async_logger(std::move(logger_name), sinks_list.begin(), sinks_list.end(), std::move(tp), overflow_policy) {}
|
||||
|
||||
spdlog::async_logger::async_logger(std::string logger_name,
|
||||
sink_ptr single_sink,
|
||||
std::weak_ptr<details::thread_pool> tp,
|
||||
async_overflow_policy overflow_policy)
|
||||
: async_logger(std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy) {}
|
||||
|
||||
// send the log message to the thread pool
|
||||
void spdlog::async_logger::sink_it_(const details::log_msg &msg) {
|
||||
try {
|
||||
if (auto pool_ptr = thread_pool_.lock()) {
|
||||
pool_ptr->post_log(shared_from_this(), msg, overflow_policy_);
|
||||
} else {
|
||||
throw_spdlog_ex("async log: thread pool doesn't exist anymore");
|
||||
}
|
||||
}
|
||||
SPDLOG_LOGGER_CATCH(msg.source)
|
||||
}
|
||||
|
||||
// send flush request to the thread pool
|
||||
void spdlog::async_logger::flush_() {
|
||||
try {
|
||||
if (auto pool_ptr = thread_pool_.lock()) {
|
||||
pool_ptr->post_flush(shared_from_this(), overflow_policy_);
|
||||
} else {
|
||||
throw_spdlog_ex("async flush: thread pool doesn't exist anymore");
|
||||
}
|
||||
}
|
||||
SPDLOG_LOGGER_CATCH(source_loc())
|
||||
}
|
||||
|
||||
//
|
||||
// backend functions - called from the thread pool to do the actual job
|
||||
//
|
||||
void spdlog::async_logger::backend_sink_it_(const details::log_msg &msg) {
|
||||
for (auto &sink : sinks_) {
|
||||
if (sink->should_log(msg.log_level)) {
|
||||
try {
|
||||
sink->log(msg);
|
||||
}
|
||||
SPDLOG_LOGGER_CATCH(msg.source)
|
||||
}
|
||||
}
|
||||
|
||||
if (should_flush_(msg)) {
|
||||
backend_flush_();
|
||||
}
|
||||
}
|
||||
|
||||
void spdlog::async_logger::backend_flush_() {
|
||||
for (auto &sink : sinks_) {
|
||||
try {
|
||||
sink->flush();
|
||||
}
|
||||
SPDLOG_LOGGER_CATCH(source_loc())
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<spdlog::logger> spdlog::async_logger::clone(std::string new_name) {
|
||||
auto cloned = std::make_shared<spdlog::async_logger>(*this);
|
||||
cloned->name_ = std::move(new_name);
|
||||
return cloned;
|
||||
}
|
61
src/details/async_log_msg.cpp
Normal file
61
src/details/async_log_msg.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#include "spdlog/details/async_log_msg.h"
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
|
||||
|
||||
async_log_msg::async_log_msg(const type type)
|
||||
: msg_type_{type} {}
|
||||
|
||||
// copy logger name and payload to buffer so can be used asynchronously
|
||||
// note: source location pointers are copied without allocation since they
|
||||
// are compiler generated const chars* (__FILE__, __LINE__, __FUNCTION__)
|
||||
// if you pass custom strings to source location, make sure they outlive the async_log_msg
|
||||
async_log_msg::async_log_msg(const type type, const log_msg &orig_msg)
|
||||
: log_msg{orig_msg}, msg_type_(type) {
|
||||
buffer_.append(logger_name);
|
||||
buffer_.append(payload);
|
||||
update_string_views();
|
||||
}
|
||||
|
||||
async_log_msg::async_log_msg(const async_log_msg &other)
|
||||
: log_msg{other}, msg_type_{other.msg_type_} {
|
||||
buffer_.append(logger_name);
|
||||
buffer_.append(payload);
|
||||
update_string_views();
|
||||
}
|
||||
|
||||
async_log_msg::async_log_msg(async_log_msg &&other) noexcept
|
||||
: log_msg{other}, msg_type_{other.msg_type_}, buffer_{std::move(other.buffer_)} {
|
||||
update_string_views();
|
||||
}
|
||||
|
||||
async_log_msg &async_log_msg::operator=(const async_log_msg &other) {
|
||||
if (this == &other) return *this;
|
||||
log_msg::operator=(other);
|
||||
msg_type_ = other.msg_type_;
|
||||
buffer_.clear();
|
||||
buffer_.append(other.buffer_.data(), other.buffer_.data() + other.buffer_.size());
|
||||
update_string_views();
|
||||
return *this;
|
||||
}
|
||||
|
||||
async_log_msg &async_log_msg::operator=(async_log_msg &&other) noexcept {
|
||||
if (this == &other) return *this;
|
||||
log_msg::operator=(other);
|
||||
msg_type_ = other.msg_type_;
|
||||
buffer_ = std::move(other.buffer_);
|
||||
update_string_views();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void async_log_msg::update_string_views() {
|
||||
logger_name = string_view_t{buffer_.data(), logger_name.size()};
|
||||
payload = string_view_t{buffer_.data() + logger_name.size(), payload.size()};
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
@@ -1,49 +0,0 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#include "spdlog/details/context.h"
|
||||
|
||||
#include "spdlog/logger.h"
|
||||
|
||||
#ifndef SPDLOG_DISABLE_GLOBAL_LOGGER
|
||||
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||
#endif // SPDLOG_DISABLE_GLOBAL_LOGGER
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
|
||||
context::context(std::unique_ptr<logger> global_logger) { global_logger_ = std::move(global_logger); }
|
||||
|
||||
std::shared_ptr<logger> context::global_logger() { return global_logger_; }
|
||||
|
||||
// Return raw ptr to the global logger.
|
||||
// To be used directly by the spdlog default api (e.g. spdlog::info)
|
||||
// This make the default 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.
|
||||
logger *context::global_logger_raw() const noexcept { return global_logger_.get(); }
|
||||
|
||||
// set global logger
|
||||
void context::set_logger(std::shared_ptr<logger> new_global_logger) { global_logger_ = std::move(new_global_logger); }
|
||||
|
||||
void context::set_tp(std::shared_ptr<thread_pool> tp) {
|
||||
std::lock_guard lock(tp_mutex_);
|
||||
tp_ = std::move(tp);
|
||||
}
|
||||
|
||||
std::shared_ptr<thread_pool> context::get_tp() {
|
||||
std::lock_guard lock(tp_mutex_);
|
||||
return tp_;
|
||||
}
|
||||
|
||||
// clean all resources and threads started by the registry
|
||||
void context::shutdown() {
|
||||
std::lock_guard lock(tp_mutex_);
|
||||
tp_.reset();
|
||||
}
|
||||
|
||||
std::recursive_mutex &context::tp_mutex() { return tp_mutex_; }
|
||||
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
40
src/details/err_helper.cpp
Normal file
40
src/details/err_helper.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#include "iostream"
|
||||
#include "spdlog/details/err_helper.h"
|
||||
#include "spdlog/details/os.h"
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
|
||||
// Prints error to stderr with source location (if available). A stderr sink is not used because reaching
|
||||
// this point might indicate a problem with the logging system itself so we use fputs() directly.
|
||||
void err_helper::handle_ex(const std::string &origin, const source_loc &loc, const std::exception &ex) const {
|
||||
if (custom_err_handler_) {
|
||||
custom_err_handler_(ex.what());
|
||||
return;
|
||||
}
|
||||
const auto tm_time = os::localtime();
|
||||
char date_buf[32];
|
||||
std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
|
||||
std::string msg;
|
||||
if (loc.empty()) {
|
||||
msg = fmt_lib::format("[*** LOG ERROR ***] [{}] [{}] {}\n", date_buf, origin, ex.what());
|
||||
} else {
|
||||
msg = fmt_lib::format("[*** LOG ERROR ***] [{}({})] [{}] [{}] {}\n", loc.filename, loc.line, date_buf, origin,
|
||||
ex.what());
|
||||
}
|
||||
std::fputs(msg.c_str(), stderr);
|
||||
}
|
||||
|
||||
void err_helper::handle_unknown_ex(const std::string &origin, const source_loc &loc) const {
|
||||
handle_ex(origin, loc, std::runtime_error("unknown exception"));
|
||||
}
|
||||
|
||||
void err_helper::set_err_handler(err_handler handler) {
|
||||
custom_err_handler_ = std::move(handler);
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
@@ -1,54 +0,0 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#include "spdlog/details/log_msg_buffer.h"
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
|
||||
// copy logger name and payload to buffer so can be used asynchronously
|
||||
// note: source location pointers are copied without allocation since they
|
||||
// are compiler generated const chars* (__FILE__, __LINE__, __FUNCTION__)
|
||||
// if you pass custom strings to source location, make sure they outlive the log_msg_buffer
|
||||
log_msg_buffer::log_msg_buffer(const log_msg &orig_msg)
|
||||
: log_msg{orig_msg} {
|
||||
buffer.append(logger_name);
|
||||
buffer.append(payload);
|
||||
update_string_views();
|
||||
}
|
||||
|
||||
log_msg_buffer::log_msg_buffer(const log_msg_buffer &other)
|
||||
: log_msg{other} {
|
||||
buffer.append(logger_name);
|
||||
buffer.append(payload);
|
||||
update_string_views();
|
||||
}
|
||||
|
||||
log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) noexcept
|
||||
: log_msg{other},
|
||||
buffer{std::move(other.buffer)} {
|
||||
update_string_views();
|
||||
}
|
||||
|
||||
log_msg_buffer &log_msg_buffer::operator=(const log_msg_buffer &other) {
|
||||
log_msg::operator=(other);
|
||||
buffer.clear();
|
||||
buffer.append(other.buffer.data(), other.buffer.data() + other.buffer.size());
|
||||
update_string_views();
|
||||
return *this;
|
||||
}
|
||||
|
||||
log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other) noexcept {
|
||||
log_msg::operator=(other);
|
||||
buffer = std::move(other.buffer);
|
||||
update_string_views();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void log_msg_buffer::update_string_views() {
|
||||
logger_name = string_view_t{buffer.data(), logger_name.size()};
|
||||
payload = string_view_t{buffer.data() + logger_name.size(), payload.size()};
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
@@ -1,117 +0,0 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#include "spdlog/details/thread_pool.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "spdlog/common.h"
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
|
||||
thread_pool::thread_pool(size_t q_max_items,
|
||||
size_t threads_n,
|
||||
std::function<void()> on_thread_start,
|
||||
std::function<void()> on_thread_stop)
|
||||
: q_(q_max_items) {
|
||||
if (threads_n == 0 || threads_n > 1000) {
|
||||
throw_spdlog_ex(
|
||||
"spdlog::thread_pool(): invalid threads_n param (valid "
|
||||
"range is 1-1000)");
|
||||
}
|
||||
for (size_t i = 0; i < threads_n; i++) {
|
||||
threads_.emplace_back([this, on_thread_start, on_thread_stop] {
|
||||
on_thread_start();
|
||||
this->thread_pool::worker_loop_();
|
||||
on_thread_stop();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
thread_pool::thread_pool(size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start)
|
||||
: thread_pool(q_max_items, threads_n, on_thread_start, [] {}) {}
|
||||
|
||||
thread_pool::thread_pool(size_t q_max_items, size_t threads_n)
|
||||
: thread_pool(q_max_items, threads_n, [] {}, [] {}) {}
|
||||
|
||||
// message all threads to terminate gracefully join them
|
||||
thread_pool::~thread_pool() {
|
||||
try {
|
||||
for (size_t i = 0; i < threads_.size(); i++) {
|
||||
post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block);
|
||||
}
|
||||
|
||||
for (auto &t : threads_) {
|
||||
t.join();
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
void thread_pool::post_log(async_logger_ptr &&worker_ptr, const details::log_msg &msg, async_overflow_policy overflow_policy) {
|
||||
async_msg async_m(std::move(worker_ptr), async_msg_type::log, msg);
|
||||
post_async_msg_(std::move(async_m), overflow_policy);
|
||||
}
|
||||
|
||||
void thread_pool::post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy) {
|
||||
post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy);
|
||||
}
|
||||
|
||||
size_t thread_pool::overrun_counter() { return q_.overrun_counter(); }
|
||||
|
||||
void thread_pool::reset_overrun_counter() { q_.reset_overrun_counter(); }
|
||||
|
||||
size_t thread_pool::discard_counter() { return q_.discard_counter(); }
|
||||
|
||||
void thread_pool::reset_discard_counter() { q_.reset_discard_counter(); }
|
||||
|
||||
size_t thread_pool::queue_size() { return q_.size(); }
|
||||
|
||||
void thread_pool::post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy) {
|
||||
if (overflow_policy == async_overflow_policy::block) {
|
||||
q_.enqueue(std::move(new_msg));
|
||||
} else if (overflow_policy == async_overflow_policy::overrun_oldest) {
|
||||
q_.enqueue_nowait(std::move(new_msg));
|
||||
} else {
|
||||
assert(overflow_policy == async_overflow_policy::discard_new);
|
||||
q_.enqueue_if_have_room(std::move(new_msg));
|
||||
}
|
||||
}
|
||||
|
||||
void thread_pool::worker_loop_() {
|
||||
while (process_next_msg_()) {
|
||||
}
|
||||
}
|
||||
|
||||
// process next message in the queue
|
||||
// return true if this thread should still be active (while no terminate msg
|
||||
// was received)
|
||||
bool thread_pool::process_next_msg_() {
|
||||
async_msg incoming_async_msg;
|
||||
q_.dequeue(incoming_async_msg);
|
||||
|
||||
switch (incoming_async_msg.msg_type) {
|
||||
case async_msg_type::log: {
|
||||
incoming_async_msg.worker_ptr->backend_sink_it_(incoming_async_msg);
|
||||
return true;
|
||||
}
|
||||
case async_msg_type::flush: {
|
||||
incoming_async_msg.worker_ptr->backend_flush_();
|
||||
return true;
|
||||
}
|
||||
|
||||
case async_msg_type::terminate: {
|
||||
return false;
|
||||
}
|
||||
|
||||
default: {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
@@ -3,9 +3,6 @@
|
||||
|
||||
#include "spdlog/logger.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <mutex>
|
||||
|
||||
#include "spdlog/pattern_formatter.h"
|
||||
#include "spdlog/sinks/sink.h"
|
||||
|
||||
@@ -17,14 +14,14 @@ logger::logger(const logger &other) noexcept
|
||||
sinks_(other.sinks_),
|
||||
level_(other.level_.load(std::memory_order_relaxed)),
|
||||
flush_level_(other.flush_level_.load(std::memory_order_relaxed)),
|
||||
custom_err_handler_(other.custom_err_handler_) {}
|
||||
err_helper_(other.err_helper_) {}
|
||||
|
||||
logger::logger(logger &&other) noexcept
|
||||
: name_(std::move(other.name_)),
|
||||
sinks_(std::move(other.sinks_)),
|
||||
level_(other.level_.load(std::memory_order_relaxed)),
|
||||
flush_level_(other.flush_level_.load(std::memory_order_relaxed)),
|
||||
custom_err_handler_(std::move(other.custom_err_handler_)) {}
|
||||
err_helper_(std::move(other.err_helper_)) {}
|
||||
|
||||
void logger::set_level(level level) { level_.store(level); }
|
||||
|
||||
@@ -62,8 +59,8 @@ const std::vector<sink_ptr> &logger::sinks() const { return sinks_; }
|
||||
|
||||
std::vector<sink_ptr> &logger::sinks() { return sinks_; }
|
||||
|
||||
// error handler
|
||||
void logger::set_error_handler(err_handler handler) { custom_err_handler_ = std::move(handler); }
|
||||
// custom error handler
|
||||
void logger::set_error_handler(err_handler handler) { err_helper_.set_err_handler(std::move(handler)); }
|
||||
|
||||
// create new logger with same sinks and configuration.
|
||||
std::shared_ptr<logger> logger::clone(std::string logger_name) {
|
||||
@@ -77,30 +74,17 @@ void logger::flush_() {
|
||||
for (auto &sink : sinks_) {
|
||||
try {
|
||||
sink->flush();
|
||||
} catch (const std::exception &ex) {
|
||||
err_helper_.handle_ex(name_, source_loc{}, ex);
|
||||
} catch (...) {
|
||||
err_helper_.handle_unknown_ex(name_, source_loc{});
|
||||
}
|
||||
SPDLOG_LOGGER_CATCH(source_loc())
|
||||
}
|
||||
}
|
||||
|
||||
bool logger::should_flush_(const details::log_msg &msg) const {
|
||||
auto flush_level = flush_level_.load(std::memory_order_relaxed);
|
||||
const auto flush_level = flush_level_.load(std::memory_order_relaxed);
|
||||
return (msg.log_level >= flush_level) && (msg.log_level != level::off);
|
||||
}
|
||||
|
||||
void logger::err_handler_(const std::string &msg) {
|
||||
if (custom_err_handler_) {
|
||||
custom_err_handler_(msg);
|
||||
} else {
|
||||
using std::chrono::system_clock;
|
||||
auto now = system_clock::now();
|
||||
auto tm_time = details::os::localtime(system_clock::to_time_t(now));
|
||||
char date_buf[64];
|
||||
std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
|
||||
#if defined(USING_R) && defined(R_R_H) // if in R environment
|
||||
REprintf("[*** LOG ERROR ***] [%s] [%s] %s\n", date_buf, name().c_str(), msg.c_str());
|
||||
#else
|
||||
std::fprintf(stderr, "[*** LOG ERROR ***] [%s] [%s] %s\n", date_buf, name().c_str(), msg.c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace spdlog
|
||||
|
@@ -16,7 +16,6 @@
|
||||
#include "spdlog/details/fmt_helper.h"
|
||||
#include "spdlog/details/log_msg.h"
|
||||
#include "spdlog/details/os.h"
|
||||
#include "spdlog/fmt/fmt.h"
|
||||
#include "spdlog/formatter.h"
|
||||
|
||||
namespace spdlog {
|
||||
|
@@ -5,7 +5,6 @@
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/details/os.h"
|
||||
#include "spdlog/pattern_formatter.h"
|
||||
|
||||
@@ -110,12 +109,13 @@ template <typename Mutex>
|
||||
ansicolor_stderr_sink<Mutex>::ansicolor_stderr_sink(color_mode mode)
|
||||
: ansicolor_sink<Mutex>(stderr, mode) {}
|
||||
|
||||
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
||||
|
||||
// template instantiations
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
template class SPDLOG_API spdlog::sinks::ansicolor_stdout_sink<std::mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::ansicolor_stdout_sink<spdlog::details::null_mutex>;
|
||||
|
||||
template class SPDLOG_API spdlog::sinks::ansicolor_stderr_sink<std::mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::ansicolor_stderr_sink<spdlog::details::null_mutex>;
|
||||
|
130
src/sinks/async_sink.cpp
Normal file
130
src/sinks/async_sink.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#include "spdlog/sinks/async_sink.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
#include "spdlog/common.h"
|
||||
#include "spdlog/details/mpmc_blocking_q.h"
|
||||
#include "spdlog/pattern_formatter.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
namespace spdlog {
|
||||
namespace sinks {
|
||||
|
||||
async_sink::async_sink(config async_config)
|
||||
: config_(std::move(async_config)) {
|
||||
if (config_.queue_size == 0 || config_.queue_size > max_queue_size) {
|
||||
throw spdlog_ex("async_sink: invalid queue size");
|
||||
}
|
||||
q_ = std::make_unique<queue_t>(config_.queue_size);
|
||||
worker_thread_ = std::thread([this] {
|
||||
if (config_.on_thread_start) config_.on_thread_start();
|
||||
this->backend_loop_();
|
||||
if (config_.on_thread_stop) config_.on_thread_stop();
|
||||
});
|
||||
}
|
||||
|
||||
async_sink::~async_sink() {
|
||||
try {
|
||||
q_->enqueue(async_log_msg(async_log_msg::type::terminate));
|
||||
worker_thread_.join();
|
||||
} catch (...) {
|
||||
printf("Exception in ~async_sink()\n");
|
||||
}
|
||||
}
|
||||
|
||||
void async_sink::log(const details::log_msg &msg) { send_message_(async_log_msg::type::log, msg); }
|
||||
|
||||
void async_sink::flush() { send_message_(async_log_msg::type::flush, details::log_msg()); }
|
||||
|
||||
void async_sink::set_pattern(const std::string &pattern) { set_formatter(std::make_unique<pattern_formatter>(pattern)); }
|
||||
|
||||
void async_sink::set_formatter(std::unique_ptr<formatter> formatter) {
|
||||
const auto &sinks = config_.sinks;
|
||||
for (auto it = sinks.begin(); it != sinks.end(); ++it) {
|
||||
if (std::next(it) == sinks.end()) {
|
||||
// last element - we can move it.
|
||||
(*it)->set_formatter(std::move(formatter));
|
||||
break; // to prevent clang-tidy warning
|
||||
}
|
||||
(*it)->set_formatter(formatter->clone());
|
||||
}
|
||||
}
|
||||
|
||||
size_t async_sink::get_overrun_counter() const { return q_->overrun_counter(); }
|
||||
|
||||
void async_sink::reset_overrun_counter() const { q_->reset_overrun_counter(); }
|
||||
|
||||
size_t async_sink::get_discard_counter() const { return q_->discard_counter(); }
|
||||
|
||||
void async_sink::reset_discard_counter() const { q_->reset_discard_counter(); }
|
||||
|
||||
const async_sink::config &async_sink::get_config() const { return config_; }
|
||||
|
||||
// private methods
|
||||
void async_sink::send_message_(async_log_msg::type msg_type, const details::log_msg &msg) const {
|
||||
switch (config_.policy) {
|
||||
case overflow_policy::block:
|
||||
q_->enqueue(async_log_msg(msg_type, msg));
|
||||
break;
|
||||
case overflow_policy::overrun_oldest:
|
||||
q_->enqueue_nowait(async_log_msg(msg_type, msg));
|
||||
break;
|
||||
case overflow_policy::discard_new:
|
||||
q_->enqueue_if_have_room(async_log_msg(msg_type, msg));
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
throw spdlog_ex("async_sink: invalid overflow policy");
|
||||
}
|
||||
}
|
||||
|
||||
void async_sink::backend_loop_() {
|
||||
details::async_log_msg incoming_msg;
|
||||
for (;;) {
|
||||
q_->dequeue(incoming_msg);
|
||||
switch (incoming_msg.message_type()) {
|
||||
case async_log_msg::type::log:
|
||||
backend_log_(incoming_msg);
|
||||
break;
|
||||
case async_log_msg::type::flush:
|
||||
backend_flush_();
|
||||
break;
|
||||
case async_log_msg::type::terminate:
|
||||
return;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void async_sink::backend_log_(const details::log_msg &msg) {
|
||||
for (const auto &sink : config_.sinks) {
|
||||
if (sink->should_log(msg.log_level)) {
|
||||
try {
|
||||
sink->log(msg);
|
||||
} catch (const std::exception &ex) {
|
||||
err_helper_.handle_ex("async log", msg.source, ex);
|
||||
} catch (...) {
|
||||
err_helper_.handle_unknown_ex("async log", source_loc{});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void async_sink::backend_flush_() {
|
||||
for (const auto &sink : config_.sinks) {
|
||||
try {
|
||||
sink->flush();
|
||||
} catch (const std::exception &ex) {
|
||||
err_helper_.handle_ex("async flush", source_loc{}, ex);
|
||||
} catch (...) {
|
||||
err_helper_.handle_unknown_ex("async flush", source_loc{});
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
@@ -5,53 +5,58 @@
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include "spdlog/common.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/pattern_formatter.h"
|
||||
|
||||
namespace spdlog {
|
||||
namespace sinks {
|
||||
|
||||
template <typename Mutex>
|
||||
spdlog::sinks::base_sink<Mutex>::base_sink()
|
||||
base_sink<Mutex>::base_sink()
|
||||
: formatter_{std::make_unique<spdlog::pattern_formatter>()} {}
|
||||
|
||||
template <typename Mutex>
|
||||
spdlog::sinks::base_sink<Mutex>::base_sink(std::unique_ptr<spdlog::formatter> formatter)
|
||||
base_sink<Mutex>::base_sink(std::unique_ptr<spdlog::formatter> formatter)
|
||||
: formatter_{std::move(formatter)} {}
|
||||
|
||||
template <typename Mutex>
|
||||
void spdlog::sinks::base_sink<Mutex>::log(const details::log_msg &msg) {
|
||||
void base_sink<Mutex>::log(const details::log_msg &msg) {
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
sink_it_(msg);
|
||||
}
|
||||
|
||||
template <typename Mutex>
|
||||
void spdlog::sinks::base_sink<Mutex>::flush() {
|
||||
void base_sink<Mutex>::flush() {
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
flush_();
|
||||
}
|
||||
|
||||
template <typename Mutex>
|
||||
void spdlog::sinks::base_sink<Mutex>::set_pattern(const std::string &pattern) {
|
||||
void base_sink<Mutex>::set_pattern(const std::string &pattern) {
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
set_pattern_(pattern);
|
||||
}
|
||||
|
||||
template <typename Mutex>
|
||||
void spdlog::sinks::base_sink<Mutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) {
|
||||
void base_sink<Mutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) {
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
set_formatter_(std::move(sink_formatter));
|
||||
}
|
||||
|
||||
template <typename Mutex>
|
||||
void spdlog::sinks::base_sink<Mutex>::set_pattern_(const std::string &pattern) {
|
||||
set_formatter_(std::make_unique<spdlog::pattern_formatter>(pattern));
|
||||
void base_sink<Mutex>::set_pattern_(const std::string &pattern) {
|
||||
set_formatter_(std::make_unique<pattern_formatter>(pattern));
|
||||
}
|
||||
|
||||
template <typename Mutex>
|
||||
void spdlog::sinks::base_sink<Mutex>::set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter) {
|
||||
void base_sink<Mutex>::set_formatter_(std::unique_ptr<formatter> sink_formatter) {
|
||||
formatter_ = std::move(sink_formatter);
|
||||
}
|
||||
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
||||
|
||||
// template instantiations
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
template class SPDLOG_API spdlog::sinks::base_sink<std::mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::base_sink<spdlog::details::null_mutex>;
|
||||
|
@@ -2,8 +2,8 @@
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#include "spdlog/sinks/basic_file_sink.h"
|
||||
|
||||
#include "spdlog/common.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace spdlog {
|
||||
namespace sinks {
|
||||
@@ -34,6 +34,8 @@ void basic_file_sink<Mutex>::flush_() {
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
||||
|
||||
|
||||
// template instantiations
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
template class SPDLOG_API spdlog::sinks::basic_file_sink<std::mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::basic_file_sink<spdlog::details::null_mutex>;
|
@@ -140,5 +140,6 @@ bool rotating_file_sink<Mutex>::rename_file_(const filename_t &src_filename, con
|
||||
} // namespace spdlog
|
||||
|
||||
// template instantiations
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
template class SPDLOG_API spdlog::sinks::rotating_file_sink<std::mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::rotating_file_sink<spdlog::details::null_mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::rotating_file_sink<spdlog::details::null_mutex>;
|
@@ -1,14 +0,0 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#include "spdlog/sinks/sink.h"
|
||||
|
||||
#include "spdlog/common.h"
|
||||
|
||||
bool spdlog::sinks::sink::should_log(spdlog::level msg_level) const {
|
||||
return msg_level >= level_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void spdlog::sinks::sink::set_level(level level) { level_.store(level, std::memory_order_relaxed); }
|
||||
|
||||
spdlog::level spdlog::sinks::sink::log_level() const { return level_.load(std::memory_order_relaxed); }
|
@@ -1,57 +0,0 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||
|
||||
#include "spdlog/async.h"
|
||||
#include "spdlog/common.h"
|
||||
#include "spdlog/details/synchronous_factory.h"
|
||||
#include "spdlog/logger.h"
|
||||
|
||||
namespace spdlog {
|
||||
|
||||
template <typename Factory>
|
||||
std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, color_mode mode) {
|
||||
return Factory::template create<sinks::stdout_color_sink_mt>(logger_name, mode);
|
||||
}
|
||||
|
||||
template <typename Factory>
|
||||
std::shared_ptr<logger> stdout_color_st(const std::string &logger_name, color_mode mode) {
|
||||
return Factory::template create<sinks::stdout_color_sink_st>(logger_name, mode);
|
||||
}
|
||||
|
||||
template <typename Factory>
|
||||
std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name, color_mode mode) {
|
||||
return Factory::template create<sinks::stderr_color_sink_mt>(logger_name, mode);
|
||||
}
|
||||
|
||||
template <typename Factory>
|
||||
std::shared_ptr<logger> stderr_color_st(const std::string &logger_name, color_mode mode) {
|
||||
return Factory::template create<sinks::stderr_color_sink_st>(logger_name, mode);
|
||||
}
|
||||
} // namespace spdlog
|
||||
|
||||
// template instantiations
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt<spdlog::synchronous_factory>(
|
||||
const std::string &logger_name, color_mode mode);
|
||||
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_color_st<spdlog::synchronous_factory>(
|
||||
const std::string &logger_name, color_mode mode);
|
||||
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt<spdlog::synchronous_factory>(
|
||||
const std::string &logger_name, color_mode mode);
|
||||
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_color_st<spdlog::synchronous_factory>(
|
||||
const std::string &logger_name, color_mode mode);
|
||||
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt<spdlog::async_factory>(const std::string &logger_name,
|
||||
color_mode mode);
|
||||
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_color_st<spdlog::async_factory>(const std::string &logger_name,
|
||||
color_mode mode);
|
||||
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt<spdlog::async_factory>(const std::string &logger_name,
|
||||
color_mode mode);
|
||||
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_color_st<spdlog::async_factory>(const std::string &logger_name,
|
||||
color_mode mode);
|
@@ -4,6 +4,7 @@
|
||||
#include "spdlog/sinks/stdout_sinks.h"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include "spdlog/details/os.h"
|
||||
#include "spdlog/pattern_formatter.h"
|
||||
@@ -82,55 +83,11 @@ stderr_sink<Mutex>::stderr_sink()
|
||||
: stdout_sink_base<Mutex>(stderr) {}
|
||||
|
||||
} // namespace sinks
|
||||
|
||||
// factory methods
|
||||
template <typename Factory>
|
||||
std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name) {
|
||||
return Factory::template create<sinks::stdout_sink_mt>(logger_name);
|
||||
}
|
||||
|
||||
template <typename Factory>
|
||||
std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name) {
|
||||
return Factory::template create<sinks::stdout_sink_st>(logger_name);
|
||||
}
|
||||
|
||||
template <typename Factory>
|
||||
std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name) {
|
||||
return Factory::template create<sinks::stderr_sink_mt>(logger_name);
|
||||
}
|
||||
|
||||
template <typename Factory>
|
||||
std::shared_ptr<logger> stderr_logger_st(const std::string &logger_name) {
|
||||
return Factory::template create<sinks::stderr_sink_st>(logger_name);
|
||||
}
|
||||
} // namespace spdlog
|
||||
|
||||
// template instantiations for stdout/stderr loggers
|
||||
template class SPDLOG_API spdlog::sinks::stdout_sink_base<std::mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::stdout_sink_base<spdlog::details::null_mutex>;
|
||||
// template instantiations
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
template class SPDLOG_API spdlog::sinks::stdout_sink<std::mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::stdout_sink<spdlog::details::null_mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::stderr_sink<std::mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::stderr_sink<spdlog::details::null_mutex>;
|
||||
|
||||
// template instantiations for stdout/stderr factory functions
|
||||
#include "spdlog/async.h"
|
||||
#include "spdlog/details/synchronous_factory.h"
|
||||
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt<spdlog::synchronous_factory>(
|
||||
const std::string &logger_name);
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st<spdlog::synchronous_factory>(
|
||||
const std::string &logger_name);
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt<spdlog::synchronous_factory>(
|
||||
const std::string &logger_name);
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st<spdlog::synchronous_factory>(
|
||||
const std::string &logger_name);
|
||||
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt<spdlog::async_factory>(
|
||||
const std::string &logger_name);
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st<spdlog::async_factory>(
|
||||
const std::string &logger_name);
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt<spdlog::async_factory>(
|
||||
const std::string &logger_name);
|
||||
template SPDLOG_API std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st<spdlog::async_factory>(
|
||||
const std::string &logger_name);
|
||||
template class SPDLOG_API spdlog::sinks::stderr_sink<spdlog::details::null_mutex>;
|
@@ -5,12 +5,10 @@
|
||||
#include "spdlog/details/windows_include.h"
|
||||
#include <wincon.h>
|
||||
#include <mutex>
|
||||
|
||||
// clang-format on
|
||||
|
||||
#include "spdlog/sinks/wincolor_sink.h"
|
||||
|
||||
#include "spdlog/common.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
|
||||
namespace spdlog {
|
||||
namespace sinks {
|
||||
@@ -132,15 +130,14 @@ wincolor_stdout_sink<Mutex>::wincolor_stdout_sink(color_mode mode)
|
||||
template <typename Mutex>
|
||||
wincolor_stderr_sink<Mutex>::wincolor_stderr_sink(color_mode mode)
|
||||
: wincolor_sink<Mutex>(::GetStdHandle(STD_ERROR_HANDLE), mode) {}
|
||||
|
||||
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
||||
|
||||
// template instantiations
|
||||
template class SPDLOG_API spdlog::sinks::wincolor_sink<std::mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::wincolor_sink<spdlog::details::null_mutex>;
|
||||
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
template class SPDLOG_API spdlog::sinks::wincolor_stdout_sink<std::mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::wincolor_stdout_sink<spdlog::details::null_mutex>;
|
||||
|
||||
template class SPDLOG_API spdlog::sinks::wincolor_stderr_sink<std::mutex>;
|
||||
template class SPDLOG_API spdlog::sinks::wincolor_stderr_sink<spdlog::details::null_mutex>;
|
||||
|
@@ -13,27 +13,20 @@
|
||||
|
||||
namespace spdlog {
|
||||
|
||||
static std::shared_ptr s_context =
|
||||
|
||||
#ifndef SPDLOG_DISABLE_GLOBAL_LOGGER
|
||||
std::make_unique<details::context>(std::make_unique<logger>(std::string(), std::make_unique<sinks::stdout_color_sink_mt>()));
|
||||
static std::shared_ptr<logger> s_logger = std::make_shared<logger>("global", std::make_shared<sinks::stdout_color_sink_mt>());
|
||||
#else
|
||||
std::make_unique<details::context>(); // empty context
|
||||
static std::short_ptr<logger> s_logger = nullptr;
|
||||
#endif
|
||||
|
||||
void set_context(std::shared_ptr<details::context> context) { s_context = std::move(context); }
|
||||
|
||||
std::shared_ptr<details::context> context() { return s_context; }
|
||||
std::shared_ptr<logger> global_logger() { return s_logger; }
|
||||
|
||||
const std::shared_ptr<details::context> &context_ref() { return s_context; }
|
||||
|
||||
std::shared_ptr<logger> global_logger() { return context_ref()->global_logger(); }
|
||||
|
||||
void set_global_logger(std::shared_ptr<logger> global_logger) { context()->set_logger(std::move(global_logger)); }
|
||||
void set_global_logger(std::shared_ptr<logger> global_logger) { s_logger = std::move(global_logger); }
|
||||
|
||||
logger *global_logger_raw() noexcept {
|
||||
auto *rv = context_ref()->global_logger_raw();
|
||||
assert(rv != nullptr);
|
||||
return rv;
|
||||
return s_logger.get();
|
||||
}
|
||||
|
||||
void set_formatter(std::unique_ptr<formatter> formatter) { global_logger()->set_formatter(std::move(formatter)); }
|
||||
@@ -52,6 +45,6 @@ void flush_on(level level) { global_logger()->flush_on(level); }
|
||||
|
||||
void set_error_handler(void (*handler)(const std::string &msg)) { global_logger()->set_error_handler(handler); }
|
||||
|
||||
void shutdown() { s_context.reset(); }
|
||||
void shutdown() { s_logger.reset(); }
|
||||
|
||||
} // namespace spdlog
|
||||
|
Reference in New Issue
Block a user