starrocks/thirdparty/patches/glog-0.4.0-for-starrocks2.p...

392 lines
14 KiB
Diff

diff --git a/src/glog/logging.h.in b/src/glog/logging.h.in
index 9968b96..ff7c1c2 100644
--- a/src/glog/logging.h.in
+++ b/src/glog/logging.h.in
@@ -330,6 +330,11 @@ typedef unsigned __int64 uint64;
using fLS::FLAGS_##name
#endif
+DECLARE_int32(log_filenum_quota);
+
+DECLARE_string(log_split_method);
+
+
// Set whether log messages go to stderr instead of logfiles
DECLARE_bool(logtostderr);
diff --git a/src/logging.cc b/src/logging.cc
index 0c86cf6..d846a4e 100644
--- a/src/logging.cc
+++ b/src/logging.cc
@@ -49,13 +49,17 @@
#include <iostream>
#include <stdarg.h>
#include <stdlib.h>
+#include <dirent.h>
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#ifdef HAVE_SYSLOG_H
# include <syslog.h>
#endif
+#include <algorithm>
#include <vector>
+#include <list>
+#include <string>
#include <errno.h> // for errno
#include <sstream>
#include "base/commandlineflags.h" // to get the program name
@@ -172,6 +176,12 @@ GLOG_DEFINE_int32(max_log_size, 1800,
"approx. maximum log file size (in MB). A value of 0 will "
"be silently overridden to 1.");
+GLOG_DEFINE_string(log_split_method, "day",
+ "split log by size, day, hour");
+
+GLOG_DEFINE_int32(log_filenum_quota, 10,
+ "max log file num in log dir");
+
GLOG_DEFINE_bool(stop_logging_if_full_disk, false,
"Stop attempting to log to disk if the disk is full.");
@@ -394,6 +404,15 @@ base::Logger::~Logger() {
namespace {
+typedef struct filetime {
+ std::string name;
+ time_t time;
+
+ bool operator < (const struct filetime& o) const {
+ return o.time > time;
+ }
+}Filetime;
+
// Encapsulates all file-system related state
class LogFileObject : public base::Logger {
public:
@@ -425,6 +444,8 @@ class LogFileObject : public base::Logger {
// acquiring lock_.
void FlushUnlocked();
+ void CheckFileNumQuota();
+
private:
static const uint32 kRolloverAttemptFrequency = 0x20;
@@ -440,6 +461,9 @@ class LogFileObject : public base::Logger {
uint32 file_length_;
unsigned int rollover_attempt_;
int64 next_flush_time_; // cycle count at which to flush log
+ std::list<Filetime> file_list_;
+ bool inited_;
+ struct ::tm tm_time_;
// Actually create a logfile using the value of base_filename_ and the
// supplied argument time_pid_string
@@ -458,7 +482,7 @@ class LogDestination {
// These methods are just forwarded to by their global versions.
static void SetLogDestination(LogSeverity severity,
- const char* base_filename);
+ const char* base_filename);
static void SetLogSymlink(LogSeverity severity,
const char* symlink_basename);
static void AddLogSink(LogSink *destination);
@@ -490,17 +514,17 @@ class LogDestination {
// Take a log message of a particular severity and log it to stderr
// iff it's of a high enough severity to deserve it.
static void MaybeLogToStderr(LogSeverity severity, const char* message,
- size_t len);
+ size_t len);
// Take a log message of a particular severity and log it to email
// iff it's of a high enough severity to deserve it.
static void MaybeLogToEmail(LogSeverity severity, const char* message,
- size_t len);
+ size_t len);
// Take a log message of a particular severity and log it to a file
// iff the base filename is not "" (which means "don't log to me")
static void MaybeLogToLogfile(LogSeverity severity,
time_t timestamp,
- const char* message, size_t len);
+ const char* message, size_t len);
// Take a log message of a particular severity and log it to the file
// for that severity and also for all files with severity less than
// this severity.
@@ -589,7 +613,7 @@ inline void LogDestination::FlushLogFiles(int min_severity) {
// all this stuff.
MutexLock l(&log_mutex);
for (int i = min_severity; i < NUM_SEVERITIES; i++) {
- LogDestination* log = log_destination(i);
+ LogDestination* log = log_destinations_[i];
if (log != NULL) {
log->logger_->Flush();
}
@@ -664,7 +688,7 @@ inline void LogDestination::LogToStderr() {
}
inline void LogDestination::SetEmailLogging(LogSeverity min_severity,
- const char* addresses) {
+ const char* addresses) {
assert(min_severity >= 0 && min_severity < NUM_SEVERITIES);
// Prevent any subtle race conditions by wrapping a mutex lock around
// all this stuff.
@@ -717,7 +741,7 @@ static void WriteToStderr(const char* message, size_t len) {
}
inline void LogDestination::MaybeLogToStderr(LogSeverity severity,
- const char* message, size_t len) {
+ const char* message, size_t len) {
if ((severity >= FLAGS_stderrthreshold) || FLAGS_alsologtostderr) {
ColoredWriteToStderr(severity, message, len);
#ifdef OS_WINDOWS
@@ -756,8 +780,8 @@ inline void LogDestination::MaybeLogToEmail(LogSeverity severity,
inline void LogDestination::MaybeLogToLogfile(LogSeverity severity,
time_t timestamp,
- const char* message,
- size_t len) {
+ const char* message,
+ size_t len) {
const bool should_flush = severity > FLAGS_logbuflevel;
LogDestination* destination = log_destination(severity);
destination->logger_->Write(should_flush, timestamp, message, len);
@@ -771,8 +795,12 @@ inline void LogDestination::LogToAllLogfiles(LogSeverity severity,
if ( FLAGS_logtostderr ) { // global flag: never log to file
ColoredWriteToStderr(severity, message, len);
} else {
- for (int i = severity; i >= 0; --i)
- LogDestination::MaybeLogToLogfile(i, timestamp, message, len);
+ if (severity >= 1) {
+ LogDestination::MaybeLogToLogfile(1, timestamp, message, len);
+ LogDestination::MaybeLogToLogfile(0, timestamp, message, len);
+ } else if (severity == 0) {
+ LogDestination::MaybeLogToLogfile(0, timestamp, message, len);
+ } else {}
}
}
@@ -841,7 +869,8 @@ LogFileObject::LogFileObject(LogSeverity severity,
dropped_mem_length_(0),
file_length_(0),
rollover_attempt_(kRolloverAttemptFrequency-1),
- next_flush_time_(0) {
+ next_flush_time_(0),
+ inited_(false) {
assert(severity >= 0);
assert(severity < NUM_SEVERITIES);
}
@@ -906,7 +935,7 @@ bool LogFileObject::CreateLogfile(const string& time_pid_string) {
string string_filename = base_filename_+filename_extension_+
time_pid_string;
const char* filename = string_filename.c_str();
- int fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, FLAGS_logfile_mode);
+ int fd = open(filename, O_WRONLY | O_CREAT /* | O_EXCL */ | O_APPEND, 0664);
if (fd == -1) return false;
#ifdef HAVE_FCNTL
// Mark the file close-on-exec. We don't really care if this fails
@@ -920,6 +949,10 @@ bool LogFileObject::CreateLogfile(const string& time_pid_string) {
return false;
}
+ Filetime ft;
+ ft.name = string_filename;
+ file_list_.push_back(ft);
+
// We try to create a symlink called <program_name>.<severity>,
// which is easier to use. (Every time we create a new logfile,
// we destroy the old symlink and create a new one, so it always
@@ -961,6 +994,59 @@ bool LogFileObject::CreateLogfile(const string& time_pid_string) {
return true; // Everything worked
}
+void LogFileObject::CheckFileNumQuota() {
+ struct dirent *entry;
+ DIR *dp;
+
+ const vector<string> & log_dirs = GetLoggingDirectories();
+ if (log_dirs.size() < 1) return;
+
+ //fprintf(stderr, "log dir: %s\n", log_dirs[0].c_str());
+
+ // list file in log dir
+ dp = opendir(log_dirs[0].c_str());
+ if (dp == NULL) {
+ fprintf(stderr, "open log dir %s fail\n", log_dirs[0].c_str());
+ return;
+ }
+
+ file_list_.clear();
+ while ((entry = readdir(dp)) != NULL) {
+ if (DT_DIR == entry->d_type ||
+ DT_LNK == entry->d_type) {
+ continue;
+ }
+ std::string filename = std::string(entry->d_name);
+ //fprintf(stderr, "filename: %s\n", filename.c_str());
+
+ if (filename.find(symlink_basename_ + '.' + LogSeverityNames[severity_]) == 0) {
+ std::string filepath = log_dirs[0] + "/" + filename;
+
+ struct stat fstat;
+ if (::stat(filepath.c_str(), &fstat) < 0) {
+ fprintf(stderr, "state %s fail\n", filepath.c_str());
+ closedir(dp);
+ return;
+ }
+ //fprintf(stderr, "filepath: %s\n", filepath.c_str());
+
+ Filetime file_time;
+ file_time.time = fstat.st_mtime;
+ file_time.name = filepath;
+ file_list_.push_back(file_time);
+ }
+ }
+ closedir(dp);
+
+ file_list_.sort();
+
+ while (FLAGS_log_filenum_quota > 0 && file_list_.size() >= FLAGS_log_filenum_quota) {
+ // fprintf(stderr, "delete %s\n", file_list_.front().name.c_str());
+ unlink(file_list_.front().name.c_str());
+ file_list_.pop_front();
+ }
+}
+
void LogFileObject::Write(bool force_flush,
time_t timestamp,
const char* message,
@@ -972,14 +1058,55 @@ void LogFileObject::Write(bool force_flush,
return;
}
- if (static_cast<int>(file_length_ >> 20) >= MaxLogSize() ||
- PidHasChanged()) {
+ struct ::tm tm_time;
+
+ bool is_split = false;
+ if ("day" == FLAGS_log_split_method) {
+ localtime_r(&timestamp, &tm_time);
+ if (tm_time.tm_year != tm_time_.tm_year
+ || tm_time.tm_mon != tm_time_.tm_mon
+ || tm_time.tm_mday != tm_time_.tm_mday) {
+ is_split = true;
+ }
+ } else if ("hour" == FLAGS_log_split_method) {
+ localtime_r(&timestamp, &tm_time);
+ if (tm_time.tm_year != tm_time_.tm_year
+ || tm_time.tm_mon != tm_time_.tm_mon
+ || tm_time.tm_mday != tm_time_.tm_mday
+ || tm_time.tm_hour != tm_time_.tm_hour) {
+ is_split = true;
+ }
+ } else if (static_cast<int>(file_length_ >> 20) >= MaxLogSize()) {
+ // PidHasChanged()) {
+ is_split = true;
+ }
+
+ if (is_split) {
if (file_ != NULL) fclose(file_);
file_ = NULL;
file_length_ = bytes_since_flush_ = dropped_mem_length_ = 0;
rollover_attempt_ = kRolloverAttemptFrequency-1;
}
+ if ((file_ == NULL) && (!inited_) && (FLAGS_log_split_method == "size")) {
+ CheckFileNumQuota();
+ const char* filename = file_list_.back().name.c_str();
+ int fd = open(filename, O_WRONLY | O_CREAT /* | O_EXCL */ | O_APPEND, 0664);
+ if (fd != -1) {
+#ifdef HAVE_FCNTL
+ // Mark the file close-on-exec. We don't really care if this fails
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+ file_ = fopen(filename, "a+"); // Read and append a FILE*.
+ if (file_ == NULL) { // Man, we're screwed!, try to create new log file
+ close(fd);
+ }
+ fseek(file_, 0, SEEK_END);
+ file_length_ = bytes_since_flush_ = ftell(file_);
+ inited_ = true;
+ }
+ }
+
// If there's no destination file, make one before outputting
if (file_ == NULL) {
// Try to rollover the log file every 32 log messages. The only time
@@ -988,21 +1115,35 @@ void LogFileObject::Write(bool force_flush,
if (++rollover_attempt_ != kRolloverAttemptFrequency) return;
rollover_attempt_ = 0;
- struct ::tm tm_time;
- localtime_r(&timestamp, &tm_time);
+ if (!inited_) {
+ CheckFileNumQuota();
+ inited_ = true;
+ } else {
+ while (FLAGS_log_filenum_quota > 0 && file_list_.size() >= FLAGS_log_filenum_quota) {
+ unlink(file_list_.front().name.c_str());
+ file_list_.pop_front();
+ }
+ }
+ localtime_r(&timestamp, &tm_time);
// The logfile's filename will have the date/time & pid in it
ostringstream time_pid_stream;
time_pid_stream.fill('0');
time_pid_stream << 1900+tm_time.tm_year
<< setw(2) << 1+tm_time.tm_mon
- << setw(2) << tm_time.tm_mday
- << '-'
- << setw(2) << tm_time.tm_hour
- << setw(2) << tm_time.tm_min
- << setw(2) << tm_time.tm_sec
- << '.'
- << GetMainThreadPid();
+ << setw(2) << tm_time.tm_mday;
+
+ if ("hour" == FLAGS_log_split_method) {
+ time_pid_stream << setw(2) << tm_time.tm_hour;
+ } else if ("day" != FLAGS_log_split_method) {
+ time_pid_stream << '-'
+ << setw(2) << tm_time.tm_hour
+ << setw(2) << tm_time.tm_min
+ << setw(2) << tm_time.tm_sec;
+ }
+
+ tm_time_ = tm_time;
+
const string& time_pid_string = time_pid_stream.str();
if (base_filename_selected_) {
@@ -1036,9 +1177,7 @@ void LogFileObject::Write(bool force_flush,
// deadlock. Simply use a name like invalid-user.
if (uidname.empty()) uidname = "invalid-user";
- stripped_filename = stripped_filename+'.'+hostname+'.'
- +uidname+".log."
- +LogSeverityNames[severity_]+'.';
+ stripped_filename = stripped_filename + "." + LogSeverityNames[severity_] + ".log.";
// We're going to (potentially) try to put logs in several different dirs
const vector<string> & log_dirs = GetLoggingDirectories();
@@ -1062,7 +1201,8 @@ void LogFileObject::Write(bool force_flush,
return;
}
}
-
+
+ /*
// Write a header message into the log file
ostringstream file_header_stream;
file_header_stream.fill('0');
@@ -1084,6 +1224,7 @@ void LogFileObject::Write(bool force_flush,
fwrite(file_header_string.data(), 1, header_len, file_);
file_length_ += header_len;
bytes_since_flush_ += header_len;
+ */
}
// Write to LOG file