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:
parent
ee6faf13b2
commit
ef36f800ed
1
AUTHORS
1
AUTHORS
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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.
|
||||
|
||||
100
src/logging.cc
100
src/logging.cc
@ -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(×tamp_now, &time_struct);
|
||||
else
|
||||
localtime_r(&data_->timestamp_, &data_->tm_time_);
|
||||
data_->usecs_ = static_cast<int32>((now - data_->timestamp_) * 1000000);
|
||||
localtime_r(×tamp_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(×tamp_, &gmt_struct);
|
||||
isDst = gmt_struct.tm_isdst;
|
||||
gmt_struct = time_struct_;
|
||||
} else {
|
||||
isDst = time_struct_.tm_isdst;
|
||||
gmtime_r(×tamp_, &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) ) ;
|
||||
}
|
||||
|
||||
|
||||
@ -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) );
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user