Added an API to get GMT offset from LogMessageTime

* Added API to get GMT offset
    * Made LogMessageTime as a memeber of LogMessage
    * Refactored LogSink::send() method
This commit is contained in:
Vijaymahantesh Sattigeri 2021-11-18 17:58:36 +05:30 committed by Sergiu Deitsch
parent ee6faf13b2
commit ef36f800ed
7 changed files with 121 additions and 124 deletions

View File

@ -24,5 +24,6 @@ Roman Perepelitsa <roman.perepelitsa@gmail.com>
Sergiu Deitsch <sergiu.deitsch@gmail.com>
tbennun <tbennun@gmail.com>
Teddy Reed <teddy@prosauce.org>
Vijaymahantesh Sattigeri <vijay.thread.temp@gmail.com>
Zhongming Qu <qzmfranklin@gmail.com>
Zhuoran Shen <cmsflash99@gmail.com>

View File

@ -47,5 +47,6 @@ Sergiu Deitsch <sergiu.deitsch@gmail.com>
Shinichiro Hamaji <hamaji@google.com>
tbennun <tbennun@gmail.com>
Teddy Reed <teddy@prosauce.org>
Vijaymahantesh Sattigeri <vijay.thread.temp@gmail.com>
Zhongming Qu <qzmfranklin@gmail.com>
Zhuoran Shen <cmsflash99@gmail.com>

View File

