From 63d0ab09b5445ce5d1dfa84d6600e61deef70601 Mon Sep 17 00:00:00 2001 From: stoffu Date: Fri, 1 Jun 2018 12:29:26 +0900 Subject: [PATCH] mlog: --max-log-files to set the max number of rotated log files --- contrib/epee/include/misc_log_ex.h | 3 +- contrib/epee/src/mlog.cpp | 53 ++++++++++++++++++++++++++++-- src/daemon/command_line_args.h | 5 +++ src/daemon/main.cpp | 3 +- src/wallet/wallet_args.cpp | 4 ++- 5 files changed, 63 insertions(+), 5 deletions(-) diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h index 35ec0950b..530f8e636 100644 --- a/contrib/epee/include/misc_log_ex.h +++ b/contrib/epee/include/misc_log_ex.h @@ -34,6 +34,7 @@ #define MONERO_DEFAULT_LOG_CATEGORY "default" #define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes +#define MAX_LOG_FILES 50 #define MCFATAL(cat,x) CLOG(FATAL,cat) << x #define MCERROR(cat,x) CLOG(ERROR,cat) << x @@ -105,7 +106,7 @@ #endif std::string mlog_get_default_log_path(const char *default_filename); -void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size = MAX_LOG_FILE_SIZE); +void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size = MAX_LOG_FILE_SIZE, const std::size_t max_log_files = MAX_LOG_FILES); void mlog_set_categories(const char *categories); std::string mlog_get_categories(); void mlog_set_log_level(int level); diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp index fb0b4ac2b..0759f5d34 100644 --- a/contrib/epee/src/mlog.cpp +++ b/contrib/epee/src/mlog.cpp @@ -116,7 +116,7 @@ static const char *get_default_categories(int level) return categories; } -void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size) +void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size, const std::size_t max_log_files) { el::Configurations c; c.setGlobally(el::ConfigurationType::Filename, filename_base); @@ -134,9 +134,58 @@ void mlog_configure(const std::string &filename_base, bool console, const std::s el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog); el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput); el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck); - el::Helpers::installPreRollOutCallback([filename_base](const char *name, size_t){ + el::Helpers::installPreRollOutCallback([filename_base, max_log_files](const char *name, size_t){ std::string rname = generate_log_filename(filename_base.c_str()); rename(name, rname.c_str()); + if (max_log_files != 0) + { + std::vector found_files; + const boost::filesystem::directory_iterator end_itr; + for (boost::filesystem::directory_iterator iter(boost::filesystem::path(filename_base).parent_path()); iter != end_itr; ++iter) + { + const std::string filename = iter->path().string(); + if (filename.size() >= filename_base.size() && std::memcmp(filename.data(), filename_base.data(), filename_base.size()) == 0) + { + found_files.push_back(iter->path()); + } + } + if (found_files.size() >= max_log_files) + { + std::sort(found_files.begin(), found_files.end(), [](const boost::filesystem::path &a, const boost::filesystem::path &b) { + boost::system::error_code ec; + std::time_t ta = boost::filesystem::last_write_time(boost::filesystem::path(a), ec); + if (ec) + { + MERROR("Failed to get timestamp from " << a << ": " << ec); + ta = std::time(nullptr); + } + std::time_t tb = boost::filesystem::last_write_time(boost::filesystem::path(b), ec); + if (ec) + { + MERROR("Failed to get timestamp from " << b << ": " << ec); + tb = std::time(nullptr); + } + static_assert(std::is_integral(), "bad time_t"); + return ta < tb; + }); + for (size_t i = 0; i <= found_files.size() - max_log_files; ++i) + { + try + { + boost::system::error_code ec; + boost::filesystem::remove(found_files[i], ec); + if (ec) + { + MERROR("Failed to remove " << found_files[i] << ": " << ec); + } + } + catch (const std::exception &e) + { + MERROR("Failed to remove " << found_files[i] << ": " << e.what()); + } + } + } + } }); mlog_set_common_prefix(); const char *monero_log = getenv("MONERO_LOGS"); diff --git a/src/daemon/command_line_args.h b/src/daemon/command_line_args.h index 4673590aa..cba71bf3b 100644 --- a/src/daemon/command_line_args.h +++ b/src/daemon/command_line_args.h @@ -72,6 +72,11 @@ namespace daemon_args , "Specify maximum log file size [B]" , MAX_LOG_FILE_SIZE }; + const command_line::arg_descriptor arg_max_log_files = { + "max-log-files" + , "Specify maximum number of rotated log files to be saved (no limit by setting to 0)" + , MAX_LOG_FILES + }; const command_line::arg_descriptor arg_log_level = { "log-level" , "" diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index 49494e889..822be0d70 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -84,6 +84,7 @@ int main(int argc, char const * argv[]) command_line::add_arg(core_settings, daemon_args::arg_log_file); command_line::add_arg(core_settings, daemon_args::arg_log_level); command_line::add_arg(core_settings, daemon_args::arg_max_log_file_size); + command_line::add_arg(core_settings, daemon_args::arg_max_log_files); command_line::add_arg(core_settings, daemon_args::arg_max_concurrency); command_line::add_arg(core_settings, daemon_args::arg_zmq_rpc_bind_ip); command_line::add_arg(core_settings, daemon_args::arg_zmq_rpc_bind_port); @@ -203,7 +204,7 @@ int main(int argc, char const * argv[]) if (!command_line::is_arg_defaulted(vm, daemon_args::arg_log_file)) log_file_path = command_line::get_arg(vm, daemon_args::arg_log_file); log_file_path = bf::absolute(log_file_path, relative_path_base); - mlog_configure(log_file_path.string(), true, command_line::get_arg(vm, daemon_args::arg_max_log_file_size)); + mlog_configure(log_file_path.string(), true, command_line::get_arg(vm, daemon_args::arg_max_log_file_size), command_line::get_arg(vm, daemon_args::arg_max_log_files)); // Set log level if (!command_line::is_arg_defaulted(vm, daemon_args::arg_log_level)) diff --git a/src/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp index 6311e7700..91aad9c6e 100644 --- a/src/wallet/wallet_args.cpp +++ b/src/wallet/wallet_args.cpp @@ -101,6 +101,7 @@ namespace wallet_args const command_line::arg_descriptor arg_log_level = {"log-level", "0-4 or categories", ""}; const command_line::arg_descriptor arg_max_log_file_size = {"max-log-file-size", "Specify maximum log file size [B]", MAX_LOG_FILE_SIZE}; + const command_line::arg_descriptor arg_max_log_files = {"max-log-files", "Specify maximum number of rotated log files to be saved (no limit by setting to 0)", MAX_LOG_FILES}; const command_line::arg_descriptor arg_max_concurrency = {"max-concurrency", wallet_args::tr("Max number of threads to use for a parallel job"), DEFAULT_MAX_CONCURRENCY}; const command_line::arg_descriptor arg_log_file = {"log-file", wallet_args::tr("Specify log file"), ""}; const command_line::arg_descriptor arg_config_file = {"config-file", wallet_args::tr("Config file"), "", true}; @@ -119,6 +120,7 @@ namespace wallet_args command_line::add_arg(desc_params, arg_log_file); command_line::add_arg(desc_params, arg_log_level); command_line::add_arg(desc_params, arg_max_log_file_size); + command_line::add_arg(desc_params, arg_max_log_files); command_line::add_arg(desc_params, arg_max_concurrency); command_line::add_arg(desc_params, arg_config_file); @@ -180,7 +182,7 @@ namespace wallet_args log_path = command_line::get_arg(vm, arg_log_file); else log_path = mlog_get_default_log_path(default_log_name); - mlog_configure(log_path, log_to_console, command_line::get_arg(vm, arg_max_log_file_size)); + mlog_configure(log_path, log_to_console, command_line::get_arg(vm, arg_max_log_file_size), command_line::get_arg(vm, arg_max_log_files)); if (!command_line::is_arg_defaulted(vm, arg_log_level)) { mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());