30 #define _GNU_SOURCE 1 // needed for O_NOFOLLOW and pread()/pwrite()
42 #include <sys/types.h>
44 #ifdef HAVE_SYS_UTSNAME_H
45 # include <sys/utsname.h>
62 #ifdef GLOG_OS_WINDOWS
68 #include <glog/logging.h>
69 #include <glog/raw_logging.h>
72 #ifdef HAVE_STACKTRACE
77 #include <android/log.h>
88 using std::ostringstream;
102 #define fdopen _fdopen
106 #define EXCLUSIVE_LOCKS_REQUIRED(mu)
109 const char*
const valstr = getenv(varname);
113 return memchr(
"tTyY1\0", valstr[0], 6) !=
NULL;
117 BoolFromEnv(
"GOOGLE_TIMESTAMP_IN_LOGFILE_NAME",
true),
118 "put a timestamp at the end of the log file name");
120 "log messages go to stderr instead of logfiles");
122 "log messages go to stderr in addition to logfiles");
124 "color messages logged to stderr (if supported by terminal)");
126 "color messages logged to stdout (if supported by terminal)");
128 "log messages go to stdout instead of logfiles");
130 GLOG_DEFINE_bool(drop_log_memory,
true,
"Drop in-memory buffers of log contents. "
131 "Logs can grow very quickly and they are rarely read before they "
132 "need to be evicted from memory. Instead, drop them from memory "
133 "as soon as they are flushed to disk.");
143 "log messages at or above this level are copied to stderr in "
144 "addition to logfiles. This flag obsoletes --alsologtostderr.");
147 "log messages go to these email addresses "
148 "in addition to logfiles");
150 "Prepend the log prefix to the start of each log line");
152 "Include the year in the log prefix");
153 GLOG_DEFINE_int32(minloglevel, 0,
"Messages logged at a lower level than this don't "
154 "actually get logged anywhere");
156 "Buffer log messages logged at this level or lower"
157 " (-1 means don't buffer; 0 means buffer INFO only;"
160 "Buffer log messages for at most this many seconds");
163 "Clean overdue logs every this many seconds");
166 "Email log messages logged at this level or higher"
167 " (0 means email all; 3 means email FATAL only;"
170 "Mailer used to send logging email");
175 env = getenv(
"GOOGLE_LOG_DIR");
176 if (env !=
NULL && env[0] !=
'\0') {
179 env = getenv(
"TEST_TMPDIR");
180 if (env !=
NULL && env[0] !=
'\0') {
189 "If specified, logfiles are written into this directory instead "
190 "of the default logging directory.");
192 "files in this directory");
195 "approx. maximum log file size (in MB). A value of 0 will "
196 "be silently overridden to 1.");
199 "Stop attempting to log to disk if the disk is full.");
202 "Emit a backtrace when logging at file:linenum.");
205 "Use UTC time for logging.");
208 #define PATH_SEPARATOR '/'
211 #if defined(GLOG_OS_WINDOWS)
213 #define ssize_t SSIZE_T
216 off_t orig_offset = lseek(fd, 0, SEEK_CUR);
217 if (orig_offset == (off_t)-1)
219 if (lseek(fd,
offset, SEEK_CUR) == (off_t)-1)
224 if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
228 #endif // !HAVE_PREAD
232 off_t orig_offset = lseek(fd, 0, SEEK_CUR);
233 if (orig_offset == (off_t)-1)
235 if (lseek(fd,
offset, SEEK_CUR) == (off_t)-1)
240 if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
244 #endif // !HAVE_PWRITE
247 #if defined(HAVE_SYS_UTSNAME_H)
249 if (uname(&
buf) < 0) {
251 *
buf.nodename =
'\0';
253 *hostname =
buf.nodename;
254 #elif defined(GLOG_OS_WINDOWS)
255 char buf[MAX_COMPUTERNAME_LENGTH + 1];
256 DWORD
len = MAX_COMPUTERNAME_LENGTH + 1;
257 if (GetComputerNameA(
buf, &
len)) {
263 # warning There is no way to retrieve the host name.
264 *hostname =
"(unknown)";
270 bool term_supports_color =
false;
271 #ifdef GLOG_OS_WINDOWS
274 term_supports_color =
true;
277 const char*
const term = getenv(
"TERM");
278 if (term !=
NULL && term[0] !=
'\0') {
279 term_supports_color =
280 !strcmp(term,
"xterm") ||
281 !strcmp(term,
"xterm-color") ||
282 !strcmp(term,
"xterm-256color") ||
283 !strcmp(term,
"screen-256color") ||
284 !strcmp(term,
"konsole") ||
285 !strcmp(term,
"konsole-16color") ||
286 !strcmp(term,
"konsole-256color") ||
287 !strcmp(term,
"screen") ||
288 !strcmp(term,
"linux") ||
289 !strcmp(term,
"cygwin");
292 return term_supports_color;
325 #ifdef GLOG_OS_WINDOWS
332 case COLOR_YELLOW:
return FOREGROUND_RED | FOREGROUND_GREEN;
350 #endif // GLOG_OS_WINDOWS
354 return (FLAGS_max_log_size > 0 && FLAGS_max_log_size < 4096
361 const size_t LogMessage::kMaxLogMessageLen = 30000;
405 "INFO",
"WARNING",
"ERROR",
"FATAL"
416 const char*body,
bool use_logging);
418 base::Logger::~Logger() {
421 #ifdef GLOG_CUSTOM_PREFIX_SUPPORT
424 CustomPrefixCallback custom_prefix_callback =
NULL;
426 void* custom_prefix_callback_data =
NULL;
433 class LogFileObject :
public base::Logger {
438 virtual void Write(
bool force_flush,
444 void SetBasename(
const char* basename);
445 void SetExtension(
const char* ext);
446 void SetSymlinkBasename(
const char* symlink_basename);
449 virtual void Flush();
453 virtual uint32 LogSize() {
461 void FlushUnlocked();
464 static const uint32 kRolloverAttemptFrequency = 0x20;
467 bool base_filename_selected_;
468 string base_filename_;
469 string symlink_basename_;
470 string filename_extension_;
473 uint32 bytes_since_flush_;
474 uint32 dropped_mem_length_;
476 unsigned int rollover_attempt_;
477 int64 next_flush_time_;
478 WallTime start_time_;
483 bool CreateLogfile(
const string& time_pid_string);
492 void Enable(
unsigned int overdue_days);
496 void UpdateCleanUpTime();
498 void Run(
bool base_filename_selected,
499 const string& base_filename,
500 const string& filename_extension);
502 bool enabled()
const {
return enabled_; }
505 vector<string> GetOverdueLogNames(
string log_directory,
unsigned int days,
506 const string& base_filename,
507 const string& filename_extension)
const;
509 bool IsLogFromCurrentProject(
const string& filepath,
510 const string& base_filename,
511 const string& filename_extension)
const;
513 bool IsLogLastModifiedOver(
const string& filepath,
unsigned int days)
const;
516 unsigned int overdue_days_;
517 int64 next_cleanup_time_;
520 LogCleaner log_cleaner;
533 const char* base_filename);
535 const char* symlink_basename);
565 size_t message_len,
size_t prefix_len);
585 const char* base_filename,
int line,
586 const LogMessageTime& logmsgtime,
const char*
message,
638 const char* base_filename)
639 : fileobject_(
severity, base_filename),
640 logger_(&fileobject_) {
676 const char* base_filename) {
685 const char* symlink_basename) {
697 sinks_->push_back(destination);
724 FLAGS_stderrthreshold = min_severity;
737 const char* addresses) {
750 ((!is_stdout && FLAGS_colorlogtostderr) ||
751 (is_stdout && FLAGS_colorlogtostdout)))
761 #ifdef GLOG_OS_WINDOWS
762 const HANDLE output_handle =
763 GetStdHandle(is_stdout ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
766 CONSOLE_SCREEN_BUFFER_INFO buffer_info;
767 GetConsoleScreenBufferInfo(output_handle, &buffer_info);
768 const WORD old_color_attrs = buffer_info.wAttributes;
774 SetConsoleTextAttribute(output_handle,
775 GetColorAttribute(
color) | FOREGROUND_INTENSITY);
779 SetConsoleTextAttribute(output_handle, old_color_attrs);
783 fprintf(
output,
"\033[m");
784 #endif // GLOG_OS_WINDOWS
792 if (
severity >= FLAGS_stderrthreshold) {
810 const char*
message,
size_t message_len,
size_t prefix_len) {
813 #ifdef GLOG_OS_WINDOWS
817 #elif defined(__ANDROID__)
825 __android_log_write(android_log_levels[
severity],
839 string to(FLAGS_alsologtoemail);
865 const bool should_flush =
severity > FLAGS_logbuflevel;
874 if (FLAGS_logtostdout) {
886 const char* full_filename,
887 const char* base_filename,
int line,
888 const LogMessageTime& logmsgtime,
890 size_t message_len) {
893 for (
size_t i =
sinks_->size();
i-- > 0; ) {
894 (*sinks_)[
i]->send(
severity, full_filename, base_filename,
895 line, logmsgtime,
message, message_len);
903 for (
size_t i =
sinks_->size();
i-- > 0; ) {
904 (*sinks_)[
i]->WaitTillSent();
907 const bool send_to_sink =
908 (
data->send_method_ == &LogMessage::SendToSink) ||
909 (
data->send_method_ == &LogMessage::SendToSinkAndLog);
910 if (send_to_sink &&
data->sink_ !=
NULL) {
911 data->sink_->WaitTillSent();
942 g_application_fingerprint = fingerprint;
948 #ifdef GLOG_OS_WINDOWS
949 const char possible_dir_delim[] = {
'\\',
'/'};
951 const char possible_dir_delim[] = {
'/'};
954 string PrettyDuration(
int secs) {
955 std::stringstream result;
956 int mins = secs / 60;
957 int hours = mins / 60;
961 result << hours <<
':' << setw(2) << mins <<
':' << setw(2) << secs;
967 const char* base_filename)
968 : base_filename_selected_(base_filename !=
NULL),
969 base_filename_((base_filename !=
NULL) ? base_filename :
""),
971 filename_extension_(),
974 bytes_since_flush_(0),
975 dropped_mem_length_(0),
977 rollover_attempt_(kRolloverAttemptFrequency-1),
984 LogFileObject::~LogFileObject() {
992 void LogFileObject::SetBasename(
const char* basename) {
994 base_filename_selected_ =
true;
995 if (base_filename_ != basename) {
1000 rollover_attempt_ = kRolloverAttemptFrequency-1;
1002 base_filename_ = basename;
1006 void LogFileObject::SetExtension(
const char* ext) {
1008 if (filename_extension_ != ext) {
1013 rollover_attempt_ = kRolloverAttemptFrequency-1;
1015 filename_extension_ = ext;
1019 void LogFileObject::SetSymlinkBasename(
const char* symlink_basename) {
1021 symlink_basename_ = symlink_basename;
1024 void LogFileObject::Flush() {
1029 void LogFileObject::FlushUnlocked(){
1032 bytes_since_flush_ = 0;
1036 *
static_cast<int64>(1000000));
1040 bool LogFileObject::CreateLogfile(
const string& time_pid_string) {
1041 string string_filename = base_filename_;
1042 if (FLAGS_timestamp_in_logfile_name) {
1043 string_filename += time_pid_string;
1045 string_filename += filename_extension_;
1046 const char* filename = string_filename.c_str();
1048 int flags = O_WRONLY | O_CREAT;
1049 if (FLAGS_timestamp_in_logfile_name) {
1053 int fd = open(filename,
flags, FLAGS_logfile_mode);
1054 if (fd == -1)
return false;
1057 fcntl(fd, F_SETFD, FD_CLOEXEC);
1068 static struct flock w_lock;
1070 w_lock.l_type = F_WRLCK;
1072 w_lock.l_whence = SEEK_SET;
1075 int wlock_ret = fcntl(fd, F_SETLK, &w_lock);
1076 if (wlock_ret == -1) {
1083 file_ = fdopen(fd,
"a");
1086 if (FLAGS_timestamp_in_logfile_name) {
1091 #ifdef GLOG_OS_WINDOWS
1094 if (!FLAGS_timestamp_in_logfile_name) {
1095 if (fseek(
file_, 0, SEEK_END) != 0) {
1105 if (!symlink_basename_.empty()) {
1108 const string linkname =
1111 if ( slash ) linkpath =
string(filename,
static_cast<size_t>(slash-filename+1));
1112 linkpath += linkname;
1113 unlink(linkpath.c_str());
1115 #if defined(GLOG_OS_WINDOWS)
1117 #elif defined(HAVE_UNISTD_H)
1121 const char *linkdest = slash ? (slash + 1) : filename;
1122 if (symlink(linkdest, linkpath.c_str()) != 0) {
1128 if (!FLAGS_log_link.empty()) {
1129 linkpath = FLAGS_log_link +
"/" + linkname;
1130 unlink(linkpath.c_str());
1131 if (symlink(filename, linkpath.c_str()) != 0) {
1144 size_t message_len) {
1148 if (base_filename_selected_ && base_filename_.empty()) {
1155 file_length_ = bytes_since_flush_ = dropped_mem_length_ = 0;
1156 rollover_attempt_ = kRolloverAttemptFrequency - 1;
1164 if (++rollover_attempt_ != kRolloverAttemptFrequency)
return;
1165 rollover_attempt_ = 0;
1167 struct ::tm tm_time;
1168 if (FLAGS_log_utc_time) {
1175 ostringstream time_pid_stream;
1176 time_pid_stream.fill(
'0');
1177 time_pid_stream << 1900+tm_time.tm_year
1178 << setw(2) << 1+tm_time.tm_mon
1179 << setw(2) << tm_time.tm_mday
1181 << setw(2) << tm_time.tm_hour
1182 << setw(2) << tm_time.tm_min
1183 << setw(2) << tm_time.tm_sec
1186 const string& time_pid_string = time_pid_stream.str();
1188 if (base_filename_selected_) {
1189 if (!CreateLogfile(time_pid_string)) {
1190 perror(
"Could not create log file");
1191 fprintf(stderr,
"COULD NOT CREATE LOGFILE '%s'!\n",
1192 time_pid_string.c_str());
1207 string stripped_filename(
1217 if (uidname.empty()) uidname =
"invalid-user";
1219 stripped_filename = stripped_filename+
'.'+hostname+
'.'
1227 bool success =
false;
1228 for (vector<string>::const_iterator dir = log_dirs.begin();
1229 dir != log_dirs.end();
1231 base_filename_ = *dir +
"/" + stripped_filename;
1232 if ( CreateLogfile(time_pid_string) ) {
1238 if ( success ==
false ) {
1239 perror(
"Could not create logging file");
1240 fprintf(stderr,
"COULD NOT CREATE A LOGGINGFILE %s!",
1241 time_pid_string.c_str());
1247 ostringstream file_header_stream;
1248 file_header_stream.fill(
'0');
1249 file_header_stream <<
"Log file created at: "
1250 << 1900+tm_time.tm_year <<
'/'
1251 << setw(2) << 1+tm_time.tm_mon <<
'/'
1252 << setw(2) << tm_time.tm_mday
1254 << setw(2) << tm_time.tm_hour <<
':'
1255 << setw(2) << tm_time.tm_min <<
':'
1256 << setw(2) << tm_time.tm_sec << (FLAGS_log_utc_time ?
" UTC\n" :
"\n")
1257 <<
"Running on machine: "
1260 if(!g_application_fingerprint.empty()) {
1261 file_header_stream <<
"Application fingerprint: " << g_application_fingerprint <<
'\n';
1263 const char*
const date_time_format = FLAGS_log_year_in_prefix
1264 ?
"yyyymmdd hh:mm:ss.uuuuuu"
1265 :
"mmdd hh:mm:ss.uuuuuu";
1266 file_header_stream <<
"Running duration (h:mm:ss): "
1267 << PrettyDuration(
static_cast<int>(
WallTime_Now() - start_time_)) <<
'\n'
1268 <<
"Log line format: [IWEF]" << date_time_format <<
" "
1269 <<
"threadid file:line] msg" <<
'\n';
1270 const string& file_header_string = file_header_stream.str();
1272 const size_t header_len = file_header_string.size();
1273 fwrite(file_header_string.data(), 1, header_len,
file_);
1274 file_length_ += header_len;
1275 bytes_since_flush_ += header_len;
1287 if ( FLAGS_stop_logging_if_full_disk &&
1292 file_length_ += message_len;
1293 bytes_since_flush_ += message_len;
1305 (bytes_since_flush_ >= 1000000) ||
1308 #ifdef GLOG_OS_LINUX
1310 if (FLAGS_drop_log_memory && file_length_ >= (3U << 20U)) {
1313 uint32 total_drop_length =
1314 (file_length_ & ~((1U << 20U) - 1U)) - (1U << 20U);
1315 uint32 this_drop_length = total_drop_length - dropped_mem_length_;
1316 if (this_drop_length >= (2U << 20U)) {
1318 # if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
1322 posix_fadvise(fileno(
file_), dropped_mem_length_, this_drop_length,
1323 POSIX_FADV_DONTNEED);
1325 dropped_mem_length_ = total_drop_length;
1331 if (log_cleaner.enabled()) {
1332 log_cleaner.Run(base_filename_selected_,
1334 filename_extension_);
1339 LogCleaner::LogCleaner() : enabled_(
false), overdue_days_(7), next_cleanup_time_(0) {}
1341 void LogCleaner::Enable(
unsigned int overdue_days) {
1343 overdue_days_ = overdue_days;
1346 void LogCleaner::Disable() {
1350 void LogCleaner::UpdateCleanUpTime() {
1357 const string& base_filename,
1358 const string& filename_extension) {
1360 assert(!base_filename_selected || !base_filename.empty());
1366 UpdateCleanUpTime();
1368 vector<string> dirs;
1370 if (!base_filename_selected) {
1373 size_t pos = base_filename.find_last_of(possible_dir_delim, string::npos,
1374 sizeof(possible_dir_delim));
1375 if (pos != string::npos) {
1376 string dir = base_filename.substr(0, pos + 1);
1377 dirs.push_back(dir);
1379 dirs.push_back(
".");
1383 for (
size_t i = 0;
i < dirs.size();
i++) {
1384 vector<string> logs = GetOverdueLogNames(dirs[
i],
1387 filename_extension);
1388 for (
size_t j = 0; j < logs.size(); j++) {
1389 static_cast<void>(unlink(logs[j].c_str()));
1394 vector<string> LogCleaner::GetOverdueLogNames(
1395 string log_directory,
unsigned int days,
const string& base_filename,
1396 const string& filename_extension)
const {
1398 vector<string> overdue_log_names;
1404 if ((dir =
opendir(log_directory.c_str()))) {
1405 while ((ent =
readdir(dir))) {
1406 if (strcmp(ent->
d_name,
".") == 0 || strcmp(ent->
d_name,
"..") == 0) {
1410 string filepath = ent->
d_name;
1411 const char*
const dir_delim_end =
1412 possible_dir_delim +
sizeof(possible_dir_delim);
1414 if (!log_directory.empty() &&
1415 std::find(possible_dir_delim, dir_delim_end,
1416 log_directory[log_directory.size() - 1]) != dir_delim_end) {
1417 filepath = log_directory + filepath;
1420 if (IsLogFromCurrentProject(filepath, base_filename, filename_extension) &&
1421 IsLogLastModifiedOver(filepath, days)) {
1422 overdue_log_names.push_back(filepath);
1428 return overdue_log_names;
1431 bool LogCleaner::IsLogFromCurrentProject(
const string& filepath,
1432 const string& base_filename,
1433 const string& filename_extension)
const {
1437 string cleaned_base_filename;
1439 const char*
const dir_delim_end =
1440 possible_dir_delim +
sizeof(possible_dir_delim);
1442 size_t real_filepath_size = filepath.size();
1443 for (
size_t i = 0;
i < base_filename.size(); ++
i) {
1444 const char& c = base_filename[
i];
1446 if (cleaned_base_filename.empty()) {
1447 cleaned_base_filename += c;
1448 }
else if (std::find(possible_dir_delim, dir_delim_end, c) ==
1450 (!cleaned_base_filename.empty() &&
1451 c != cleaned_base_filename[cleaned_base_filename.size() - 1])) {
1452 cleaned_base_filename += c;
1457 if (filepath.find(cleaned_base_filename) != 0) {
1464 if (!filename_extension.empty()) {
1465 if (cleaned_base_filename.size() >= real_filepath_size) {
1469 string ext = filepath.substr(cleaned_base_filename.size(), filename_extension.size());
1470 if (ext == filename_extension) {
1471 cleaned_base_filename += filename_extension;
1475 if (filename_extension.size() >= real_filepath_size) {
1478 real_filepath_size = filepath.size() - filename_extension.size();
1479 if (filepath.substr(real_filepath_size) != filename_extension) {
1487 for (
size_t i = cleaned_base_filename.size();
i < real_filepath_size;
i++) {
1488 const char& c = filepath[
i];
1490 if (
i <= cleaned_base_filename.size() + 7) {
1491 if (c < '0' || c >
'9') {
return false; }
1493 }
else if (
i == cleaned_base_filename.size() + 8) {
1494 if (c !=
'-') {
return false; }
1496 }
else if (
i <= cleaned_base_filename.size() + 14) {
1497 if (c < '0' || c >
'9') {
return false; }
1499 }
else if (
i == cleaned_base_filename.size() + 15) {
1500 if (c !=
'.') {
return false; }
1502 }
else if (
i >= cleaned_base_filename.size() + 16) {
1503 if (c < '0' || c >
'9') {
return false; }
1510 bool LogCleaner::IsLogLastModifiedOver(
const string& filepath,
1511 unsigned int days)
const {
1513 struct stat file_stat;
1515 if (stat(filepath.c_str(), &file_stat) == 0) {
1516 const time_t seconds_in_a_day = 60 * 60 * 24;
1517 time_t last_modified_time = file_stat.st_mtime;
1518 time_t current_time = time(
NULL);
1519 return difftime(current_time, last_modified_time) > days * seconds_in_a_day;
1540 #ifdef GLOG_THREAD_LOCAL_STORAGE
1544 static GLOG_THREAD_LOCAL_STORAGE
bool thread_data_available =
true;
1546 #if defined(HAVE_ALIGNED_STORAGE) && __cplusplus >= 201103L
1547 static GLOG_THREAD_LOCAL_STORAGE
1551 static GLOG_THREAD_LOCAL_STORAGE
1553 #endif // HAVE_ALIGNED_STORAGE
1554 #endif // defined(GLOG_THREAD_LOCAL_STORAGE)
1557 : stream_(message_text_,
LogMessage::kMaxLogMessageLen, 0) {
1562 : allocated_(
NULL) {
1564 data_->stream_.set_ctr(ctr);
1567 LogMessage::LogMessage(
const char* file,
int line,
1568 const CheckOpString& result)
1569 : allocated_(
NULL) {
1571 stream() <<
"Check failed: " << (*result.str_) <<
" ";
1574 LogMessage::LogMessage(
const char* file,
int line)
1575 : allocated_(
NULL) {
1580 : allocated_(
NULL) {
1585 LogSink* sink,
bool also_send_to_log)
1586 : allocated_(
NULL) {
1587 Init(file, line,
severity, also_send_to_log ? &LogMessage::SendToSinkAndLog :
1588 &LogMessage::SendToSink);
1589 data_->sink_ = sink;
1593 vector<string> *outvec)
1594 : allocated_(
NULL) {
1595 Init(file, line,
severity, &LogMessage::SaveOrSendToLog);
1596 data_->outvec_ = outvec;
1601 : allocated_(
NULL) {
1602 Init(file, line,
severity, &LogMessage::WriteToStringAndLog);
1612 #ifdef GLOG_THREAD_LOCAL_STORAGE
1614 if (thread_data_available) {
1615 thread_data_available =
false;
1616 #ifdef HAVE_ALIGNED_STORAGE
1617 data_ =
new (&thread_msg_data) LogMessageData;
1619 const uintptr_t kAlign =
sizeof(
void*) - 1;
1622 reinterpret_cast<char*
>(
reinterpret_cast<uintptr_t
>(thread_msg_data + kAlign) & ~kAlign);
1623 data_ =
new (align_ptr) LogMessageData;
1624 assert(
reinterpret_cast<uintptr_t
>(align_ptr) %
sizeof(
void*) == 0);
1627 allocated_ =
new LogMessageData();
1630 #else // !defined(GLOG_THREAD_LOCAL_STORAGE)
1631 allocated_ =
new LogMessageData();
1633 #endif // defined(GLOG_THREAD_LOCAL_STORAGE)
1634 data_->first_fatal_ =
false;
1640 data_->first_fatal_ =
true;
1643 data_->first_fatal_ =
false;
1649 data_->line_ = line;
1650 data_->send_method_ = send_method;
1654 time_t timestamp_now =
static_cast<time_t
>(now);
1655 logmsgtime_ = LogMessageTime(timestamp_now, now);
1657 data_->num_chars_to_log_ = 0;
1658 data_->num_chars_to_syslog_ = 0;
1660 data_->fullname_ = file;
1661 data_->has_been_flushed_ =
false;
1667 if (FLAGS_log_prefix && (line != kNoLogPrefix)) {
1668 std::ios saved_fmt(
NULL);
1669 saved_fmt.copyfmt(
stream());
1671 #ifdef GLOG_CUSTOM_PREFIX_SUPPORT
1672 if (custom_prefix_callback ==
NULL) {
1675 if (FLAGS_log_year_in_prefix) {
1676 stream() << setw(4) << 1900 + logmsgtime_.year();
1678 stream() << setw(2) << 1 + logmsgtime_.month()
1679 << setw(2) << logmsgtime_.day()
1681 << setw(2) << logmsgtime_.hour() <<
':'
1682 << setw(2) << logmsgtime_.min() <<
':'
1683 << setw(2) << logmsgtime_.sec() <<
"."
1684 << setw(6) << logmsgtime_.usec()
1686 << setfill(
' ') << setw(5)
1687 <<
static_cast<unsigned int>(
GetTID()) << setfill(
'0')
1689 <<
data_->basename_ <<
':' <<
data_->line_ <<
"] ";
1690 #ifdef GLOG_CUSTOM_PREFIX_SUPPORT
1692 custom_prefix_callback(
1697 custom_prefix_callback_data
1702 stream().copyfmt(saved_fmt);
1704 data_->num_prefix_chars_ =
data_->stream_.pcount();
1706 if (!FLAGS_log_backtrace_at.empty()) {
1708 snprintf(fileline,
sizeof(fileline),
"%s:%d",
data_->basename_, line);
1709 #ifdef HAVE_STACKTRACE
1710 if (FLAGS_log_backtrace_at == fileline) {
1713 stream() <<
" (stacktrace:\n" << stacktrace <<
") ";
1719 const LogMessageTime& LogMessage::getLogMessageTime()
const {
1723 LogMessage::~LogMessage() {
1725 #ifdef GLOG_THREAD_LOCAL_STORAGE
1726 if (
data_ ==
static_cast<void*
>(&thread_msg_data)) {
1727 data_->~LogMessageData();
1728 thread_data_available =
true;
1733 #else // !defined(GLOG_THREAD_LOCAL_STORAGE)
1735 #endif // defined(GLOG_THREAD_LOCAL_STORAGE)
1738 int LogMessage::preserved_errno()
const {
1739 return data_->preserved_errno_;
1743 return data_->stream_;
1748 void LogMessage::Flush() {
1749 if (
data_->has_been_flushed_ ||
data_->severity_ < FLAGS_minloglevel) {
1753 data_->num_chars_to_log_ =
data_->stream_.pcount();
1754 data_->num_chars_to_syslog_ =
1755 data_->num_chars_to_log_ -
data_->num_prefix_chars_;
1758 bool append_newline =
1759 (
data_->message_text_[
data_->num_chars_to_log_-1] !=
'\n');
1760 char original_final_char =
'\0';
1767 if (append_newline) {
1768 original_final_char =
data_->message_text_[
data_->num_chars_to_log_];
1769 data_->message_text_[
data_->num_chars_to_log_++] =
'\n';
1771 data_->message_text_[
data_->num_chars_to_log_] =
'\0';
1777 (this->*(
data_->send_method_))();
1778 ++num_messages_[
static_cast<int>(
data_->severity_)];
1782 if (append_newline) {
1785 data_->message_text_[
data_->num_chars_to_log_-1] = original_final_char;
1793 if (
data_->preserved_errno_ != 0) {
1799 data_->has_been_flushed_ =
true;
1821 static bool already_warned_before_initgoogle =
false;
1825 RAW_DCHECK(
data_->num_chars_to_log_ > 0 &&
1826 data_->message_text_[
data_->num_chars_to_log_-1] ==
'\n',
"");
1831 const char w[] =
"WARNING: Logging before InitGoogleLogging() is "
1832 "written to STDERR\n";
1834 already_warned_before_initgoogle =
true;
1841 if (FLAGS_logtostdout) {
1843 data_->num_chars_to_log_);
1846 data_->num_chars_to_log_);
1852 data_->line_, logmsgtime_,
1853 data_->message_text_ +
data_->num_prefix_chars_,
1854 (
data_->num_chars_to_log_ -
1855 data_->num_prefix_chars_ - 1) );
1859 data_->message_text_,
1860 data_->num_chars_to_log_);
1863 data_->num_chars_to_log_,
1864 data_->num_prefix_chars_);
1866 data_->num_chars_to_log_);
1869 data_->line_, logmsgtime_,
1870 data_->message_text_ +
data_->num_prefix_chars_,
1871 (
data_->num_chars_to_log_
1872 -
data_->num_prefix_chars_ - 1) );
1880 if (
data_->first_fatal_) {
1887 const size_t copy = min(
data_->num_chars_to_log_,
1910 const char*
message =
"*** Check failure stack trace: ***\n";
1914 #if defined(__ANDROID__)
1916 __android_log_write(ANDROID_LOG_FATAL,
1924 void LogMessage::RecordCrashReason(
1930 #ifdef HAVE_STACKTRACE
1939 reinterpret_cast<logging_fail_func_t
>(&abort);
1952 RAW_DCHECK(
data_->num_chars_to_log_ > 0 &&
1953 data_->message_text_[
data_->num_chars_to_log_-1] ==
'\n',
"");
1955 data_->line_, logmsgtime_,
1956 data_->message_text_ +
data_->num_prefix_chars_,
1957 (
data_->num_chars_to_log_ -
1958 data_->num_prefix_chars_ - 1) );
1971 RAW_DCHECK(
data_->num_chars_to_log_ > 0 &&
1972 data_->message_text_[
data_->num_chars_to_log_-1] ==
'\n',
"");
1975 size_t len =
data_->num_chars_to_log_ -
data_->num_prefix_chars_ - 1;
1984 RAW_DCHECK(
data_->num_chars_to_log_ > 0 &&
1985 data_->message_text_[
data_->num_chars_to_log_-1] ==
'\n',
"");
1988 size_t len =
data_->num_chars_to_log_ -
data_->num_prefix_chars_ - 1;
1995 void LogMessage::SendToSyslogAndLog() {
1996 #ifdef HAVE_SYSLOG_H
1998 static bool openlog_already_called =
false;
1999 if (!openlog_already_called) {
2001 LOG_CONS | LOG_NDELAY | LOG_PID,
2003 openlog_already_called =
true;
2007 const int SEVERITY_TO_LEVEL[] = { LOG_INFO, LOG_WARNING, LOG_ERR, LOG_EMERG };
2008 syslog(LOG_USER | SEVERITY_TO_LEVEL[
static_cast<int>(
data_->severity_)],
"%.*s",
2009 int(
data_->num_chars_to_syslog_),
2010 data_->message_text_ +
data_->num_prefix_chars_);
2013 LOG(
ERROR) <<
"No syslog support: message=" <<
data_->message_text_;
2037 LogMessage::LogStream *log =
static_cast<LogMessage::LogStream*
>(&os);
2039 LogMessage::LogStream *log =
dynamic_cast<LogMessage::LogStream*
>(&os);
2041 CHECK(log && log == log->self())
2042 <<
"You must not use COUNTER with non-glog ostream";
2047 ErrnoLogMessage::ErrnoLogMessage(
const char* file,
int line,
2052 ErrnoLogMessage::~ErrnoLogMessage() {
2056 << preserved_errno() <<
"]";
2075 LogSink::~LogSink() {
2079 const char* base_filename,
int line,
2080 const LogMessageTime& time,
const char*
message,
2081 size_t message_len) {
2082 #if defined(__GNUC__)
2083 #pragma GCC diagnostic push
2084 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
2085 #elif defined(_MSC_VER)
2086 #pragma warning(push)
2087 #pragma warning(disable : 4996)
2091 #if defined(__GNUC__)
2092 #pragma GCC diagnostic pop
2093 #elif defined(_MSC_VER)
2094 #pragma warning(pop)
2099 const char* base_filename,
int line,
const std::tm* t,
2100 const char*
message,
size_t message_len) {
2102 (
void)full_filename;
2103 (
void)base_filename;
2110 void LogSink::WaitTillSent() {
2115 const LogMessageTime& logmsgtime,
const char*
message,
2116 size_t message_len) {
2121 << setw(4) << 1900 + logmsgtime.year()
2122 << setw(2) << 1 + logmsgtime.month()
2123 << setw(2) << logmsgtime.day()
2125 << setw(2) << logmsgtime.hour() <<
':'
2126 << setw(2) << logmsgtime.min() <<
':'
2127 << setw(2) << logmsgtime.sec() <<
'.'
2128 << setw(6) << logmsgtime.usec()
2130 << setfill(
' ') << setw(5) <<
GetTID() << setfill(
'0')
2132 << file <<
':' << line <<
"] ";
2192 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2193 "abcdefghijklmnopqrstuvwxyz"
2194 "0123456789+-_.=/:,@";
2202 }
else if (
src.find_first_of(
'\'') == string::npos) {
2209 result.assign(
"\"");
2210 for (
size_t i = 0;
i <
src.size(); ++
i) {
2216 result.append(
"\\");
2218 result.append(
src,
i, 1);
2220 result.append(
"\"");
2230 const char*body,
bool use_logging) {
2231 #ifndef __EMSCRIPTEN__
2233 if ( use_logging ) {
2234 VLOG(1) <<
"Trying to send TITLE:" << subject
2235 <<
" BODY:" << body <<
" to " <<
dest;
2237 fprintf(stderr,
"Trying to send TITLE: %s BODY: %s to %s\n",
2238 subject, body,
dest);
2241 string logmailer = FLAGS_logmailer;
2242 if (logmailer.empty()) {
2243 logmailer =
"/bin/mail";
2249 VLOG(4) <<
"Mailing command: " << cmd;
2252 FILE* pipe = popen(cmd.c_str(),
"w");
2256 fwrite(body,
sizeof(
char), strlen(body), pipe);
2258 bool ok = pclose(pipe) != -1;
2260 if ( use_logging ) {
2261 LOG(
ERROR) <<
"Problems sending mail to " <<
dest <<
": "
2264 fprintf(stderr,
"Problems sending mail to %s: %s\n",
2270 if ( use_logging ) {
2273 fprintf(stderr,
"Unable to send mail to %s\n",
dest);
2287 #ifdef GLOG_OS_WINDOWS
2295 if (GetTempPathA(MAX_PATH, tmp))
2296 list->push_back(tmp);
2297 list->push_back(
"C:\\tmp\\");
2298 list->push_back(
"C:\\temp\\");
2302 const char * candidates[] = {
2304 getenv(
"TEST_TMPDIR"),
2307 getenv(
"TMPDIR"), getenv(
"TMP"),
2314 const char *
d = candidates[
i];
2319 if (dstr[dstr.size() - 1] !=
'/') {
2322 list->push_back(dstr);
2324 struct stat statbuf;
2325 if (!stat(
d, &statbuf) &&
S_ISDIR(statbuf.st_mode)) {
2341 if ( !FLAGS_log_dir.empty() ) {
2346 #ifdef GLOG_OS_WINDOWS
2348 if (GetWindowsDirectoryA(tmp, MAX_PATH))
2360 fprintf(stderr,
"TestOnly_ClearLoggingDirectoriesList should only be "
2361 "called from test code.\n");
2368 vector<string>::iterator i_dir = list->begin();
2369 while( i_dir != list->end() ) {
2372 if (
access(i_dir->c_str(), 0) ) {
2373 i_dir = list->erase(i_dir);
2381 #ifdef HAVE_UNISTD_H
2382 struct stat statbuf;
2383 const int kCopyBlockSize = 8 << 10;
2384 char copybuf[kCopyBlockSize];
2385 off_t read_offset, write_offset;
2389 #ifdef GLOG_OS_LINUX
2390 const char *procfd_prefix =
"/proc/self/fd/";
2391 if (strncmp(procfd_prefix,
path, strlen(procfd_prefix)))
flags |= O_NOFOLLOW;
2396 if (
errno == EFBIG) {
2402 if (truncate(
path, 0) == -1) {
2403 PLOG(
ERROR) <<
"Unable to truncate " <<
path;
2405 LOG(
ERROR) <<
"Truncated " <<
path <<
" due to EFBIG error";
2408 PLOG(
ERROR) <<
"Unable to open " <<
path;
2413 if (fstat(fd, &statbuf) == -1) {
2414 PLOG(
ERROR) <<
"Unable to fstat()";
2420 if (!
S_ISREG(statbuf.st_mode))
goto out_close_fd;
2421 if (statbuf.st_size <=
static_cast<off_t
>(limit))
goto out_close_fd;
2422 if (statbuf.st_size <=
static_cast<off_t
>(keep))
goto out_close_fd;
2425 LOG(
INFO) <<
"Truncating " <<
path <<
" to " << keep <<
" bytes";
2428 read_offset = statbuf.st_size -
static_cast<off_t
>(keep);
2430 ssize_t bytesin, bytesout;
2431 while ((bytesin =
pread(fd, copybuf,
sizeof(copybuf), read_offset)) > 0) {
2432 bytesout =
pwrite(fd, copybuf,
static_cast<size_t>(bytesin), write_offset);
2433 if (bytesout == -1) {
2434 PLOG(
ERROR) <<
"Unable to write to " <<
path;
2436 }
else if (bytesout != bytesin) {
2437 LOG(
ERROR) <<
"Expected to write " << bytesin <<
", wrote " << bytesout;
2439 read_offset += bytesin;
2440 write_offset += bytesout;
2442 if (bytesin == -1) PLOG(
ERROR) <<
"Unable to read from " <<
path;
2447 if (ftruncate(fd, write_offset) == -1) {
2448 PLOG(
ERROR) <<
"Unable to truncate " <<
path;
2454 LOG(
ERROR) <<
"No log truncation support.";
2459 #ifdef HAVE_UNISTD_H
2465 LOG(
ERROR) <<
"No log truncation support.";
2471 #define DEFINE_CHECK_STROP_IMPL(name, func, expected) \
2472 string* Check##func##expected##Impl(const char* s1, const char* s2, \
2473 const char* names) { \
2474 bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2)); \
2475 if (equal == expected) return NULL; \
2480 ss << #name " failed: " << names << " (" << s1 << " vs. " << s2 << ")"; \
2481 return new string(ss.str()); \
2488 #undef DEFINE_CHECK_STROP_IMPL
2500 int old_errno =
errno;
2502 char *rc =
reinterpret_cast<char *
>(strerror_r(
err,
buf,
len));
2528 #if defined(GLOG_OS_MACOSX) || defined(GLOG_OS_FREEBSD) || defined(GLOG_OS_OPENBSD)
2529 if (
reinterpret_cast<intptr_t
>(rc) <
sys_nerr) {
2543 if ((rc < 0) || (
buf[0] ==
'\000')) {
2549 LogMessageFatal::LogMessageFatal(
const char* file,
int line) :
2552 LogMessageFatal::LogMessageFatal(
const char* file,
int line,
2553 const CheckOpString& result) :
2556 LogMessageFatal::~LogMessageFatal() {
2563 CheckOpMessageBuilder::CheckOpMessageBuilder(
const char *exprtext)
2564 : stream_(new ostringstream) {
2565 *stream_ << exprtext <<
" (";
2568 CheckOpMessageBuilder::~CheckOpMessageBuilder() {
2572 ostream* CheckOpMessageBuilder::ForVar2() {
2573 *stream_ <<
" vs. ";
2577 string* CheckOpMessageBuilder::NewString() {
2579 return new string(stream_->str());
2586 if (
v >= 32 &&
v <= 126) {
2587 (*os) <<
"'" <<
v <<
"'";
2589 (*os) <<
"char value " <<
static_cast<short>(
v);
2595 if (
v >= 32 &&
v <= 126) {
2596 (*os) <<
"'" <<
v <<
"'";
2598 (*os) <<
"signed char value " <<
static_cast<short>(
v);
2604 if (
v >= 32 &&
v <= 126) {
2605 (*os) <<
"'" <<
v <<
"'";
2607 (*os) <<
"unsigned char value " <<
static_cast<unsigned short>(
v);
2611 #if defined(HAVE_CXX11_NULLPTR_T) && __cplusplus >= 201103L
2616 #endif // defined(HAVE_CXX11_NULLPTR_T)
2622 #ifdef GLOG_CUSTOM_PREFIX_SUPPORT
2624 CustomPrefixCallback prefix_callback,
2625 void* prefix_callback_data) {
2626 custom_prefix_callback = prefix_callback;
2627 custom_prefix_callback_data = prefix_callback_data;
2640 log_cleaner.Enable(overdue_days);
2644 log_cleaner.Disable();
2647 LogMessageTime::LogMessageTime()
2648 : time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
2650 LogMessageTime::LogMessageTime(std::tm t) {
2651 std::time_t timestamp = std::mktime(&t);
2652 init(t, timestamp, 0);
2655 LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now) {
2657 if (FLAGS_log_utc_time)
2661 init(t, timestamp, now);
2667 timestamp_ = timestamp;
2668 usecs_ =
static_cast<int32>((now - timestamp) * 1000000);
2673 void LogMessageTime::CalcGmtOffset() {
2676 if ( FLAGS_log_utc_time ) {
2678 isDst = gmt_struct.tm_isdst;
2679 gmt_struct = time_struct_;
2681 isDst = time_struct_.tm_isdst;
2682 gmtime_r(×tamp_, &gmt_struct);
2685 time_t gmt_sec = mktime(&gmt_struct);
2686 const long hour_secs = 3600;
2688 gmtoffset_ =
static_cast<long int>(timestamp_ - gmt_sec + (isDst ? hour_secs : 0) ) ;
2691 _END_GOOGLE_NAMESPACE_