rotating file logger callback

pull/489/head
Asit Kumar Dhal 8 years ago
parent 5ed426980b
commit ca54771393

@ -67,6 +67,9 @@ using level_t = std::atomic<int>;
using log_err_handler = std::function<void(const std::string &err_msg)>; using log_err_handler = std::function<void(const std::string &err_msg)>;
using rotating_logger_cb = std::function<void(std::vector<std::string>)>;
using daily_logger_cb = std::function<void(std::string)>;
//Log level enum //Log level enum
namespace level namespace level
{ {

@ -59,25 +59,25 @@ inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_st(const std::string
} }
// Create multi/single threaded rotating file logger // Create multi/single threaded rotating file logger
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files) inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files, rotating_logger_cb cb /*= nullptr*/)
{ {
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files); return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files, cb);
} }
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files) inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files, rotating_logger_cb cb /*= nullptr*/)
{ {
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files); return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files, cb);
} }
// Create file logger which creates new file at midnight): // Create file logger which creates new file at midnight):
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour, int minute) inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour, int minute, daily_logger_cb cb /*= nullptr*/)
{ {
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, hour, minute); return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, cb);
} }
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute) inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute, daily_logger_cb cb /*= nullptr*/)
{ {
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, hour, minute); return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, hour, minute, cb);
} }

@ -66,12 +66,13 @@ class rotating_file_sink SPDLOG_FINAL : public base_sink < Mutex >
{ {
public: public:
rotating_file_sink(const filename_t &base_filename, rotating_file_sink(const filename_t &base_filename,
std::size_t max_size, std::size_t max_files) : std::size_t max_size, std::size_t max_files, rotating_logger_cb cb) :
_base_filename(base_filename), _base_filename(base_filename),
_max_size(max_size), _max_size(max_size),
_max_files(max_files), _max_files(max_files),
_current_size(0), _current_size(0),
_file_helper() _file_helper(),
_on_finish_cb(cb)
{ {
_file_helper.open(calc_filename(_base_filename, 0)); _file_helper.open(calc_filename(_base_filename, 0));
_current_size = _file_helper.size(); //expensive. called only once _current_size = _file_helper.size(); //expensive. called only once
@ -115,7 +116,10 @@ private:
void _rotate() void _rotate()
{ {
using details::os::filename_to_str; using details::os::filename_to_str;
std::vector<filename_t> files;
_file_helper.close(); _file_helper.close();
for (auto i = _max_files; i > 0; --i) for (auto i = _max_files; i > 0; --i)
{ {
filename_t src = calc_filename(_base_filename, i - 1); filename_t src = calc_filename(_base_filename, i - 1);
@ -128,18 +132,31 @@ private:
throw spdlog_ex("rotating_file_sink: failed removing " + filename_to_str(target), errno); throw spdlog_ex("rotating_file_sink: failed removing " + filename_to_str(target), errno);
} }
} }
if (details::file_helper::file_exists(src) && details::os::rename(src, target)) if (details::file_helper::file_exists(src))
{
if (details::os::rename(src, target))
{ {
throw spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno); throw spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno);
} }
if (_on_finish_cb)
{
files.push_back(target);
}
}
} }
_file_helper.reopen(true); _file_helper.reopen(true);
if (_on_finish_cb)
{
_on_finish_cb(files);
}
} }
filename_t _base_filename; filename_t _base_filename;
std::size_t _max_size; std::size_t _max_size;
std::size_t _max_files; std::size_t _max_files;
std::size_t _current_size; std::size_t _current_size;
details::file_helper _file_helper; details::file_helper _file_helper;
rotating_logger_cb _on_finish_cb;
}; };
typedef rotating_file_sink<std::mutex> rotating_file_sink_mt; typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
@ -186,9 +203,11 @@ public:
daily_file_sink( daily_file_sink(
const filename_t& base_filename, const filename_t& base_filename,
int rotation_hour, int rotation_hour,
int rotation_minute) : _base_filename(base_filename), int rotation_minute,
daily_logger_cb cb) : _base_filename(base_filename),
_rotation_h(rotation_hour), _rotation_h(rotation_hour),
_rotation_m(rotation_minute) _rotation_m(rotation_minute),
_daily_cb(cb)
{ {
if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59) if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor"); throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
@ -202,8 +221,13 @@ protected:
{ {
if (std::chrono::system_clock::now() >= _rotation_tp) if (std::chrono::system_clock::now() >= _rotation_tp)
{ {
auto old_file_name = _file_helper.filename();
_file_helper.open(FileNameCalc::calc_filename(_base_filename)); _file_helper.open(FileNameCalc::calc_filename(_base_filename));
_rotation_tp = _next_rotation_tp(); _rotation_tp = _next_rotation_tp();
if (_daily_cb)
{
_daily_cb(old_file_name);
}
} }
_file_helper.write(msg); _file_helper.write(msg);
} }
@ -234,6 +258,7 @@ private:
int _rotation_m; int _rotation_m;
std::chrono::system_clock::time_point _rotation_tp; std::chrono::system_clock::time_point _rotation_tp;
details::file_helper _file_helper; details::file_helper _file_helper;
daily_logger_cb _daily_cb;
}; };
typedef daily_file_sink<std::mutex> daily_file_sink_mt; typedef daily_file_sink<std::mutex> daily_file_sink_mt;

