customized rotation filename

pull/3296/head
hjiang 8 months ago
parent 24dde318fe
commit da9da9c9e7

@ -13,6 +13,7 @@
#include <spdlog/details/null_mutex.h>
#include <spdlog/fmt/fmt.h>
#include <cassert>
#include <cerrno>
#include <chrono>
#include <ctime>
@ -41,7 +42,7 @@ SPDLOG_INLINE rotating_file_sink<Mutex>::rotating_file_sink(
if (max_files > 200000) {
throw_spdlog_ex("rotating sink constructor: max_files arg cannot exceed 200000");
}
file_helper_.open(calc_filename(base_filename_, 0));
file_helper_.open(get_filename_for_rotation_(base_filename_, 0));
current_size_ = file_helper_.size(); // expensive. called only once
if (rotate_on_open && current_size_ > 0) {
rotate_();
@ -49,6 +50,20 @@ SPDLOG_INLINE rotating_file_sink<Mutex>::rotating_file_sink(
}
}
template <typename Mutex>
SPDLOG_INLINE void rotating_file_sink<Mutex>::set_rotate_filename_format(std::function<filename_t(const filename_t &filename, std::size_t index)> rotation_file_format) {
assert(!rotation_file_format_);
rotation_file_format_ = std::move(rotation_file_format);
}
template <typename Mutex>
SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::get_filename_for_rotation_(const filename_t &filename, std::size_t index) {
if (rotation_file_format_) {
return rotation_file_format_(filename, index);
}
return calc_filename(filename, index);
}
// calc filename according to index and file extension if exists.
// e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt".
template <typename Mutex>
@ -112,11 +127,11 @@ SPDLOG_INLINE void rotating_file_sink<Mutex>::rotate_() {
file_helper_.close();
for (auto i = max_files_; i > 0; --i) {
filename_t src = calc_filename(base_filename_, i - 1);
filename_t src = get_filename_for_rotation_(base_filename_, i - 1);
if (!path_exists(src)) {
continue;
}
filename_t target = calc_filename(base_filename_, i);
filename_t target = get_filename_for_rotation_(base_filename_, i);
if (!rename_file_(src, target)) {
// if failed try again after a small delay.

@ -9,6 +9,7 @@
#include <spdlog/sinks/base_sink.h>
#include <chrono>
#include <functional>
#include <mutex>
#include <string>
@ -26,10 +27,17 @@ public:
std::size_t max_files,
bool rotate_on_open = false,
const file_event_handlers &event_handlers = {});
// Default function to get rotation filename by base filename and rotation file index.
static filename_t calc_filename(const filename_t &filename, std::size_t index);
filename_t filename();
void rotate_now();
// Set the file format for rotation files.
// NOTE:
// 1. The format function is supposed to be called only once, otherwise check failure.
// 2. If [index] is 0, [filename] is expected to return.
void set_rotate_filename_format(std::function<filename_t(const filename_t &filename, std::size_t index)> rotation_file_format);
protected:
void sink_it_(const details::log_msg &msg) override;
void flush_() override;
@ -46,11 +54,15 @@ private:
// return true on success, false otherwise.
bool rename_file_(const filename_t &src_filename, const filename_t &target_filename);
// A wrapper around rotation filename format function(s).
filename_t get_filename_for_rotation_(const filename_t &filename, std::size_t index);
filename_t base_filename_;
std::size_t max_size_;
std::size_t max_files_;
std::size_t current_size_;
details::file_helper file_helper_;
std::function<filename_t(const filename_t &filename, std::size_t index)> rotation_file_format_;
};
using rotating_file_sink_mt = rotating_file_sink<std::mutex>;

@ -141,3 +141,30 @@ TEST_CASE("rotating_file_logger4", "[rotating_logger]") {
REQUIRE(get_filesize(ROTATING_LOG) > 0);
REQUIRE(get_filesize(ROTATING_LOG ".1") > 0);
}
// Test customized rotation filename.
TEST_CASE("rotating_file_logger5", "[rotating_logger]") {
prepare_logdir();
size_t max_size = 1024 * 10;
spdlog::filename_t basename = SPDLOG_FILENAME_T(ROTATING_LOG);
auto sink = std::make_shared<spdlog::sinks::rotating_file_sink_st>(basename, max_size, 2);
sink->set_rotate_filename_format([](const spdlog::filename_t &filename, std::size_t index) {
if (index == 0u) {
return filename;
}
const auto old_fname = spdlog::sinks::rotating_file_sink_st::calc_filename(filename, index);
return old_fname + ".test_suffix";
});
auto logger = std::make_shared<spdlog::logger>("rotating_sink_logger", sink);
logger->info("Test message - pre-rotation");
logger->flush();
sink->rotate_now();
logger->info("Test message - post-rotation");
logger->flush();
REQUIRE(get_filesize(ROTATING_LOG) > 0);
REQUIRE(get_filesize(ROTATING_LOG ".1.test_suffix") > 0);
}

Loading…
Cancel
Save