From 8079c85922396dc1f4c602c14dce6db938db859e Mon Sep 17 00:00:00 2001 From: seker <04070628@163.com> Date: Thu, 11 Nov 2021 00:08:24 +0800 Subject: [PATCH] add file event handlers --- example/example.cpp | 33 ++++++++++++++++--- include/spdlog/common.h | 8 +++++ include/spdlog/details/file_helper-inl.h | 18 ++++++++++ include/spdlog/details/file_helper.h | 4 ++- include/spdlog/sinks/basic_file_sink-inl.h | 3 +- include/spdlog/sinks/basic_file_sink.h | 10 +++--- include/spdlog/sinks/daily_file_sink.h | 19 ++++++----- include/spdlog/sinks/hourly_file_sink.h | 11 ++++--- include/spdlog/sinks/rotating_file_sink-inl.h | 3 +- include/spdlog/sinks/rotating_file_sink.h | 10 +++--- 10 files changed, 87 insertions(+), 32 deletions(-) diff --git a/example/example.cpp b/example/example.cpp index 3fbde21a..79a5bab0 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -26,9 +26,32 @@ void custom_flags_example(); #include "spdlog/spdlog.h" #include "spdlog/cfg/env.h" // support for loading levels from the environment variable #include "spdlog/fmt/ostr.h" // support for user defined types +#include "spdlog/common.h" + +spdlog::file_event_handlers_t file_event_handlers; + +void init_file_event_handler() +{ + file_event_handlers.after_open = [](spdlog::filename_t filename, std::FILE* fstream) + { + fputs("OPEN!\r\n", fstream); + spdlog::info("basic_example() : file_event_handlers.after_open : {}", filename.c_str()); + }; + file_event_handlers.before_close = [](spdlog::filename_t filename, std::FILE* fstream) + { + fputs("CLOSE!\r\n", fstream); + spdlog::info("basic_example() : file_event_handlers.before_close : {}", filename.c_str()); + }; + file_event_handlers.after_close = [](spdlog::filename_t filename) + { + spdlog::info("basic_example() : file_event_handlers.after_close : {}", filename.c_str()); + }; +} int main(int, char *[]) { + init_file_event_handler(); + // Log levels can be loaded from argv/env using "SPDLOG_LEVEL" load_levels_example(); @@ -113,21 +136,21 @@ void stdout_logger_example() void basic_example() { // Create basic file logger (not rotated). - auto my_logger = spdlog::basic_logger_mt("file_logger", "logs/basic-log.txt"); + auto my_logger = spdlog::basic_logger_mt("file_logger", "logs/basic-log.txt", false, file_event_handlers); } #include "spdlog/sinks/rotating_file_sink.h" void rotating_example() { // Create a file rotating logger with 5mb size max and 3 rotated files. - auto rotating_logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3); + auto rotating_logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3, false, file_event_handlers); } #include "spdlog/sinks/daily_file_sink.h" void daily_example() { // Create a daily logger - a new file is created every day on 2:30am. - auto daily_logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30); + auto daily_logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30, false, 0, file_event_handlers); } #include "spdlog/cfg/env.h" @@ -147,7 +170,7 @@ void async_example() { // Default thread pool settings can be modified *before* creating the async logger: // spdlog::init_thread_pool(32768, 1); // queue with max 32k items 1 backing thread. - auto async_file = spdlog::basic_logger_mt("async_file_logger", "logs/async_log.txt"); + auto async_file = spdlog::basic_logger_mt("async_file_logger", "logs/async_log.txt", false, file_event_handlers); // alternatively: // auto async_file = spdlog::create_async("async_file_logger", "logs/async_log.txt"); @@ -224,7 +247,7 @@ void multi_sink_example() console_sink->set_level(spdlog::level::warn); console_sink->set_pattern("[multi_sink_example] [%^%l%$] %v"); - auto file_sink = std::make_shared("logs/multisink.txt", true); + auto file_sink = std::make_shared("logs/multisink.txt", true, file_event_handlers); file_sink->set_level(spdlog::level::trace); spdlog::logger logger("multi_sink", {console_sink, file_sink}); diff --git a/include/spdlog/common.h b/include/spdlog/common.h index ed0ab46c..ddaa34ce 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef SPDLOG_COMPILED_LIB # undef SPDLOG_HEADER_ONLY @@ -255,6 +256,13 @@ struct source_loc const char *funcname{nullptr}; }; +typedef struct +{ + std::function after_open; + std::function before_close; + std::function after_close; +} file_event_handlers_t; + namespace details { // make_unique support for pre c++14 diff --git a/include/spdlog/details/file_helper-inl.h b/include/spdlog/details/file_helper-inl.h index ac7021a9..4c6a7aea 100644 --- a/include/spdlog/details/file_helper-inl.h +++ b/include/spdlog/details/file_helper-inl.h @@ -20,6 +20,10 @@ namespace spdlog { namespace details { +SPDLOG_INLINE file_helper::file_helper(file_event_handlers_t event_handlers) + : event_handlers_{std::move(event_handlers)} +{} + SPDLOG_INLINE file_helper::~file_helper() { close(); @@ -52,6 +56,10 @@ SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate) } if (!os::fopen_s(&fd_, fname, mode)) { + if (event_handlers_.after_open) + { + event_handlers_.after_open(filename_, fd_); + } return; } @@ -79,8 +87,18 @@ SPDLOG_INLINE void file_helper::close() { if (fd_ != nullptr) { + if (event_handlers_.before_close) + { + event_handlers_.before_close(filename_, fd_); + } + std::fclose(fd_); fd_ = nullptr; + + if (event_handlers_.after_close) + { + event_handlers_.after_close(filename_); + } } } diff --git a/include/spdlog/details/file_helper.h b/include/spdlog/details/file_helper.h index cfccaed2..e7d3cba7 100644 --- a/include/spdlog/details/file_helper.h +++ b/include/spdlog/details/file_helper.h @@ -16,7 +16,8 @@ namespace details { class SPDLOG_API file_helper { public: - explicit file_helper() = default; + file_helper() = default; + explicit file_helper(file_event_handlers_t event_handlers); file_helper(const file_helper &) = delete; file_helper &operator=(const file_helper &) = delete; @@ -50,6 +51,7 @@ private: const unsigned int open_interval_ = 10; std::FILE *fd_{nullptr}; filename_t filename_; + file_event_handlers_t event_handlers_{}; }; } // namespace details } // namespace spdlog diff --git a/include/spdlog/sinks/basic_file_sink-inl.h b/include/spdlog/sinks/basic_file_sink-inl.h index e903dd93..bcbe26d6 100644 --- a/include/spdlog/sinks/basic_file_sink-inl.h +++ b/include/spdlog/sinks/basic_file_sink-inl.h @@ -14,7 +14,8 @@ namespace spdlog { namespace sinks { template -SPDLOG_INLINE basic_file_sink::basic_file_sink(const filename_t &filename, bool truncate) +SPDLOG_INLINE basic_file_sink::basic_file_sink(const filename_t &filename, bool truncate, const file_event_handlers_t& event_handlers) + : file_helper_{std::move(event_handlers)} { file_helper_.open(filename, truncate); } diff --git a/include/spdlog/sinks/basic_file_sink.h b/include/spdlog/sinks/basic_file_sink.h index 047bc8ce..f2e35f6e 100644 --- a/include/spdlog/sinks/basic_file_sink.h +++ b/include/spdlog/sinks/basic_file_sink.h @@ -20,7 +20,7 @@ template class basic_file_sink final : public base_sink { public: - explicit basic_file_sink(const filename_t &filename, bool truncate = false); + explicit basic_file_sink(const filename_t &filename, bool truncate = false, const file_event_handlers_t& event_handlers = {}); const filename_t &filename() const; protected: @@ -40,15 +40,15 @@ using basic_file_sink_st = basic_file_sink; // factory functions // template -inline std::shared_ptr basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false) +inline std::shared_ptr basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers_t& event_handlers = {}) { - return Factory::template create(logger_name, filename, truncate); + return Factory::template create(logger_name, filename, truncate, event_handlers); } template -inline std::shared_ptr basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false) +inline std::shared_ptr basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers_t& event_handlers = {}) { - return Factory::template create(logger_name, filename, truncate); + return Factory::template create(logger_name, filename, truncate, event_handlers); } } // namespace spdlog diff --git a/include/spdlog/sinks/daily_file_sink.h b/include/spdlog/sinks/daily_file_sink.h index d6a09f6b..5b30e73c 100644 --- a/include/spdlog/sinks/daily_file_sink.h +++ b/include/spdlog/sinks/daily_file_sink.h @@ -68,10 +68,11 @@ class daily_file_sink final : public base_sink { public: // create daily file sink which rotates on given time - daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0) + daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0, const file_event_handlers_t& event_handlers = {}) : base_filename_(std::move(base_filename)) , rotation_h_(rotation_hour) , rotation_m_(rotation_minute) + , file_helper_{std::move(event_handlers)} , truncate_(truncate) , max_files_(max_files) , filenames_q_() @@ -214,29 +215,29 @@ using daily_file_format_sink_st = daily_file_sink inline std::shared_ptr 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 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_t& event_handlers = {}) { - return Factory::template create(logger_name, filename, hour, minute, truncate, max_files); + return Factory::template create(logger_name, filename, hour, minute, truncate, max_files, event_handlers); } template inline std::shared_ptr 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 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_t& event_handlers = {}) { - return Factory::template create(logger_name, filename, hour, minute, truncate, max_files); + return Factory::template create(logger_name, filename, hour, minute, truncate, max_files, event_handlers); } template inline std::shared_ptr 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 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_t& event_handlers = {}) { - return Factory::template create(logger_name, filename, hour, minute, truncate, max_files); + return Factory::template create(logger_name, filename, hour, minute, truncate, max_files, event_handlers); } template inline std::shared_ptr 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 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_t& event_handlers = {}) { - return Factory::template create(logger_name, filename, hour, minute, truncate, max_files); + return Factory::template create(logger_name, filename, hour, minute, truncate, max_files, event_handlers); } } // namespace spdlog diff --git a/include/spdlog/sinks/hourly_file_sink.h b/include/spdlog/sinks/hourly_file_sink.h index 815781d9..dfb23551 100644 --- a/include/spdlog/sinks/hourly_file_sink.h +++ b/include/spdlog/sinks/hourly_file_sink.h @@ -46,8 +46,9 @@ class hourly_file_sink final : public base_sink { public: // create hourly file sink which rotates on given time - hourly_file_sink(filename_t base_filename, bool truncate = false, uint16_t max_files = 0) + hourly_file_sink(filename_t base_filename, bool truncate = false, uint16_t max_files = 0, const file_event_handlers_t& event_handlers = {}) : base_filename_(std::move(base_filename)) + , file_helper_{std::move(event_handlers)} , truncate_(truncate) , max_files_(max_files) , filenames_q_() @@ -180,15 +181,15 @@ using hourly_file_sink_st = hourly_file_sink; // template inline std::shared_ptr hourly_logger_mt( - const std::string &logger_name, const filename_t &filename, bool truncate = false, uint16_t max_files = 0) + const std::string &logger_name, const filename_t &filename, bool truncate = false, uint16_t max_files = 0, const file_event_handlers_t& event_handlers = {}) { - return Factory::template create(logger_name, filename, truncate, max_files); + return Factory::template create(logger_name, filename, truncate, max_files, event_handlers); } template inline std::shared_ptr hourly_logger_st( - const std::string &logger_name, const filename_t &filename, bool truncate = false, uint16_t max_files = 0) + const std::string &logger_name, const filename_t &filename, bool truncate = false, uint16_t max_files = 0, const file_event_handlers_t& event_handlers = {}) { - return Factory::template create(logger_name, filename, truncate, max_files); + return Factory::template create(logger_name, filename, truncate, max_files, event_handlers); } } // namespace spdlog diff --git a/include/spdlog/sinks/rotating_file_sink-inl.h b/include/spdlog/sinks/rotating_file_sink-inl.h index f31f5319..fe2cd076 100644 --- a/include/spdlog/sinks/rotating_file_sink-inl.h +++ b/include/spdlog/sinks/rotating_file_sink-inl.h @@ -25,10 +25,11 @@ namespace sinks { template SPDLOG_INLINE rotating_file_sink::rotating_file_sink( - filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open) + filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open, const file_event_handlers_t& event_handlers) : base_filename_(std::move(base_filename)) , max_size_(max_size) , max_files_(max_files) + , file_helper_{std::move(event_handlers)} { file_helper_.open(calc_filename(base_filename_, 0)); current_size_ = file_helper_.size(); // expensive. called only once diff --git a/include/spdlog/sinks/rotating_file_sink.h b/include/spdlog/sinks/rotating_file_sink.h index 842527ef..304e9e20 100644 --- a/include/spdlog/sinks/rotating_file_sink.h +++ b/include/spdlog/sinks/rotating_file_sink.h @@ -22,7 +22,7 @@ template class rotating_file_sink final : public base_sink { public: - rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open = false); + rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open = false, const file_event_handlers_t& event_handlers = {}); static filename_t calc_filename(const filename_t &filename, std::size_t index); filename_t filename(); @@ -60,16 +60,16 @@ using rotating_file_sink_st = rotating_file_sink; template inline std::shared_ptr 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 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_t& event_handlers = {}) { - return Factory::template create(logger_name, filename, max_file_size, max_files, rotate_on_open); + return Factory::template create(logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); } template inline std::shared_ptr 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 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_t& event_handlers = {}) { - return Factory::template create(logger_name, filename, max_file_size, max_files, rotate_on_open); + return Factory::template create(logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); } } // namespace spdlog