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> Sergiu Deitsch <sergiu.deitsch@gmail.com>
tbennun <tbennun@gmail.com> tbennun <tbennun@gmail.com>
Teddy Reed <teddy@prosauce.org> Teddy Reed <teddy@prosauce.org>
Vijaymahantesh Sattigeri <vijay.thread.temp@gmail.com>
Zhongming Qu <qzmfranklin@gmail.com> Zhongming Qu <qzmfranklin@gmail.com>
Zhuoran Shen <cmsflash99@gmail.com> Zhuoran Shen <cmsflash99@gmail.com>

View File

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

View File

@ -135,30 +135,40 @@ typedef unsigned __int64 uint64;
@ac_google_end_namespace@ @ac_google_end_namespace@
#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
struct LogMessageTime { struct LogMessageTime {
explicit LogMessageTime (const struct::tm& time_struct_, LogMessageTime(): time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
const time_t& timestamp_, const int32_t& usecs_):
time_struct(time_struct_), ts(timestamp_), usecs(usecs_) {}
const time_t& timestamp() const { return ts; } void setTimeInfo(struct::tm time_struct, time_t timestamp, int32_t usecs){
const int& sec() const { return time_struct.tm_sec; } time_struct_ = time_struct;
const int32_t& usec() const { return usecs; } timestamp_ = timestamp;
const int& (min)() const { return time_struct.tm_min; } usecs_ = usecs;
const int& hour() const { return time_struct.tm_hour; }
const int& day() const { return time_struct.tm_mday; } CalcGmtOffset();
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 time_t& timestamp() const { return timestamp_; }
const int& dayInYear() const { return time_struct.tm_yday; } const int& sec() const { return time_struct_.tm_sec; }
const int& dst() const { return time_struct.tm_isdst; } 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: private:
const struct::tm& time_struct; struct::tm time_struct_; // Time of creation of LogMessage
const time_t& ts; time_t timestamp_; // Time of creation of LogMessage in seconds
const int32_t& usecs; int32_t usecs_; // Time of creation of LogMessage - microseconds part
long int gmtoffset_;
void CalcGmtOffset();
}; };
#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
struct LogMessageInfo { struct LogMessageInfo {
explicit LogMessageInfo(const char* const severity_, explicit LogMessageInfo(const char* const severity_,
const char* const filename_, const char* const filename_,
@ -1552,6 +1562,10 @@ public:
// Must be called without the log_mutex held. (L < log_mutex) // Must be called without the log_mutex held. (L < log_mutex)
static int64 num_messages(int severity); static int64 num_messages(int severity);
const LogMessageTime& getLogMessageTime() const {
return logmsgtime_;
}
struct LogMessageData; struct LogMessageData;
private: private:
@ -1577,6 +1591,7 @@ private:
// LogMessage uses less stack space. // LogMessage uses less stack space.
LogMessageData* allocated_; LogMessageData* allocated_;
LogMessageData* data_; LogMessageData* data_;
LogMessageTime logmsgtime_;
friend class LogDestination; friend class LogDestination;
@ -1721,17 +1736,7 @@ class GOOGLE_GLOG_DLL_DECL LogSink {
// during this call. // during this call.
virtual void send(LogSeverity severity, const char* full_filename, virtual void send(LogSeverity severity, const char* full_filename,
const char* base_filename, int line, const char* base_filename, int line,
const struct ::tm* tm_time, const LogMessageTime &logmsgtime,
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 char* message, size_t message_len) = 0; const char* message, size_t message_len) = 0;
// Redefine this to implement waiting for // 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. // Returns the normal text output of the log message.
// Can be useful to implement send(). // Can be useful to implement send().
static std::string ToString(LogSeverity severity, const char* file, int line, static std::string ToString(LogSeverity severity, const char* file, int line,
const struct ::tm* tm_time, const LogMessageTime &logmsgtime,
const char* message, size_t message_len, 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);
}
}; };
// Add or remove a LogSink as a consumer of logging data. Thread-safe. // 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::vector<std::string>* outvec_; // NULL or vector to push message onto
std::string* message_; // NULL or string to write message into 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_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_log_; // # of chars of msg to send to log
size_t num_chars_to_syslog_; // # of chars of msg to send to syslog 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 *full_filename,
const char *base_filename, const char *base_filename,
int line, int line,
const struct ::tm* tm_time, const LogMessageTime &logmsgtime,
const char* message, const char* message,
size_t message_len, size_t message_len);
int32 usecs);
// Wait for all registered sinks via WaitTillSent // Wait for all registered sinks via WaitTillSent
// including the optional one in "data". // including the optional one in "data".
@ -854,15 +850,14 @@ inline void LogDestination::LogToSinks(LogSeverity severity,
const char *full_filename, const char *full_filename,
const char *base_filename, const char *base_filename,
int line, int line,
const struct ::tm* tm_time, const LogMessageTime &logmsgtime,
const char* message, const char* message,
size_t message_len, size_t message_len) {
int32 usecs) {
ReaderMutexLock l(&sink_mutex_); ReaderMutexLock l(&sink_mutex_);
if (sinks_) { if (sinks_) {
for (size_t i = sinks_->size(); i-- > 0; ) { for (size_t i = sinks_->size(); i-- > 0; ) {
(*sinks_)[i]->send(severity, full_filename, base_filename, (*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_->sink_ = NULL;
data_->outvec_ = NULL; data_->outvec_ = NULL;
WallTime now = WallTime_Now(); 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) if(FLAGS_log_utc_time)
gmtime_r(&data_->timestamp_, &data_->tm_time_); gmtime_r(&timestamp_now, &time_struct);
else else
localtime_r(&data_->timestamp_, &data_->tm_time_); localtime_r(&timestamp_now, &time_struct);
data_->usecs_ = static_cast<int32>((now - data_->timestamp_) * 1000000);
logmsgtime_.setTimeInfo(time_struct, timestamp_now,
static_cast<int32>((now - timestamp_now) * 1000000));
data_->num_chars_to_log_ = 0; data_->num_chars_to_log_ = 0;
data_->num_chars_to_syslog_ = 0; data_->num_chars_to_syslog_ = 0;
@ -1633,14 +1631,14 @@ void LogMessage::Init(const char* file,
if (custom_prefix_callback == NULL) { if (custom_prefix_callback == NULL) {
#endif #endif
stream() << LogSeverityNames[severity][0] stream() << LogSeverityNames[severity][0]
<< setw(4) << 1900+data_->tm_time_.tm_year << setw(4) << 1900 + logmsgtime_.year()
<< setw(2) << 1+data_->tm_time_.tm_mon << setw(2) << 1 + logmsgtime_.month()
<< setw(2) << data_->tm_time_.tm_mday << setw(2) << logmsgtime_.day()
<< ' ' << ' '
<< setw(2) << data_->tm_time_.tm_hour << ':' << setw(2) << logmsgtime_.hour() << ':'
<< setw(2) << data_->tm_time_.tm_min << ':' << setw(2) << logmsgtime_.min() << ':'
<< setw(2) << data_->tm_time_.tm_sec << "." << setw(2) << logmsgtime_.sec() << "."
<< setw(6) << data_->usecs_ << setw(6) << logmsgtime_.usec()
<< ' ' << ' '
<< setfill(' ') << setw(5) << setfill(' ') << setw(5)
<< static_cast<unsigned int>(GetTID()) << setfill('0') << static_cast<unsigned int>(GetTID()) << setfill('0')
@ -1652,9 +1650,7 @@ void LogMessage::Init(const char* file,
stream(), stream(),
LogMessageInfo(LogSeverityNames[severity], LogMessageInfo(LogSeverityNames[severity],
data_->basename_, data_->line_, GetTID(), data_->basename_, data_->line_, GetTID(),
LogMessageTime(data_->tm_time_, logmsgtime_),
data_->timestamp_,
data_->usecs_)),
custom_prefix_callback_data custom_prefix_callback_data
); );
stream() << " "; stream() << " ";
@ -1800,15 +1796,14 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
// this could be protected by a flag if necessary. // this could be protected by a flag if necessary.
LogDestination::LogToSinks(data_->severity_, LogDestination::LogToSinks(data_->severity_,
data_->fullname_, data_->basename_, data_->fullname_, data_->basename_,
data_->line_, &data_->tm_time_, data_->line_, logmsgtime_,
data_->message_text_ + data_->num_prefix_chars_, data_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_ - (data_->num_chars_to_log_ -
data_->num_prefix_chars_ - 1), data_->num_prefix_chars_ - 1) );
data_->usecs_);
} else { } else {
// log this message to all log files of severity <= severity_ // 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_->message_text_,
data_->num_chars_to_log_); data_->num_chars_to_log_);
@ -1819,11 +1814,10 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
data_->num_chars_to_log_); data_->num_chars_to_log_);
LogDestination::LogToSinks(data_->severity_, LogDestination::LogToSinks(data_->severity_,
data_->fullname_, data_->basename_, data_->fullname_, data_->basename_,
data_->line_, &data_->tm_time_, data_->line_, logmsgtime_,
data_->message_text_ + data_->num_prefix_chars_, data_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_ (data_->num_chars_to_log_
- data_->num_prefix_chars_ - 1), - data_->num_prefix_chars_ - 1) );
data_->usecs_);
// NOTE: -1 removes trailing \n // NOTE: -1 removes trailing \n
} }
@ -1842,7 +1836,7 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
sizeof(fatal_message)-1); sizeof(fatal_message)-1);
memcpy(fatal_message, data_->message_text_, copy); memcpy(fatal_message, data_->message_text_, copy);
fatal_message[copy] = '\0'; fatal_message[copy] = '\0';
fatal_time = data_->timestamp_; fatal_time = logmsgtime_.timestamp();
} }
if (!FLAGS_logtostderr) { if (!FLAGS_logtostderr) {
@ -1904,11 +1898,10 @@ void LogMessage::SendToSink() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
RAW_DCHECK(data_->num_chars_to_log_ > 0 && RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
data_->message_text_[data_->num_chars_to_log_-1] == '\n', ""); data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
data_->sink_->send(data_->severity_, data_->fullname_, data_->basename_, 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_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_ - (data_->num_chars_to_log_ -
data_->num_prefix_chars_ - 1), data_->num_prefix_chars_ - 1) );
data_->usecs_);
} }
} }
@ -2034,20 +2027,20 @@ void LogSink::WaitTillSent() {
} }
string LogSink::ToString(LogSeverity severity, const char* file, int line, string LogSink::ToString(LogSeverity severity, const char* file, int line,
const struct ::tm* tm_time, const LogMessageTime &logmsgtime,
const char* message, size_t message_len, int32 usecs) { const char* message, size_t message_len) {
ostringstream stream(string(message, message_len)); ostringstream stream(string(message, message_len));
stream.fill('0'); stream.fill('0');
stream << LogSeverityNames[severity][0] stream << LogSeverityNames[severity][0]
<< setw(4) << 1900+tm_time->tm_year << setw(4) << 1900 + logmsgtime.year()
<< setw(2) << 1+tm_time->tm_mon << setw(2) << 1 + logmsgtime.month()
<< setw(2) << tm_time->tm_mday << setw(2) << logmsgtime.day()
<< ' ' << ' '
<< setw(2) << tm_time->tm_hour << ':' << setw(2) << logmsgtime.hour() << ':'
<< setw(2) << tm_time->tm_min << ':' << setw(2) << logmsgtime.min() << ':'
<< setw(2) << tm_time->tm_sec << '.' << setw(2) << logmsgtime.sec() << '.'
<< setw(6) << usecs << setw(6) << logmsgtime.usec()
<< ' ' << ' '
<< setfill(' ') << setw(5) << GetTID() << setfill('0') << setfill(' ') << setw(5) << GetTID() << setfill('0')
<< ' ' << ' '
@ -2566,3 +2559,22 @@ void DisableLogCleaner() {
} }
_END_GOOGLE_NAMESPACE_ _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; vector<string> errors;
virtual void send(LogSeverity severity, const char* /* full_filename */, virtual void send(LogSeverity severity, const char* /* full_filename */,
const char* base_filename, int line, const char* base_filename, int line,
const struct tm* tm_time, const LogMessageTime &logmsgtime,
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 char* message, size_t message_len) { const char* message, size_t message_len) {
send(severity, full_filename, base_filename, line, errors.push_back(
tm_time, message, message_len, 0); 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 */, virtual void send(LogSeverity severity, const char* /* full_filename */,
const char* base_filename, int line, const char* base_filename, int line,
const struct tm* tm_time, const LogMessageTime &logmsgtime,
const char* message, size_t message_len, int usecs) { const char* message, size_t message_len) {
// Push it to Writer thread if we are the original logging thread. // Push it to Writer thread if we are the original logging thread.
// Note: Something like ThreadLocalLogSink is a better choice // Note: Something like ThreadLocalLogSink is a better choice
// to do thread-specific LogSink logic for real. // to do thread-specific LogSink logic for real.
if (pthread_equal(tid_, pthread_self())) { if (pthread_equal(tid_, pthread_self())) {
writer_.Buffer(ToString(severity, base_filename, line, 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() { virtual void WaitTillSent() {
// Wait for Writer thread if we are the original logging thread. // Wait for Writer thread if we are the original logging thread.
if (pthread_equal(tid_, pthread_self())) writer_.Wait(); if (pthread_equal(tid_, pthread_self())) writer_.Wait();
@ -1379,3 +1365,17 @@ TEST(UserDefinedClass, logging) {
// We must be able to compile this. // We must be able to compile this.
CHECK_EQ(u, u); 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; vector<string> errors;
virtual void send(LogSeverity severity, const char* /* full_filename */, virtual void send(LogSeverity severity, const char* /* full_filename */,
const char* base_filename, int line, const char* base_filename, int line,
const struct tm* tm_time, const LogMessageTime &logmsgtime,
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 char* message, size_t message_len) { const char* message, size_t message_len) {
send(severity, full_filename, base_filename, line, errors.push_back(
tm_time, message, message_len, 0); 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 */, virtual void send(LogSeverity severity, const char* /* full_filename */,
const char* base_filename, int line, const char* base_filename, int line,
const struct tm* tm_time, const LogMessageTime &logmsgtime,
const char* message, size_t message_len, int usecs) { const char* message, size_t message_len) {
// Push it to Writer thread if we are the original logging thread. // Push it to Writer thread if we are the original logging thread.
// Note: Something like ThreadLocalLogSink is a better choice // Note: Something like ThreadLocalLogSink is a better choice
// to do thread-specific LogSink logic for real. // to do thread-specific LogSink logic for real.
if (pthread_equal(tid_, pthread_self())) { if (pthread_equal(tid_, pthread_self())) {
writer_.Buffer(ToString(severity, base_filename, line, 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() { virtual void WaitTillSent() {
// Wait for Writer thread if we are the original logging thread. // Wait for Writer thread if we are the original logging thread.
if (pthread_equal(tid_, pthread_self())) writer_.Wait(); 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, virtual void send(GOOGLE_NAMESPACE::LogSeverity severity,
const char* full_filename, const char* full_filename,
const char* /*base_filename*/, int /*line*/, const char* /*base_filename*/, int /*line*/,
const tm* /*tm_time*/, const LogMessageTime & /*logmsgtime*/,
const char* message, size_t message_len) { const char* message, size_t message_len) {
// We are only interested in the log severity, full file name, and // We are only interested in the log severity, full file name, and
// log message. // log message.