Fix dup filter
This commit is contained in:
		@@ -7,24 +7,30 @@
 | 
				
			|||||||
#include "spdlog/details/null_mutex.h"
 | 
					#include "spdlog/details/null_mutex.h"
 | 
				
			||||||
#include "spdlog/details/log_msg.h"
 | 
					#include "spdlog/details/log_msg.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <mutex>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <chrono>
 | 
					#include <chrono>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Duplicate remove sink.
 | 
					// Duplicate message removal sink.
 | 
				
			||||||
// Filter the message if previous one is identical and less than max max_skip_duration have passed
 | 
					// Skip the message if previous one is identical and less than "max_skip_duration" have passed
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Example:
 | 
					// Example:
 | 
				
			||||||
//     auto d = std::make_shared<dup_filter_sink_st>(std::chrono::seconds(5));
 | 
					//
 | 
				
			||||||
//     d->add_sink(std::make_shared<stdout_color_sink_mt>());
 | 
					//     #include "spdlog/sinks/dup_filter_sink.h"
 | 
				
			||||||
//     spdlog::logger l("logger", d);
 | 
					//
 | 
				
			||||||
 | 
					//     int main() {
 | 
				
			||||||
 | 
					//         auto dup_filter = std::make_shared<dup_filter_sink_st>(std::chrono::seconds(5));
 | 
				
			||||||
 | 
					//         dup_filter->add_sink(std::make_shared<stdout_color_sink_mt>());
 | 
				
			||||||
 | 
					//         spdlog::logger l("logger", dup_filter);
 | 
				
			||||||
//         l.info("Hello");
 | 
					//         l.info("Hello");
 | 
				
			||||||
//         l.info("Hello");
 | 
					//         l.info("Hello");
 | 
				
			||||||
//         l.info("Hello");
 | 
					//         l.info("Hello");
 | 
				
			||||||
//         l.info("Different Hello");
 | 
					//         l.info("Different Hello");
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Will produce:
 | 
					// Will produce:
 | 
				
			||||||
//       [2019-06-25 17:50:56.511] [logger] [info] Hello
 | 
					//       [2019-06-25 17:50:56.511] [logger] [info] Hello
 | 
				
			||||||
//       [2019-06-25 17:50:56.512] [logger] [info] 3 duplicate messages..
 | 
					//       [2019-06-25 17:50:56.512] [logger] [info] Skipped 3 duplicate messages..
 | 
				
			||||||
//       [2019-06-25 17:50:56.512] [logger] [info] Different Hello
 | 
					//       [2019-06-25 17:50:56.512] [logger] [info] Different Hello
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -36,54 +42,51 @@ class dup_filter_sink : public dist_sink<Mutex>
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    template<class Rep, class Period>
 | 
					    template<class Rep, class Period>
 | 
				
			||||||
    explicit dup_filter_sink(std::chrono::duration<Rep, Period> max_ignore_duration)
 | 
					    explicit dup_filter_sink(std::chrono::duration<Rep, Period> max_skip_duration)
 | 
				
			||||||
        : max_skip_duration_{max_ignore_duration}
 | 
					        : max_skip_duration_{max_skip_duration}
 | 
				
			||||||
        , last_msg_time_{log_clock::now()}
 | 
					 | 
				
			||||||
        , skip_counter_{0}
 | 
					 | 
				
			||||||
    {}
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
    std::chrono::microseconds max_skip_duration_;
 | 
					    std::chrono::microseconds max_skip_duration_;
 | 
				
			||||||
    log_clock::time_point last_msg_time_;
 | 
					    log_clock::time_point last_msg_time_;
 | 
				
			||||||
    size_t skip_counter_;
 | 
					 | 
				
			||||||
    std::string last_msg_payload_;
 | 
					    std::string last_msg_payload_;
 | 
				
			||||||
 | 
					    size_t skip_counter_ = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void sink_it_(const details::log_msg &msg) override
 | 
					    void sink_it_(const details::log_msg &msg) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto msg_time = msg.time;
 | 
					        bool filtered = filter_(msg);
 | 
				
			||||||
        auto delta_time = msg_time - last_msg_time_;
 | 
					        if(!filtered)
 | 
				
			||||||
        last_msg_time_ = msg_time;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (delta_time < max_skip_duration_ && last_msg_payload_ == msg.payload)
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            skip_counter_++;
 | 
					            skip_counter_ += 1;
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // got different message from the previous
 | 
					        // log the "skipped.." message
 | 
				
			||||||
        if (skip_counter_ > 0)
 | 
					        if(skip_counter_ > 0)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            fmt::basic_memory_buffer<char, 80> buf;
 | 
					            fmt::basic_memory_buffer<char, 64> buf;
 | 
				
			||||||
            fmt::format_to(buf, "{} duplicate messages..", skip_counter_);
 | 
					            fmt::format_to(buf, "Skipped {} duplicate messages..", skip_counter_);
 | 
				
			||||||
            details::log_msg skipped_msg{msg.logger_name, msg.level, string_view_t{buf.data(), buf.size()}};
 | 
					            details::log_msg skipped_msg{msg.logger_name, msg.level, string_view_t{buf.data(), buf.size()}};
 | 
				
			||||||
 | 
					            dist_sink<Mutex>::sink_it_(skipped_msg);
 | 
				
			||||||
            // log the skip notification
 | 
					 | 
				
			||||||
            for (auto &sink : dist_sink<Mutex>::sinks_)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (sink->should_log(msg.level))
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    sink->log(skipped_msg);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            skip_counter_ = 0;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        last_msg_payload_.assign(msg.payload.data(), msg.payload.data() + msg.payload.size());
 | 
					        // log current message
 | 
				
			||||||
        dist_sink<Mutex>::sink_it_(msg);
 | 
					        dist_sink<Mutex>::sink_it_(msg);
 | 
				
			||||||
 | 
					        last_msg_time_= msg.time;
 | 
				
			||||||
 | 
					        skip_counter_ = 0;
 | 
				
			||||||
 | 
					        last_msg_payload_.assign(msg.payload.data(), msg.payload.data() + msg.payload.size());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // return whether the log msg should be displayed (true) or skipped (false)
 | 
				
			||||||
 | 
					    bool filter_(const details::log_msg &msg)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto filter_duration = msg.time - last_msg_time_;
 | 
				
			||||||
 | 
					        return (filter_duration  > max_skip_duration_) || (msg.payload != last_msg_payload_);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using dup_filter_sink_mt = dup_filter_sink<std::mutex>;
 | 
					using dup_filter_sink_mt = dup_filter_sink<std::mutex>;
 | 
				
			||||||
using dup_filter_sink_st = dup_filter_sink<details::null_mutex>;
 | 
					using dup_filter_sink_st = dup_filter_sink<details::null_mutex>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace sinks
 | 
					} // namespace sinks
 | 
				
			||||||
} // namespace spdlog
 | 
					} // namespace spdlog
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user