// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) #pragma once #include #include #include #include "../details/async_log_msg.h" #include "../details/circular_q.h" #include "../details/null_mutex.h" #include "base_sink.h" namespace spdlog { namespace sinks { /* * Ring buffer sink. Holds fixed amount of log messages in memory. When the buffer is full, new * messages override the old ones. Useful for storing debug data in memory in case of error. * Example: auto rb_sink = std::make_shared(128); spdlog::logger * logger("rb_logger", rb_sink); rb->drain([](const std::string_view msg) { process(msg);}); */ template class ringbuffer_sink final : public base_sink { public: explicit ringbuffer_sink(size_t n_items) : q_{n_items} {} void drain_raw(std::function callback) { std::lock_guard lock(base_sink::mutex_); while (!q_.empty()) { callback(q_.front()); q_.pop_front(); } } void drain(std::function callback) { std::lock_guard lock(base_sink::mutex_); memory_buf_t formatted; while (!q_.empty()) { formatted.clear(); base_sink::formatter_->format(q_.front(), formatted); callback(std::string_view(formatted.data(), formatted.size())); q_.pop_front(); } } protected: 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 q_; }; using ringbuffer_sink_mt = ringbuffer_sink; using ringbuffer_sink_st = ringbuffer_sink; } // namespace sinks } // namespace spdlog