@ -77,14 +77,14 @@ std::shared_ptr<logger> basic_logger_st(const std::string& logger_name, const fi
// //
// Create and register multi/single threaded rotating file logger // Create and register multi/single threaded rotating file logger
// //
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); 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, rotating_logger_cb cb = nullptr);
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); 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, rotating_logger_cb cb = nullptr);
// //
// Create file logger which creates new file on the given time (default in midnight): // Create file logger which creates new file on the given time (default in midnight):
// //
std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0); std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0, daily_logger_cb cb = nullptr);
std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0); std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0, daily_logger_cb cb = nullptr);
// //
// Create and register stdout/stderr loggers // Create and register stdout/stderr loggers

@ -75,6 +75,31 @@ TEST_CASE("rotating_file_logger2", "[rotating_logger]]")
REQUIRE(get_filesize(filename1) <= 1024); REQUIRE(get_filesize(filename1) <= 1024);
} }
TEST_CASE("rotating_file_logger_cb", "[rotating_logger]]")
{
return;
prepare_logdir();
std::string basename = "logs/rotating_log_cb";
std::vector<std::string> file_names;
auto cb_fun = [&file_names](std::vector<std::string> _file_names) mutable
{
file_names = _file_names;
};
auto logger = spdlog::rotating_logger_mt("logger", basename, 120, 3, cb_fun);
for (int i = 0; i < 100; ++i)
logger->info("0123456789");
logger->flush();
REQUIRE(file_names.size() == 3);
REQUIRE(get_filesize(basename) <= 120);
for (auto i = 1; i < 3; i++)
{
auto filename1 = basename + "." + std::to_string(i);
REQUIRE(get_filesize(filename1) <= 120);
}
}
TEST_CASE("daily_logger", "[daily_logger]]") TEST_CASE("daily_logger", "[daily_logger]]")
{ {
@ -108,7 +133,7 @@ TEST_CASE("daily_logger with dateonly calculator", "[daily_logger_dateonly]]")
fmt::MemoryWriter w; fmt::MemoryWriter w;
w.write("{}_{:04d}-{:02d}-{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); w.write("{}_{:04d}-{:02d}-{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
auto logger = spdlog::create<sink_type>("logger", basename, 0, 0); auto logger = spdlog::create<sink_type>("logger", basename, 0, 0, nullptr);
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
logger->info("Test message {}", i); logger->info("Test message {}", i);
logger->flush(); logger->flush();
@ -140,7 +165,7 @@ TEST_CASE("daily_logger with custom calculator", "[daily_logger_custom]]")
fmt::MemoryWriter w; fmt::MemoryWriter w;
w.write("{}{:04d}{:02d}{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); w.write("{}{:04d}{:02d}{:02d}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
auto logger = spdlog::create<sink_type>("logger", basename, 0, 0); auto logger = spdlog::create<sink_type>("logger", basename, 0, 0, nullptr);
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
logger->info("Test message {}", i); logger->info("Test message {}", i);

Loading…
Cancel
Save