Added callback to rotating_file_sink

Callback can be used for compressing rotated file
pull/1693/head
Dilshod Mukhtarov 5 years ago
parent cbe9448650
commit 1bf4ca6928
No known key found for this signature in database
GPG Key ID: 61D0DE82722F1ACE

@ -30,12 +30,36 @@ SPDLOG_INLINE rotating_file_sink<Mutex>::rotating_file_sink(
, max_size_(max_size)
, max_files_(max_files)
{
file_helper_.open(calc_filename(base_filename_, 0));
current_size_ = file_helper_.size(); // expensive. called only once
init();
if (rotate_on_open && current_size_ > 0)
{
rotate_();
}
}
template<typename Mutex>
SPDLOG_INLINE rotating_file_sink<Mutex>::rotating_file_sink(
filename_t base_filename, std::size_t max_size, std::size_t max_files,
filename_t compress_extension, std::function<void(filename_t)> compress_callback, bool rotate_on_open)
: base_filename_(std::move(base_filename))
, max_size_(max_size)
, max_files_(max_files)
, compress_extension_(std::move(compress_extension))
, compress_callback_(std::move(compress_callback))
{
init();
if (rotate_on_open && current_size_ > 0)
{
rotate_();
call_compressor_callback();
}
}
template<typename Mutex>
SPDLOG_INLINE void rotating_file_sink<Mutex>::init()
{
file_helper_.open(calc_filename(base_filename_, 0));
current_size_ = file_helper_.size(); // expensive. called only once
}
// calc filename according to index and file extension if exists.
@ -66,12 +90,18 @@ SPDLOG_INLINE void rotating_file_sink<Mutex>::sink_it_(const details::log_msg &m
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
current_size_ += formatted.size();
if (current_size_ > max_size_)
const bool needRotation = (current_size_ > max_size_);
if (needRotation)
{
rotate_();
current_size_ = formatted.size();
}
file_helper_.write(formatted);
if (needRotation)
{
call_compressor_callback();
}
}
template<typename Mutex>
@ -94,11 +124,19 @@ SPDLOG_INLINE void rotating_file_sink<Mutex>::rotate_()
for (auto i = max_files_; i > 0; --i)
{
filename_t src = calc_filename(base_filename_, i - 1);
filename_t target = calc_filename(base_filename_, i);
if (!path_exists(src))
{
src.append(compress_extension_);
if (!path_exists(src))
{
continue;
}
filename_t target = calc_filename(base_filename_, i);
else
{
target.append(compress_extension_);
}
}
if (!rename_file_(src, target))
{
@ -127,5 +165,24 @@ SPDLOG_INLINE bool rotating_file_sink<Mutex>::rename_file_(const filename_t &src
return details::os::rename(src_filename, target_filename) == 0;
}
template<typename Mutex>
SPDLOG_INLINE void rotating_file_sink<Mutex>::call_compressor_callback()
{
if (!compress_callback_)
return;
using details::os::path_exists;
if (max_files_ > 0)
{
// target is log.1.txt
filename_t target = calc_filename(base_filename_, 1);
if (path_exists(target))
{
// this file has to be compressed
compress_callback_(target);
}
}
}
} // namespace sinks
} // namespace spdlog

@ -11,6 +11,7 @@
#include <chrono>
#include <mutex>
#include <string>
#include <functional>
namespace spdlog {
namespace sinks {
@ -23,6 +24,8 @@ class rotating_file_sink final : public base_sink<Mutex>
{
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,
filename_t compress_extension, std::function<void(filename_t)> compress_callback, bool rotate_on_open = false);
static filename_t calc_filename(const filename_t &filename, std::size_t index);
filename_t filename();
@ -42,11 +45,19 @@ private:
// return true on success, false otherwise.
bool rename_file_(const filename_t &src_filename, const filename_t &target_filename);
// runs given compress_
void call_compressor_callback();
// Common init called from constructor
void init();
filename_t base_filename_;
std::size_t max_size_;
std::size_t max_files_;
std::size_t current_size_;
details::file_helper file_helper_;
filename_t compress_extension_;
std::function<void(filename_t)> compress_callback_;
};
using rotating_file_sink_mt = rotating_file_sink<std::mutex>;
@ -65,12 +76,30 @@ inline std::shared_ptr<logger> rotating_logger_mt(
return Factory::template create<sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files, rotate_on_open);
}
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,
const filename_t &compress_extension, std::function<void(filename_t)> compress_callback, bool rotate_on_open = false)
{
return Factory::template create<sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files,
compress_extension, std::move(compress_callback), rotate_on_open);
}
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)
{
return Factory::template create<sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files, rotate_on_open);
}
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,
const filename_t &compress_extension, std::function<void(filename_t)> compress_callback, bool rotate_on_open = false)
{
return Factory::template create<sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files,
compress_extension, std::move(compress_callback), rotate_on_open);
}
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY

@ -96,3 +96,58 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
auto filename1 = basename + ".1";
REQUIRE(get_filesize(filename1) <= max_size);
}
TEST_CASE("rotating_file_logger_compress_callback", "[rotating_logger]]")
{
prepare_logdir();
size_t max_size = 1024 * 10;
std::string basename = "test_logs/rotating_log";
std::string ext = ".txt";
std::string logfilename = basename + ext;
std::string compress_ext = ".gz";
auto callback = [=](spdlog::filename_t filename){
// Here could be gzip filename which will rename it to filename.gz
rename(filename.c_str(), std::string(filename + compress_ext).c_str());
};
{
// make an initial logger to create the first output file
auto logger = spdlog::rotating_logger_mt("logger", logfilename, max_size, 2,
compress_ext, callback, true);
for (int i = 0; i < 10; ++i)
{
logger->info("Test message {}", i);
}
// drop causes the logger destructor to be called, which is required so the
// next logger can rename the first output file.
spdlog::drop(logger->name());
}
auto logger = spdlog::rotating_logger_mt("logger", logfilename, max_size, 2,
compress_ext, callback, true);
for (int i = 0; i < 10; ++i)
{
logger->info("Test message {}", i);
}
logger->flush();
require_message_count(logfilename, 10);
for (int i = 0; i < 1024; i++)
{
logger->info("Test message {}", i);
}
logger->flush();
REQUIRE(get_filesize(logfilename) <= max_size);
// test_logs/rotating_log.1.txt.gz
auto filename1 = basename + ".1" + ext + compress_ext;
REQUIRE(get_filesize(filename1) <= max_size);
// test_logs/rotating_log.2.txt.gz
auto filename2 = basename + ".2" + ext + compress_ext;
REQUIRE(get_filesize(filename2) <= max_size);
}

Loading…
Cancel
Save