@ -135,30 +135,40 @@ typedef unsigned __int64 uint64;
@ac_google_end_namespace@
#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
struct LogMessageTime {
explicit LogMessageTime (const struct::tm& time_struct_,
const time_t& timestamp_, const int32_t& usecs_):
time_struct(time_struct_), ts(timestamp_), usecs(usecs_) {}
LogMessageTime(): time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
const time_t& timestamp() const { return ts; }
const int& sec() const { return time_struct.tm_sec; }
const int32_t& usec() const { return usecs; }
const int& (min)() const { return time_struct.tm_min; }
const int& hour() const { return time_struct.tm_hour; }
const int& day() const { return time_struct.tm_mday; }
const int& month() const { return time_struct.tm_mon; }
const int& year() const { return time_struct.tm_year; }
const int& dayOfWeek() const { return time_struct.tm_wday; }
const int& dayInYear() const { return time_struct.tm_yday; }
const int& dst() const { return time_struct.tm_isdst; }
void setTimeInfo(struct::tm time_struct, time_t timestamp, int32_t usecs){
time_struct_ = time_struct;
timestamp_ = timestamp;
usecs_ = usecs;
CalcGmtOffset();
}
const time_t& timestamp() const { return timestamp_; }
const int& sec() const { return time_struct_.tm_sec; }
const int32_t& usec() const { return usecs_; }
const int& (min)() const { return time_struct_.tm_min; }
const int& hour() const { return time_struct_.tm_hour; }
const int& day() const { return time_struct_.tm_mday; }
const int& month() const { return time_struct_.tm_mon; }
const int& year() const { return time_struct_.tm_year; }
const int& dayOfWeek() const { return time_struct_.tm_wday; }
const int& dayInYear() const { return time_struct_.tm_yday; }
const int& dst() const { return time_struct_.tm_isdst; }
const long int& gmtoff() const { return gmtoffset_; }
private:
const struct::tm& time_struct;
const time_t& ts;
const int32_t& usecs;
struct::tm time_struct_; // Time of creation of LogMessage
time_t timestamp_; // Time of creation of LogMessage in seconds
int32_t usecs_; // Time of creation of LogMessage - microseconds part
long int gmtoffset_;
void CalcGmtOffset();
};
#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
struct LogMessageInfo {
explicit LogMessageInfo(const char* const severity_,
const char* const filename_,
@ -1552,6 +1562,10 @@ public:
// Must be called without the log_mutex held. (L < log_mutex)
static int64 num_messages(int severity);
const LogMessageTime& getLogMessageTime() const {
return logmsgtime_;
}
struct LogMessageData;
private:
@ -1577,6 +1591,7 @@ private:
// LogMessage uses less stack space.
LogMessageData* allocated_;
LogMessageData* data_;
LogMessageTime logmsgtime_;
friend class LogDestination;
@ -1721,17 +1736,7 @@ class GOOGLE_GLOG_DLL_DECL LogSink {
// during this call.
virtual void send(LogSeverity severity, const char* full_filename,
const char* base_filename, int line,
const struct ::tm* tm_time,
const char* message, size_t message_len, int32 /*usecs*/) {
send(severity, full_filename, base_filename, line,
tm_time, message, message_len);
}
// This send() signature is obsolete.
// New implementations should define this in terms of
// the above send() method.
virtual void send(LogSeverity severity, const char* full_filename,
const char* base_filename, int line,
const struct ::tm* tm_time,
const LogMessageTime &logmsgtime,
const char* message, size_t message_len) = 0;
// Redefine this to implement waiting for
@ -1752,16 +1757,8 @@ class GOOGLE_GLOG_DLL_DECL LogSink {
// Returns the normal text output of the log message.
// Can be useful to implement send().
static std::string ToString(LogSeverity severity, const char* file, int line,
const struct ::tm* tm_time,
const char* message, size_t message_len,
int32 usecs);
// Obsolete
static std::string ToString(LogSeverity severity, const char* file, int line,
const struct ::tm* tm_time,
const char* message, size_t message_len) {
return ToString(severity, file, line, tm_time, message, message_len, 0);
}
const LogMessageTime &logmsgtime,
const char* message, size_t message_len);
};
// Add or remove a LogSink as a consumer of logging data. Thread-safe.

View File

@ -363,9 +363,6 @@ struct LogMessage::LogMessageData {
std::vector<std::string>* outvec_; // NULL or vector to push message onto
std::string* message_; // NULL or string to write message into
};
time_t timestamp_; // Time of creation of LogMessage
struct ::tm tm_time_; // Time of creation of LogMessage
int32 usecs_; // Time of creation of LogMessage - microseconds part
size_t num_prefix_chars_; // # of chars of prefix in this message
size_t num_chars_to_log_; // # of chars of msg to send to log
size_t num_chars_to_syslog_; // # of chars of msg to send to syslog
@ -571,10 +568,9 @@ class LogDestination {
const char *full_filename,
const char *base_filename,
int line,
const struct ::tm* tm_time,
const LogMessageTime &logmsgtime,
const char* message,
size_t message_len,
int32 usecs);
size_t message_len);
// Wait for all registered sinks via WaitTillSent
// including the optional one in "data".
@ -854,15 +850,14 @@ inline void LogDestination::LogToSinks(LogSeverity severity,
const char *full_filename,
const char *base_filename,
int line,
const struct ::tm* tm_time,
const LogMessageTime &logmsgtime,
const char* message,
size_t message_len,
int32 usecs) {
size_t message_len) {
ReaderMutexLock l(&sink_mutex_);
if (sinks_) {
for (size_t i = sinks_->size(); i-- > 0; ) {
(*sinks_)[i]->send(severity, full_filename, base_filename,
line, tm_time, message, message_len, usecs);
line, logmsgtime, message, message_len);
}
}
}
@ -1608,12 +1603,15 @@ void LogMessage::Init(const char* file,
data_->sink_ = NULL;
data_->outvec_ = NULL;
WallTime now = WallTime_Now();
data_->timestamp_ = static_cast<time_t>(now);
time_t timestamp_now = static_cast<time_t>(now);
std::tm time_struct;
if(FLAGS_log_utc_time)
gmtime_r(&data_->timestamp_, &data_->tm_time_);
gmtime_r(&timestamp_now, &time_struct);
else
localtime_r(&data_->timestamp_, &data_->tm_time_);
data_->usecs_ = static_cast<int32>((now - data_->timestamp_) * 1000000);
localtime_r(&timestamp_now, &time_struct);
logmsgtime_.setTimeInfo(time_struct, timestamp_now,
static_cast<int32>((now - timestamp_now) * 1000000));
data_->num_chars_to_log_ = 0;
data_->num_chars_to_syslog_ = 0;
@ -1633,14 +1631,14 @@ void LogMessage::Init(const char* file,
if (custom_prefix_callback == NULL) {
#endif
stream() << LogSeverityNames[severity][0]
<< setw(4) << 1900+data_->tm_time_.tm_year
<< setw(2) << 1+data_->tm_time_.tm_mon
<< setw(2) << data_->tm_time_.tm_mday
<< setw(4) << 1900 + logmsgtime_.year()
<< setw(2) << 1 + logmsgtime_.month()
<< setw(2) << logmsgtime_.day()
<< ' '
<< setw(2) << data_->tm_time_.tm_hour << ':'
<< setw(2) << data_->tm_time_.tm_min << ':'
<< setw(2) << data_->tm_time_.tm_sec << "."
<< setw(6) << data_->usecs_
<< setw(2) << logmsgtime_.hour() << ':'
<< setw(2) << logmsgtime_.min() << ':'
<< setw(2) << logmsgtime_.sec() << "."
<< setw(6) << logmsgtime_.usec()
<< ' '
<< setfill(' ') << setw(5)
<< static_cast<unsigned int>(GetTID()) << setfill('0')
@ -1652,9 +1650,7 @@ void LogMessage::Init(const char* file,
stream(),
LogMessageInfo(LogSeverityNames[severity],
data_->basename_, data_->line_, GetTID(),
LogMessageTime(data_->tm_time_,
data_->timestamp_,
data_->usecs_)),
logmsgtime_),
custom_prefix_callback_data
);
stream() << " ";
@ -1800,15 +1796,14 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
// this could be protected by a flag if necessary.
LogDestination::LogToSinks(data_->severity_,
data_->fullname_, data_->basename_,
data_->line_, &data_->tm_time_,
data_->line_, logmsgtime_,
data_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_ -
data_->num_prefix_chars_ - 1),
data_->usecs_);
data_->num_prefix_chars_ - 1) );
} else {
// log this message to all log files of severity <= severity_
LogDestination::LogToAllLogfiles(data_->severity_, data_->timestamp_,
LogDestination::LogToAllLogfiles(data_->severity_, logmsgtime_.timestamp(),
data_->message_text_,
data_->num_chars_to_log_);
@ -1819,11 +1814,10 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
data_->num_chars_to_log_);
LogDestination::LogToSinks(data_->severity_,
data_->fullname_, data_->basename_,
data_->line_, &data_->tm_time_,
data_->line_, logmsgtime_,
data_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_
- data_->num_prefix_chars_ - 1),
data_->usecs_);
- data_->num_prefix_chars_ - 1) );
// NOTE: -1 removes trailing \n
}
@ -1842,7 +1836,7 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
sizeof(fatal_message)-1);
memcpy(fatal_message, data_->message_text_, copy);
fatal_message[copy] = '\0';
fatal_time = data_->timestamp_;
fatal_time = logmsgtime_.timestamp();
}
if (!FLAGS_logtostderr) {
@ -1904,11 +1898,10 @@ void LogMessage::SendToSink() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
data_->sink_->send(data_->severity_, data_->fullname_, data_->basename_,
data_->line_, &data_->tm_time_,
data_->line_, logmsgtime_,
data_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_ -
data_->num_prefix_chars_ - 1),
data_->usecs_);
data_->num_prefix_chars_ - 1) );
}
}
@ -2034,20 +2027,20 @@ void LogSink::WaitTillSent() {
}
string LogSink::ToString(LogSeverity severity, const char* file, int line,
const struct ::tm* tm_time,
const char* message, size_t message_len, int32 usecs) {
const LogMessageTime &logmsgtime,
const char* message, size_t message_len) {
ostringstream stream(string(message, message_len));
stream.fill('0');
stream << LogSeverityNames[severity][0]
<< setw(4) << 1900+tm_time->tm_year
<< setw(2) << 1+tm_time->tm_mon
<< setw(2) << tm_time->tm_mday
<< setw(4) << 1900 + logmsgtime.year()
<< setw(2) << 1 + logmsgtime.month()
<< setw(2) << logmsgtime.day()
<< ' '
<< setw(2) << tm_time->tm_hour << ':'
<< setw(2) << tm_time->tm_min << ':'
<< setw(2) << tm_time->tm_sec << '.'
<< setw(6) << usecs
<< setw(2) << logmsgtime.hour() << ':'
<< setw(2) << logmsgtime.min() << ':'
<< setw(2) << logmsgtime.sec() << '.'
<< setw(6) << logmsgtime.usec()
<< ' '
<< setfill(' ') << setw(5) << GetTID() << setfill('0')
<< ' '
@ -2566,3 +2559,22 @@ void DisableLogCleaner() {
}
_END_GOOGLE_NAMESPACE_
void LogMessageTime::CalcGmtOffset() {
std::tm gmt_struct;
int isDst = 0;
if ( FLAGS_log_utc_time ) {
localtime_r(&timestamp_, &gmt_struct);
isDst = gmt_struct.tm_isdst;
gmt_struct = time_struct_;
} else {
isDst = time_struct_.tm_isdst;
gmtime_r(&timestamp_, &gmt_struct);
}
time_t gmt_sec = mktime(&gmt_struct);
const long hour_secs = 3600;
// If the Daylight Saving Time(isDst) is active subtract an hour from the current timestamp.
gmtoffset_ = static_cast<long int>(timestamp_ - gmt_sec + (isDst ? hour_secs : 0) ) ;
}

View File

@ -526,17 +526,10 @@ class TestLogSinkImpl : public LogSink {
vector<string> errors;
virtual void send(LogSeverity severity, const char* /* full_filename */,
const char* base_filename, int line,
const struct tm* tm_time,
const char* message, size_t message_len, int usecs) {
errors.push_back(
ToString(severity, base_filename, line, tm_time, message, message_len, usecs));
}
virtual void send(LogSeverity severity, const char* full_filename,
const char* base_filename, int line,
const struct tm* tm_time,
const LogMessageTime &logmsgtime,
const char* message, size_t message_len) {
send(severity, full_filename, base_filename, line,
tm_time, message, message_len, 0);
errors.push_back(
ToString(severity, base_filename, line, logmsgtime, message, message_len));
}
};
@ -1154,24 +1147,17 @@ class TestWaitingLogSink : public LogSink {
virtual void send(LogSeverity severity, const char* /* full_filename */,
const char* base_filename, int line,
const struct tm* tm_time,
const char* message, size_t message_len, int usecs) {
const LogMessageTime &logmsgtime,
const char* message, size_t message_len) {
// Push it to Writer thread if we are the original logging thread.
// Note: Something like ThreadLocalLogSink is a better choice
// to do thread-specific LogSink logic for real.
if (pthread_equal(tid_, pthread_self())) {
writer_.Buffer(ToString(severity, base_filename, line,
tm_time, message, message_len, usecs));
logmsgtime, message, message_len));
}
}
virtual void send(LogSeverity severity, const char* full_filename,
const char* base_filename, int line,
const struct tm* tm_time,
const char* message, size_t message_len) {
send(severity, full_filename, base_filename, line, tm_time, message, message_len, 0);
}
virtual void WaitTillSent() {
// Wait for Writer thread if we are the original logging thread.
if (pthread_equal(tid_, pthread_self())) writer_.Wait();
@ -1379,3 +1365,17 @@ TEST(UserDefinedClass, logging) {
// We must be able to compile this.
CHECK_EQ(u, u);
}
TEST(LogMsgTime, gmtoff) {
/*
* Unit test for GMT offset API
* TODO: To properly test this API, we need a platform independent way to set time-zone.
* */
google::LogMessage log_obj(__FILE__, __LINE__);
long int nGmtOff = log_obj.getLogMessageTime().gmtoff();
// GMT offset ranges from UTC-12:00 to UTC+14:00
const long utc_min_offset = -43200;
const long utc_max_offset = 50400;
EXPECT_TRUE( (nGmtOff >= utc_min_offset) && (nGmtOff <= utc_max_offset) );
}

View File

@ -521,17 +521,10 @@ class TestLogSinkImpl : public LogSink {
vector<string> errors;
virtual void send(LogSeverity severity, const char* /* full_filename */,
const char* base_filename, int line,
const struct tm* tm_time,
const char* message, size_t message_len, int usecs) {
errors.push_back(
ToString(severity, base_filename, line, tm_time, message, message_len, usecs));
}
virtual void send(LogSeverity severity, const char* full_filename,
const char* base_filename, int line,
const struct tm* tm_time,
const LogMessageTime &logmsgtime,
const char* message, size_t message_len) {
send(severity, full_filename, base_filename, line,
tm_time, message, message_len, 0);
errors.push_back(
ToString(severity, base_filename, line, logmsgtime, message, message_len));
}
};
@ -1242,24 +1235,17 @@ class TestWaitingLogSink : public LogSink {
virtual void send(LogSeverity severity, const char* /* full_filename */,
const char* base_filename, int line,
const struct tm* tm_time,
const char* message, size_t message_len, int usecs) {
const LogMessageTime &logmsgtime,
const char* message, size_t message_len) {
// Push it to Writer thread if we are the original logging thread.
// Note: Something like ThreadLocalLogSink is a better choice
// to do thread-specific LogSink logic for real.
if (pthread_equal(tid_, pthread_self())) {
writer_.Buffer(ToString(severity, base_filename, line,
tm_time, message, message_len, usecs));
logmsgtime, message, message_len));
}
}
virtual void send(LogSeverity severity, const char* full_filename,
const char* base_filename, int line,
const struct tm* tm_time,
const char* message, size_t message_len) {
send(severity, full_filename, base_filename, line, tm_time, message, message_len, 0);
}
virtual void WaitTillSent() {
// Wait for Writer thread if we are the original logging thread.
if (pthread_equal(tid_, pthread_self())) writer_.Wait();

View File

@ -116,7 +116,7 @@ class ScopedMockLog : public GOOGLE_NAMESPACE::LogSink {
virtual void send(GOOGLE_NAMESPACE::LogSeverity severity,
const char* full_filename,
const char* /*base_filename*/, int /*line*/,
const tm* /*tm_time*/,
const LogMessageTime & /*logmsgtime*/,
const char* message, size_t message_len) {
// We are only interested in the log severity, full file name, and
// log message.