Merge 314903eac7 into 4f007d9621
This commit is contained in:
commit
fbe03cbf1e
100
src/cleanup_deferred_unittest.cc
Normal file
100
src/cleanup_deferred_unittest.cc
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2024, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "base/commandlineflags.h"
|
||||
#include "glog/logging.h"
|
||||
#include "glog/raw_logging.h"
|
||||
#include "googletest.h"
|
||||
|
||||
#ifdef GLOG_USE_GFLAGS
|
||||
# include <gflags/gflags.h>
|
||||
using namespace GFLAGS_NAMESPACE;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIB_GMOCK
|
||||
# include <gmock/gmock.h>
|
||||
|
||||
# include "mock-log.h"
|
||||
// Introduce several symbols from gmock.
|
||||
using google::glog_testing::ScopedMockLog;
|
||||
using testing::_;
|
||||
using testing::AllOf;
|
||||
using testing::AnyNumber;
|
||||
using testing::HasSubstr;
|
||||
using testing::InitGoogleMock;
|
||||
using testing::StrictMock;
|
||||
using testing::StrNe;
|
||||
#endif
|
||||
|
||||
using namespace google;
|
||||
|
||||
TEST(CleanDeferred, logging) {
|
||||
using namespace std::chrono_literals;
|
||||
const string dest =
|
||||
FLAGS_test_tmpdir + "/test_cleanup_enable_generic_logs";
|
||||
google::EnableLogCleanerForGenericLogs(1h);
|
||||
google::SetLogDestination(GLOG_INFO, dest.c_str());
|
||||
for (unsigned i = 0; i < 10; ++i) {
|
||||
LOG(INFO) << "cleanup test";
|
||||
}
|
||||
|
||||
google::DisableLogCleanerForGenericLogs();
|
||||
// delete the file
|
||||
CHECK(unlink(dest.c_str()) == 0) << ": " << strerror(errno);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
FLAGS_colorlogtostderr = false;
|
||||
FLAGS_timestamp_in_logfile_name = false;
|
||||
FLAGS_logcleansecs = 1;
|
||||
#ifdef GLOG_USE_GFLAGS
|
||||
ParseCommandLineFlags(&argc, &argv, true);
|
||||
#endif
|
||||
// Make sure stderr is not buffered as stderr seems to be buffered
|
||||
// on recent windows.
|
||||
setbuf(stderr, nullptr);
|
||||
|
||||
// Test some basics before InitGoogleLogging:
|
||||
CaptureTestStderr();
|
||||
const string early_stderr = GetCapturedTestStderr();
|
||||
|
||||
EXPECT_FALSE(IsGoogleLoggingInitialized());
|
||||
|
||||
InitGoogleLogging(argv[0]);
|
||||
|
||||
EXPECT_TRUE(IsGoogleLoggingInitialized());
|
||||
|
||||
InitGoogleTest(&argc, argv);
|
||||
#ifdef HAVE_LIB_GMOCK
|
||||
InitGoogleMock(&argc, argv);
|
||||
#endif
|
||||
|
||||
// so that death tests run before we use threads
|
||||
CHECK_EQ(RUN_ALL_TESTS(), 0);
|
||||
}
|
||||
@ -485,6 +485,10 @@ InstallFailureFunction(logging_fail_func_t fail_func);
|
||||
GLOG_EXPORT void EnableLogCleaner(const std::chrono::minutes& overdue);
|
||||
GLOG_EXPORT void DisableLogCleaner();
|
||||
GLOG_EXPORT void SetApplicationFingerprint(const std::string& fingerprint);
|
||||
GLOG_EXPORT void EnableLogCleaner(LogSeverity severity, const std::chrono::minutes& overdue);
|
||||
GLOG_EXPORT void DisableLogCleaner(LogSeverity severity);
|
||||
GLOG_EXPORT void EnableLogCleanerForGenericLogs(const std::chrono::minutes& overdue);
|
||||
GLOG_EXPORT void DisableLogCleanerForGenericLogs();
|
||||
|
||||
class LogSink; // defined below
|
||||
|
||||
|
||||
@ -72,6 +72,7 @@
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef HAVE__CHSIZE_S
|
||||
# include <io.h> // for truncate log file
|
||||
@ -337,6 +338,16 @@ const char* GetLogSeverityName(LogSeverity severity) {
|
||||
return LogSeverityNames[severity];
|
||||
}
|
||||
|
||||
int FindFilepathLogSeverity(const std::string& filepath) {
|
||||
for (int i = GLOG_INFO; i < NUM_SEVERITIES; i++) {
|
||||
if (filepath.rfind(GetLogSeverityName(static_cast<LogSeverity>(i))) != std::string::npos) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool SendEmailInternal(const char* dest, const char* subject,
|
||||
const char* body, bool use_logging);
|
||||
|
||||
@ -345,7 +356,6 @@ base::Logger::~Logger() = default;
|
||||
namespace {
|
||||
|
||||
constexpr std::intmax_t kSecondsInDay = 60 * 60 * 24;
|
||||
constexpr std::intmax_t kSecondsInWeek = kSecondsInDay * 7;
|
||||
|
||||
// Optional user-configured callback to print custom prefixes.
|
||||
class PrefixFormatter {
|
||||
@ -437,13 +447,18 @@ class LogCleaner {
|
||||
|
||||
// Setting overdue to 0 days will delete all logs.
|
||||
void Enable(const std::chrono::minutes& overdue);
|
||||
void Enable(const LogSeverity severity, const std::chrono::minutes& overdue);
|
||||
void Disable();
|
||||
void Disable(const LogSeverity severity);
|
||||
// For files with no severity in their names
|
||||
void EnableForGenericLogs(const std::chrono::minutes& overdue);
|
||||
void DisableForGenericLogs();
|
||||
|
||||
void Run(const std::chrono::system_clock::time_point& current_time,
|
||||
bool base_filename_selected, const string& base_filename,
|
||||
const string& filename_extension);
|
||||
|
||||
bool enabled() const { return enabled_; }
|
||||
bool enabled() const { return !overdue_.empty(); }
|
||||
|
||||
private:
|
||||
vector<string> GetOverdueLogNames(
|
||||
@ -459,9 +474,7 @@ class LogCleaner {
|
||||
const string& filepath,
|
||||
const std::chrono::system_clock::time_point& current_time) const;
|
||||
|
||||
bool enabled_{false};
|
||||
std::chrono::minutes overdue_{
|
||||
std::chrono::duration<int, std::ratio<kSecondsInWeek>>{1}};
|
||||
std::unordered_map<int, std::chrono::minutes> overdue_;
|
||||
std::chrono::system_clock::time_point
|
||||
next_cleanup_time_; // cycle count at which to clean overdue log
|
||||
};
|
||||
@ -1300,16 +1313,36 @@ void LogFileObject::Write(
|
||||
LogCleaner::LogCleaner() = default;
|
||||
|
||||
void LogCleaner::Enable(const std::chrono::minutes& overdue) {
|
||||
enabled_ = true;
|
||||
overdue_ = overdue;
|
||||
// For the files that have no severity specified, we use -1 as the key
|
||||
EnableForGenericLogs(overdue);
|
||||
// For backward compatability, set all severities to the same value
|
||||
for (int i = GLOG_INFO; i < NUM_SEVERITIES; i++) {
|
||||
Enable(static_cast<LogSeverity>(i), overdue);
|
||||
}
|
||||
}
|
||||
|
||||
void LogCleaner::Disable() { enabled_ = false; }
|
||||
void LogCleaner::Enable(const LogSeverity severity, const std::chrono::minutes& overdue) {
|
||||
overdue_[severity] = overdue;
|
||||
}
|
||||
|
||||
void LogCleaner::Disable() { overdue_.clear(); }
|
||||
|
||||
void LogCleaner::Disable(const LogSeverity severity) {
|
||||
overdue_.erase(severity);
|
||||
}
|
||||
|
||||
void LogCleaner::EnableForGenericLogs(const std::chrono::minutes& overdue) {
|
||||
overdue_[-1] = overdue;
|
||||
}
|
||||
|
||||
void LogCleaner::DisableForGenericLogs() {
|
||||
overdue_.erase(-1);
|
||||
}
|
||||
|
||||
void LogCleaner::Run(const std::chrono::system_clock::time_point& current_time,
|
||||
bool base_filename_selected, const string& base_filename,
|
||||
const string& filename_extension) {
|
||||
assert(enabled_);
|
||||
assert(enabled());
|
||||
assert(!base_filename_selected || !base_filename.empty());
|
||||
|
||||
// avoid scanning logs too frequently
|
||||
@ -1486,7 +1519,13 @@ bool LogCleaner::IsLogLastModifiedOver(
|
||||
const auto last_modified_time =
|
||||
std::chrono::system_clock::from_time_t(file_stat.st_mtime);
|
||||
const auto diff = current_time - last_modified_time;
|
||||
return diff >= overdue_;
|
||||
|
||||
auto severity_it = overdue_.find(FindFilepathLogSeverity(filepath));
|
||||
if (severity_it == overdue_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return diff >= severity_it->second;
|
||||
}
|
||||
|
||||
// If failed to get file stat, don't return true!
|
||||
@ -2642,8 +2681,24 @@ void EnableLogCleaner(const std::chrono::minutes& overdue) {
|
||||
log_cleaner.Enable(overdue);
|
||||
}
|
||||
|
||||
void EnableLogCleaner(LogSeverity severity, const std::chrono::minutes& overdue) {
|
||||
log_cleaner.Enable(severity, overdue);
|
||||
}
|
||||
|
||||
void EnableLogCleanerForGenericLogs(const std::chrono::minutes& overdue) {
|
||||
log_cleaner.EnableForGenericLogs(overdue);
|
||||
}
|
||||
|
||||
void DisableLogCleaner() { log_cleaner.Disable(); }
|
||||
|
||||
void DisableLogCleaner(LogSeverity severity) {
|
||||
log_cleaner.Disable(severity);
|
||||
}
|
||||
|
||||
void DisableLogCleanerForGenericLogs() {
|
||||
log_cleaner.DisableForGenericLogs();
|
||||
}
|
||||
|
||||
LogMessageTime::LogMessageTime() = default;
|
||||
|
||||
namespace {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user