fix: truncate single log file upon reopening (#1143)

This commit is contained in:
Ahmed Hani 2025-02-20 18:49:33 +02:00 committed by GitHub
parent 7fcf58afa6
commit 4f007d9621
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 58 additions and 0 deletions

View File

@ -995,7 +995,22 @@ bool LogFileObject::CreateLogfile(const string& time_pid_string) {
if (FLAGS_timestamp_in_logfile_name) {
// demand that the file is unique for our timestamp (fail if it exists).
flags = flags | O_EXCL;
} else {
// logs are written to a single file, where: a log file is created for the
// the first time or a file is being recreated due to exceeding max size
struct stat statbuf;
if (stat(filename, &statbuf) == 0) {
// truncate the file if it exceeds the max size
if ((static_cast<uint32>(statbuf.st_size) >> 20U) >= MaxLogSize()) {
flags |= O_TRUNC;
}
// update file length to sync file size
file_length_ = static_cast<uint32>(statbuf.st_size);
}
}
FileDescriptor fd{
open(filename, flags, static_cast<mode_t>(FLAGS_logfile_mode))};
if (!fd) return false;

View File

@ -110,6 +110,7 @@ static void TestLogSinkWaitTillSent();
static void TestCHECK();
static void TestDCHECK();
static void TestSTREQ();
static void TestMaxLogSizeWhenNoTimestamp();
static void TestBasename();
static void TestBasenameAppendWhenNoTimestamp();
static void TestTwoProcessesWrite();
@ -288,6 +289,7 @@ int main(int argc, char** argv) {
MungeAndDiffTestStdout(FLAGS_test_srcdir + "/src/logging_unittest.out"));
FLAGS_logtostdout = false;
TestMaxLogSizeWhenNoTimestamp();
TestBasename();
TestBasenameAppendWhenNoTimestamp();
TestTwoProcessesWrite();
@ -806,6 +808,47 @@ static void CheckFile(const string& name, const string& expected_string,
<< expected_string << " in " << files[0];
}
static void TestMaxLogSizeWhenNoTimestamp() {
fprintf(stderr, "==== Test setting max log size without timestamp\n");
const string dest = FLAGS_test_tmpdir + "/logging_test_max_log_size";
DeleteFiles(dest + "*");
auto original_max_log_size = FLAGS_max_log_size;
auto original_timestamp_in_logfile_name = FLAGS_timestamp_in_logfile_name;
FLAGS_max_log_size = 1; // Set max log size to 1MB
FLAGS_timestamp_in_logfile_name = false;
// Set log destination
SetLogDestination(GLOG_INFO, dest.c_str());
// 1e4 info logs -> is about 772 KB in size
// 2e4 info logs -> is around 1500 KB in size -> 1.5MB
// If our max_log_size constraint is respected, it will truncate earlier logs
// and the file size will be lesser than 1MB (around 0.5MB)
const int num_logs = 2e4;
for (int i = 0; i < num_logs; i++) {
LOG(INFO) << "Hello world";
}
FlushLogFiles(GLOG_INFO);
// Check log file size
struct stat statbuf;
stat(dest.c_str(), &statbuf);
// Verify file size is less than the max log size limit
CHECK_LT(static_cast<unsigned int>(statbuf.st_size),
FLAGS_max_log_size << 20U);
// Reset flag values to their original values
FLAGS_max_log_size = original_max_log_size;
FLAGS_timestamp_in_logfile_name = original_timestamp_in_logfile_name;
// Release file handle for the destination file to unlock the file in Windows.
LogToStderr();
DeleteFiles(dest + "*");
}
static void TestBasename() {
fprintf(stderr, "==== Test setting log file basename\n");
const string dest = FLAGS_test_tmpdir + "/logging_test_basename";