Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:Added the periodically clearing serverlog function #2829

Merged
merged 10 commits into from
Aug 8, 2024
5 changes: 5 additions & 0 deletions conf/pika.conf
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ sync-binlog-thread-num : 1
# is used for replication.
log-path : ./log/

# log retention time of serverlogs(pika.{hostname}.{username}.log.{loglevel}.YYYYMMDD-HHMMSS) files that stored within log-path.
# Any serverlogs files that exceed this time will be cleaned up.
# The unit of serverlogs is in [days] and the default value is 7(days).
log-retention-time : 7

# Directory to store the data of Pika.
db-path : ./db/

Expand Down
5 changes: 5 additions & 0 deletions include/pika_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ class PikaConf : public pstd::BaseConf {
std::shared_lock l(rwlock_);
return log_path_;
}
int log_retention_time() {
std::shared_lock l(rwlock_);
return log_retention_time_;
}
std::string log_level() {
std::shared_lock l(rwlock_);
return log_level_;
Expand Down Expand Up @@ -904,6 +908,7 @@ class PikaConf : public pstd::BaseConf {
int db_sync_speed_ = 0;
std::string slaveof_;
std::string log_path_;
int log_retention_time_;
std::string log_level_;
std::string db_path_;
int db_instance_num_ = 0;
Expand Down
3 changes: 2 additions & 1 deletion include/pika_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,8 @@ class PikaServer : public pstd::noncopyable {
*/
void DoTimingTask();
void AutoCompactRange();
void AutoPurge();
void AutoBinlogPurge();
void AutoServerlogPurge();
void AutoDeleteExpiredDump();
void AutoUpdateNetworkMetric();
void PrintThreadPoolQueueStatus();
Expand Down
83 changes: 80 additions & 3 deletions src/pika_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1085,8 +1085,10 @@ int PikaServer::ClientPubSubChannelPatternSize(const std::shared_ptr<NetConn>& c
void PikaServer::DoTimingTask() {
// Maybe schedule compactrange
AutoCompactRange();
// Purge log
AutoPurge();
// Purge serverlog
AutoServerlogPurge();
// Purge binlog
AutoBinlogPurge();
Comment on lines +1090 to +1093
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure proper error handling for purging tasks.

Consider adding error handling and logging for AutoServerlogPurge and AutoBinlogPurge to capture any issues during log purging.

// Purge serverlog
if (!AutoServerlogPurge()) {
  LOG(ERROR) << "Failed to purge server logs";
}
// Purge binlog
if (!AutoBinlogPurge()) {
  LOG(ERROR) << "Failed to purge binlogs";
}

// Delete expired dump
AutoDeleteExpiredDump();
// Cheek Rsync Status
Expand Down Expand Up @@ -1206,7 +1208,82 @@ void PikaServer::AutoCompactRange() {
}
}

void PikaServer::AutoPurge() { DoSameThingEveryDB(TaskType::kPurgeLog); }
void PikaServer::AutoBinlogPurge() { DoSameThingEveryDB(TaskType::kPurgeLog); }

cheniujh marked this conversation as resolved.
Show resolved Hide resolved
void PikaServer::AutoServerlogPurge(){
std::string log_path = g_pika_conf->log_path();
int retention_time = g_pika_conf->log_retention_time();
if (retention_time <= 0) {
return;
}
std::vector<std::string> log_files;

if (!pstd::FileExists(log_path)) {
return;
}

if (pstd::GetChildren(log_path, log_files) != 0) {
return;
}

time_t t = time(nullptr);
struct tm* now = localtime(&t);
int now_year = now->tm_year + 1900;
int now_month = now->tm_mon + 1;
int now_day = now->tm_mday;

//logformat: pika.[hostname].[user name].log.[severity level].[date].[time].[pid]
for (const auto& file : log_files) {
if (file.substr(0, 5) != "pika.") {
continue;
}

size_t log_pos = file.find(".log.");
if (log_pos == std::string::npos) {
continue;
}

// Start at the end of ".log." to find the date and time
size_t date_pos = file.find('.', log_pos + 5);
if (date_pos == std::string::npos || date_pos + 16 > file.length()) {
continue;
}

std::string date = file.substr(date_pos + 1, 8);
std::string time = file.substr(date_pos + 10, 6);

int log_year = std::atoi(date.substr(0, 4).c_str());
int log_month = std::atoi(date.substr(4, 2).c_str());
int log_day = std::atoi(date.substr(6, 2).c_str());

struct tm log_time;
struct tm now_time;

log_time.tm_year = log_year - 1900;
log_time.tm_mon = log_month - 1;
log_time.tm_mday = log_day;
log_time.tm_hour = 0;
log_time.tm_min = 0;
log_time.tm_sec = 0;

now_time.tm_year = now_year - 1900;
now_time.tm_mon = now_month - 1;
now_time.tm_mday = now_day;
now_time.tm_hour = 0;
now_time.tm_min = 0;
now_time.tm_sec = 0;

int64_t log_timestamp = mktime(&log_time);
int64_t now_timestamp = mktime(&now_time);
int64_t interval_days = (now_timestamp - log_timestamp) / 86400;

if (interval_days > retention_time) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A logic is needed to guarantee that the latest log(which is in use) will not be deleted even if it's logically expired.
The time extracted from log file name is the time of it's creation. thus it's possible that a log has logically expired but still in use if the pika server is inactive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do your mean that assuming a Pika instance has been running continuously for 8 days, a server log created 8 days ago should logically have expired, but in reality, it is the most recent and currently used server log?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that's what i mean

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure the latest log file is not deleted if still in use.

Add logic to guarantee that the latest log file, which might still be in use, is not deleted even if it is logically expired.

if (interval_days > retention_time && !IsLogFileInUse(file)) {
  std::string log_file = log_path + "/" + file;
  LOG(INFO) << "Deleting out of date log file: " << log_file;
  if (!pstd::DeleteFile(log_file)) {
    LOG(ERROR) << "Failed to delete log file: " << log_file;
  }
}

std::string log_file = log_path + "/" + file;
LOG(INFO) << "Deleting out of date log file: " << log_file;
pstd::DeleteFile(log_file);
Copy link
Collaborator

@cheniujh cheniujh Jul 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls check return value and print Error Log if deleteFile failed

}
}
}

void PikaServer::AutoDeleteExpiredDump() {
std::string db_sync_prefix = g_pika_conf->bgsave_prefix();
Expand Down
Loading