OR-Tools  9.1
base/logging.cc
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
15
16#define _GNU_SOURCE 1 // needed for O_NOFOLLOW and pread()/pwrite()
17
18#include <algorithm>
19#include <cassert>
20#include <iomanip>
21#include <mutex> // for std::call_once and std::once_flag. // NOLINT
22#include <string>
23
24#if defined(_MSC_VER)
25#include <io.h> // lseek
26#include <string.h> /* for _strnicmp(), strerror_s() */
27#include <time.h> /* for localtime_s() */
28#include <windows.h>
29#else
30#include <pwd.h>
31#include <sys/utsname.h> // For uname.
32#include <syslog.h>
33#include <unistd.h> // For _exit.
34#endif
35#include <errno.h> // for errno
36#include <fcntl.h>
37#include <stdarg.h>
38#include <stdlib.h>
39#include <sys/stat.h>
40#include <sys/types.h>
41
42#include <climits>
43#include <cstdio>
44#include <iostream>
45#include <sstream>
46#include <vector>
47
48#include "absl/debugging/stacktrace.h"
49#include "absl/time/time.h"
53
54ABSL_DECLARE_FLAG(bool, log_prefix);
55ABSL_DECLARE_FLAG(bool, logtostderr);
56
57namespace {
58std::once_flag init_done;
59} // namespace
60
62 std::call_once(init_done, [] { google::InitGoogleLogging("swig_helper"); });
63 absl::SetFlag(&FLAGS_logtostderr, true);
64 absl::SetFlag(&FLAGS_log_prefix, false);
65}
66
67using std::dec;
68using std::hex;
69using std::min;
70using std::ostream;
71using std::ostringstream;
72using std::setfill;
73using std::setw;
74using std::string;
75using std::vector;
76
77using std::fclose;
78using std::fflush;
79using std::FILE;
80using std::fprintf;
81using std::fwrite;
82using std::perror;
83
84#ifdef _WIN32
85#define fdopen _fdopen
86#define strcasecmp _stricmp
87#endif
88
89#if defined(_MSC_VER)
90#ifndef __MINGW32__
91enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
92#endif
93
94inline char* strerror_r(int errnum, char* buf, size_t buflen) {
95 strerror_s(buf, buflen, errnum);
96 return buf;
97}
98
99inline struct tm* localtime_r(const time_t* timep, struct tm* result) {
100 localtime_s(result, timep);
101 return result;
102}
103#endif
104
105ABSL_FLAG(bool, logtostderr, false,
106 "log messages go to stderr instead of logfiles");
107ABSL_FLAG(bool, alsologtostderr, false,
108 "log messages go to stderr in addition to logfiles");
109ABSL_FLAG(bool, colorlogtostderr, false,
110 "color messages logged to stderr (if supported by terminal)");
111#if defined(__linux__)
112ABSL_FLAG(bool, drop_log_memory, true,
113 "Drop in-memory buffers of log contents. "
114 "Logs can grow very quickly and they are rarely read before they "
115 "need to be evicted from memory. Instead, drop them from memory "
116 "as soon as they are flushed to disk.");
117#endif
118
119// By default, errors (including fatal errors) get logged to stderr as
120// well as the file.
121//
122// The default is ERROR instead of FATAL so that users can see problems
123// when they run a program without having to look in another file.
124ABSL_FLAG(int, stderrthreshold, google::GLOG_ERROR,
125 "log messages at or above this level are copied to stderr in "
126 "addition to logfiles. This flag obsoletes --alsologtostderr.");
127
128ABSL_FLAG(bool, log_prefix, true,
129 "Prepend the log prefix to the start of each log line");
130ABSL_FLAG(int, minloglevel, 0,
131 "Messages logged at a lower level than this don't "
132 "actually get logged anywhere");
133ABSL_FLAG(int, logbuflevel, 0,
134 "Buffer log messages logged at this level or lower"
135 " (-1 means don't buffer; 0 means buffer INFO only;"
136 " ...)");
137ABSL_FLAG(int, logbufsecs, 30,
138 "Buffer log messages for at most this many seconds");
139
140// Compute the default value for --log_dir
141static const char* DefaultLogDir() {
142 const char* env;
143 env = getenv("GOOGLE_LOG_DIR");
144 if (env != NULL && env[0] != '\0') {
145 return env;
146 }
147 env = getenv("TEST_TMPDIR");
148 if (env != NULL && env[0] != '\0') {
149 return env;
150 }
151 return "";
152}
153
154ABSL_FLAG(int, logfile_mode, 0664, "Log file mode/permissions.");
155
156ABSL_FLAG(std::string, log_dir, DefaultLogDir(),
157 "If specified, logfiles are written into this directory instead "
158 "of the default logging directory.");
159ABSL_FLAG(std::string, log_link, "",
160 "Put additional links to the log "
161 "files in this directory");
162
163ABSL_FLAG(int, max_log_size, 1800,
164 "approx. maximum log file size (in MB). A value of 0 will "
165 "be silently overridden to 1.");
166
167ABSL_FLAG(bool, stop_logging_if_full_disk, false,
168 "Stop attempting to log to disk if the disk is full.");
169
170ABSL_FLAG(std::string, log_backtrace_at, "",
171 "Emit a backtrace when logging at file:linenum.");
172
173#if defined(_MSC_VER)
174#define PATH_SEPARATOR '\\'
175#else
176#define PATH_SEPARATOR '/'
177#endif
178
179#ifdef _MSC_VER
180#include <basetsd.h>
181#define ssize_t SSIZE_T
182static ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
183 off_t orig_offset = lseek(fd, 0, SEEK_CUR);
184 if (orig_offset == (off_t)-1) return -1;
185 if (lseek(fd, offset, SEEK_CUR) == (off_t)-1) return -1;
186 ssize_t len = read(fd, buf, count);
187 if (len < 0) return len;
188 if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1) return -1;
189 return len;
190}
191
192static ssize_t pwrite(int fd, void* buf, size_t count, off_t offset) {
193 off_t orig_offset = lseek(fd, 0, SEEK_CUR);
194 if (orig_offset == (off_t)-1) return -1;
195 if (lseek(fd, offset, SEEK_CUR) == (off_t)-1) return -1;
196 ssize_t len = write(fd, buf, count);
197 if (len < 0) return len;
198 if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1) return -1;
199 return len;
200}
201#endif // _MSC_VER
202
203static void GetHostName(string* hostname) {
204#if !defined(_MSC_VER)
205 struct utsname buf;
206 if (0 != uname(&buf)) {
207 // ensure null termination on failure
208 *buf.nodename = '\0';
209 }
210 *hostname = buf.nodename;
211#else // _MSC_VER
212 char buf[MAX_COMPUTERNAME_LENGTH + 1];
213 DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
214 if (GetComputerNameA(buf, &len)) {
215 *hostname = buf;
216 } else {
217 hostname->clear();
218 }
219#endif // _MSC_VER
220}
221
222// Returns true iff terminal supports using colors in output.
224 bool term_supports_color = false;
225#ifdef _MSC_VER
226 // on Windows TERM variable is usually not set, but the console does
227 // support colors.
228 term_supports_color = true;
229#else
230 // On non-Windows platforms, we rely on the TERM variable.
231 const char* const term = getenv("TERM");
232 if (term != NULL && term[0] != '\0') {
233 term_supports_color =
234 !strcmp(term, "xterm") || !strcmp(term, "xterm-color") ||
235 !strcmp(term, "xterm-256color") || !strcmp(term, "screen-256color") ||
236 !strcmp(term, "konsole") || !strcmp(term, "konsole-16color") ||
237 !strcmp(term, "konsole-256color") || !strcmp(term, "screen") ||
238 !strcmp(term, "linux") || !strcmp(term, "cygwin");
239 }
240#endif
241 return term_supports_color;
242}
243
244namespace google {
245
247
249 assert(severity >= 0 && severity < NUM_SEVERITIES);
250 GLogColor color = COLOR_DEFAULT;
251 switch (severity) {
252 case GLOG_INFO:
253 color = COLOR_DEFAULT;
254 break;
255 case GLOG_WARNING:
256 color = COLOR_YELLOW;
257 break;
258 case GLOG_ERROR:
259 case GLOG_FATAL:
260 color = COLOR_RED;
261 break;
262 default:
263 // should never get here.
264 assert(false);
265 }
266 return color;
267}
268
269#ifdef _MSC_VER
270
271// Returns the character attribute for the given color.
272static WORD GetColorAttribute(GLogColor color) {
273 switch (color) {
274 case COLOR_RED:
275 return FOREGROUND_RED;
276 case COLOR_GREEN:
277 return FOREGROUND_GREEN;
278 case COLOR_YELLOW:
279 return FOREGROUND_RED | FOREGROUND_GREEN;
280 default:
281 return 0;
282 }
283}
284
285#else // _MSC_VER
286
287// Returns the ANSI color code for the given color.
288static const char* GetAnsiColorCode(GLogColor color) {
289 switch (color) {
290 case COLOR_RED:
291 return "1";
292 case COLOR_GREEN:
293 return "2";
294 case COLOR_YELLOW:
295 return "3";
296 case COLOR_DEFAULT:
297 return "";
298 }
299 return NULL; // stop warning about return type.
300}
301
302#endif // !_MSC_VER
303
304// Safely get max_log_size, overriding to 1 if it somehow gets defined as 0
305static int32_t MaxLogSize() {
306 return (absl::GetFlag(FLAGS_max_log_size) > 0
307 ? absl::GetFlag(FLAGS_max_log_size)
308 : 1);
309}
310
311// An arbitrary limit on the length of a single log message. This
312// is so that streaming can be done more efficiently.
313const size_t LogMessage::kMaxLogMessageLen = 30000;
314
317
318 int preserved_errno_; // preserved errno
319 // Buffer space; contains complete message text.
322 char severity_; // What level is this LogMessage logged at?
323 int line_; // line number where logging call is.
324 void (LogMessage::*send_method_)(); // Call this in destructor to send
325 union { // At most one of these is used: union to keep the size low.
326 LogSink* sink_; // NULL or sink to send message to
327 std::vector<std::string>* outvec_; // NULL or vector to push message onto
328 std::string* message_; // NULL or string to write message into
329 };
330 time_t timestamp_; // Time of creation of LogMessage
331 struct ::tm tm_time_; // Time of creation of LogMessage
332 size_t num_prefix_chars_; // # of chars of prefix in this message
333 size_t num_chars_to_log_; // # of chars of msg to send to log
334 size_t num_chars_to_syslog_; // # of chars of msg to send to syslog
335 const char* basename_; // basename of file that called LOG
336 const char* fullname_; // fullname of file that called LOG
337 bool has_been_flushed_; // false => data has not been flushed
338 bool first_fatal_; // true => this was first fatal msg
339
340 private:
342 void operator=(const LogMessageData&);
343};
344
345// A absl::Mutex that allows only one thread to log at a time, to keep things
346// from getting jumbled. Some other very uncommon logging operations (like
347// changing the destination file for log messages of a given severity) also
348// lock this absl::Mutex. Please be sure that anybody who might possibly need
349// to lock it does so.
350static absl::Mutex log_mutex;
351
352// Number of messages sent at each severity. Under log_mutex.
353int64_t LogMessage::num_messages_[NUM_SEVERITIES] = {0, 0, 0, 0};
354
355// Globally disable log writing (if disk is full)
356static bool stop_writing = false;
357
358const char* const LogSeverityNames[NUM_SEVERITIES] = {"INFO", "WARNING",
359 "ERROR", "FATAL"};
360
361// Has the user called SetExitOnDFatal(true)?
362static bool exit_on_dfatal = true;
363
364const char* GetLogSeverityName(LogSeverity severity) {
365 return LogSeverityNames[severity];
366}
367
369
370namespace {
371
372// Encapsulates all file-system related state
373class LogFileObject : public base::Logger {
374 public:
375 LogFileObject(LogSeverity severity, const char* base_filename);
376 ~LogFileObject();
377
378 virtual void Write(bool force_flush, // Should we force a flush here?
379 time_t timestamp, // Timestamp for this entry
380 const char* message, int message_len);
381
382 // Configuration options
383 void SetBasename(const char* basename);
384 void SetExtension(const char* ext);
385 void SetSymlinkBasename(const char* symlink_basename);
386
387 // Normal flushing routine
388 virtual void Flush();
389
390 // It is the actual file length for the system loggers,
391 // i.e., INFO, ERROR, etc.
392 virtual uint32_t LogSize() {
393 absl::MutexLock l(&lock_);
394 return file_length_;
395 }
396
397 // Internal flush routine. Exposed so that FlushLogFilesUnsafe()
398 // can avoid grabbing a lock. Usually Flush() calls it after
399 // acquiring lock_.
400 void FlushUnlocked();
401
402 private:
403 static const uint32_t kRolloverAttemptFrequency = 0x20;
404
405 absl::Mutex lock_;
406 bool base_filename_selected_;
407 string base_filename_;
408 string symlink_basename_;
409 string filename_extension_; // option users can specify (eg to add port#)
410 FILE* file_;
411 LogSeverity severity_;
412 uint32_t bytes_since_flush_;
413 uint32_t dropped_mem_length_;
414 uint32_t file_length_;
415 unsigned int rollover_attempt_;
416 int64_t next_flush_time_; // cycle count at which to flush log
417
418 // Actually create a logfile using the value of base_filename_ and the
419 // supplied argument time_pid_string
420 // REQUIRES: lock_ is held
421 bool CreateLogfile(const string& time_pid_string);
422};
423
424} // namespace
425
427 public:
428 friend class LogMessage;
429 friend void ReprintFatalMessage();
432
433 // These methods are just forwarded to by their global versions.
434 static void SetLogDestination(LogSeverity severity,
435 const char* base_filename);
436 static void SetLogSymlink(LogSeverity severity, const char* symlink_basename);
437 static void AddLogSink(LogSink* destination);
438 static void RemoveLogSink(LogSink* destination);
439 static void SetLogFilenameExtension(const char* filename_extension);
440 static void SetStderrLogging(LogSeverity min_severity);
441 static void LogToStderr();
442 // Flush all log files that are at least at the given severity level
443 static void FlushLogFiles(int min_severity);
444 static void FlushLogFilesUnsafe(int min_severity);
445
446 // we set the maximum size of our packet to be 1400, the logic being
447 // to prevent fragmentation.
448 // Really this number is arbitrary.
449 static const int kNetworkBytes = 1400;
450
451 static const string& hostname();
452 static const bool& terminal_supports_color() {
453 return terminal_supports_color_;
454 }
455
456 static void DeleteLogDestinations();
457
458 private:
459 LogDestination(LogSeverity severity, const char* base_filename);
460 ~LogDestination() {}
461
462 // Take a log message of a particular severity and log it to stderr
463 // iff it's of a high enough severity to deserve it.
464 static void MaybeLogToStderr(LogSeverity severity, const char* message,
465 size_t len);
466
467 // Take a log message of a particular severity and log it to a file
468 // iff the base filename is not "" (which means "don't log to me")
469 static void MaybeLogToLogfile(LogSeverity severity, time_t timestamp,
470 const char* message, size_t len);
471 // Take a log message of a particular severity and log it to the file
472 // for that severity and also for all files with severity less than
473 // this severity.
474 static void LogToAllLogfiles(LogSeverity severity, time_t timestamp,
475 const char* message, size_t len);
476
477 // Send logging info to all registered sinks.
478 static void LogToSinks(LogSeverity severity, const char* full_filename,
479 const char* base_filename, int line,
480 const struct ::tm* tm_time, const char* message,
481 size_t message_len);
482
483 // Wait for all registered sinks via WaitTillSent
484 // including the optional one in "data".
485 static void WaitForSinks(LogMessage::LogMessageData* data);
486
487 static LogDestination* log_destination(LogSeverity severity);
488
489 LogFileObject fileobject_;
490 base::Logger* logger_; // Either &fileobject_, or wrapper around it
491
492 static LogDestination* log_destinations_[NUM_SEVERITIES];
493 static string addresses_;
494 static string hostname_;
495 static bool terminal_supports_color_;
496
497 // arbitrary global logging destinations.
498 static vector<LogSink*>* sinks_;
499
500 // Protects the vector sinks_,
501 // but not the LogSink objects its elements reference.
502 static absl::Mutex sink_mutex_;
503
504 // Disallow
505 LogDestination(const LogDestination&);
506 LogDestination& operator=(const LogDestination&);
507};
508
509string LogDestination::addresses_; // NOLINT
510string LogDestination::hostname_; // NOLINT
511
512vector<LogSink*>* LogDestination::sinks_ = NULL;
513absl::Mutex LogDestination::sink_mutex_;
514bool LogDestination::terminal_supports_color_ = TerminalSupportsColor();
515
516/* static */
518 if (hostname_.empty()) {
519 GetHostName(&hostname_);
520 if (hostname_.empty()) {
521 hostname_ = "(unknown)";
522 }
523 }
524 return hostname_;
525}
526
527LogDestination::LogDestination(LogSeverity severity, const char* base_filename)
528 : fileobject_(severity, base_filename), logger_(&fileobject_) {}
529
530inline void LogDestination::FlushLogFilesUnsafe(int min_severity) {
531 // assume we have the log_mutex or we simply don't care
532 // about it
533 for (int i = min_severity; i < NUM_SEVERITIES; i++) {
534 LogDestination* log = log_destinations_[i];
535 if (log != NULL) {
536 // Flush the base fileobject_ logger directly instead of going
537 // through any wrappers to reduce chance of deadlock.
538 log->fileobject_.FlushUnlocked();
539 }
540 }
541}
542
543inline void LogDestination::FlushLogFiles(int min_severity) {
544 // Prevent any subtle race conditions by wrapping a absl::Mutex lock around
545 // all this stuff.
546 absl::MutexLock l(&log_mutex);
547 for (int i = min_severity; i < NUM_SEVERITIES; i++) {
548 LogDestination* log = log_destination(i);
549 if (log != NULL) {
550 log->logger_->Flush();
551 }
552 }
553}
554
556 const char* base_filename) {
557 assert(severity >= 0 && severity < NUM_SEVERITIES);
558 // Prevent any subtle race conditions by wrapping a absl::Mutex lock around
559 // all this stuff.
560 absl::MutexLock l(&log_mutex);
561 log_destination(severity)->fileobject_.SetBasename(base_filename);
562}
563
565 const char* symlink_basename) {
566 CHECK_GE(severity, 0);
567 CHECK_LT(severity, NUM_SEVERITIES);
568 absl::MutexLock l(&log_mutex);
569 log_destination(severity)->fileobject_.SetSymlinkBasename(symlink_basename);
570}
571
572inline void LogDestination::AddLogSink(LogSink* destination) {
573 // Prevent any subtle race conditions by wrapping a absl::Mutex lock around
574 // all this stuff.
575 absl::MutexLock l(&sink_mutex_);
576 if (!sinks_) sinks_ = new vector<LogSink*>;
577 sinks_->push_back(destination);
578}
579
580inline void LogDestination::RemoveLogSink(LogSink* destination) {
581 // Prevent any subtle race conditions by wrapping a absl::Mutex lock around
582 // all this stuff.
583 absl::MutexLock l(&sink_mutex_);
584 // This doesn't keep the sinks in order, but who cares?
585 if (sinks_) {
586 for (int i = sinks_->size() - 1; i >= 0; i--) {
587 if ((*sinks_)[i] == destination) {
588 (*sinks_)[i] = (*sinks_)[sinks_->size() - 1];
589 sinks_->pop_back();
590 break;
591 }
592 }
593 }
594}
595
596inline void LogDestination::SetLogFilenameExtension(const char* ext) {
597 // Prevent any subtle race conditions by wrapping a absl::Mutex lock around
598 // all this stuff.
599 absl::MutexLock l(&log_mutex);
600 for (int severity = 0; severity < NUM_SEVERITIES; ++severity) {
601 log_destination(severity)->fileobject_.SetExtension(ext);
602 }
603}
604
606 assert(min_severity >= 0 && min_severity < NUM_SEVERITIES);
607 // Prevent any subtle race conditions by wrapping a absl::Mutex lock around
608 // all this stuff.
609 absl::MutexLock l(&log_mutex);
610 absl::SetFlag(&FLAGS_stderrthreshold, min_severity);
611}
612
614 // *Don't* put this stuff in a absl::Mutex lock, since SetStderrLogging &
615 // SetLogDestination already do the locking!
616 SetStderrLogging(0); // thus everything is "also" logged to stderr
617 for (int i = 0; i < NUM_SEVERITIES; ++i) {
618 SetLogDestination(i, ""); // "" turns off logging to a logfile
619 }
620}
621
622static void ColoredWriteToStderr(LogSeverity severity, const char* message,
623 size_t len) {
625 absl::GetFlag(FLAGS_colorlogtostderr))
626 ? SeverityToColor(severity)
628
629 // Avoid using cerr from this module since we may get called during
630 // exit code, and cerr may be partially or fully destroyed by then.
631 if (COLOR_DEFAULT == color) {
632 fwrite(message, len, 1, stderr);
633 return;
634 }
635#ifdef _MSC_VER
636 const HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
637
638 // Gets the current text color.
639 CONSOLE_SCREEN_BUFFER_INFO buffer_info;
640 GetConsoleScreenBufferInfo(stderr_handle, &buffer_info);
641 const WORD old_color_attrs = buffer_info.wAttributes;
642
643 // We need to flush the stream buffers into the console before each
644 // SetConsoleTextAttribute call lest it affect the text that is already
645 // printed but has not yet reached the console.
646 fflush(stderr);
647 SetConsoleTextAttribute(stderr_handle,
648 GetColorAttribute(color) | FOREGROUND_INTENSITY);
649 fwrite(message, len, 1, stderr);
650 fflush(stderr);
651 // Restores the text color.
652 SetConsoleTextAttribute(stderr_handle, old_color_attrs);
653#else // !_MSC_VER
654 fprintf(stderr, "\033[0;3%sm", GetAnsiColorCode(color));
655 fwrite(message, len, 1, stderr);
656 fprintf(stderr, "\033[m"); // Resets the terminal to default.
657#endif // !_MSC_VER
658}
659
660static void WriteToStderr(const char* message, size_t len) {
661 // Avoid using cerr from this module since we may get called during
662 // exit code, and cerr may be partially or fully destroyed by then.
663 fwrite(message, len, 1, stderr);
664}
665
666inline void LogDestination::MaybeLogToStderr(LogSeverity severity,
667 const char* message, size_t len) {
668 if ((severity >= absl::GetFlag(FLAGS_stderrthreshold)) ||
669 absl::GetFlag(FLAGS_alsologtostderr)) {
670 ColoredWriteToStderr(severity, message, len);
671#ifdef _MSC_VER
672 // On Windows, also output to the debugger
673 ::OutputDebugStringA(string(message, len).c_str());
674#endif
675 }
676}
677
678inline void LogDestination::MaybeLogToLogfile(LogSeverity severity,
679 time_t timestamp,
680 const char* message, size_t len) {
681 const bool should_flush = severity > absl::GetFlag(FLAGS_logbuflevel);
682 LogDestination* destination = log_destination(severity);
683 destination->logger_->Write(should_flush, timestamp, message, len);
684}
685
686inline void LogDestination::LogToAllLogfiles(LogSeverity severity,
687 time_t timestamp,
688 const char* message, size_t len) {
689 if (absl::GetFlag(FLAGS_logtostderr)) { // global flag: never log to file
690 ColoredWriteToStderr(severity, message, len);
691 } else {
692 for (int i = severity; i >= 0; --i)
693 LogDestination::MaybeLogToLogfile(i, timestamp, message, len);
694 }
695}
696
697inline void LogDestination::LogToSinks(LogSeverity severity,
698 const char* full_filename,
699 const char* base_filename, int line,
700 const struct ::tm* tm_time,
701 const char* message,
702 size_t message_len) {
703 absl::ReaderMutexLock l(&sink_mutex_);
704 if (sinks_) {
705 for (int i = sinks_->size() - 1; i >= 0; i--) {
706 (*sinks_)[i]->send(severity, full_filename, base_filename, line, tm_time,
707 message, message_len);
708 }
709 }
710}
711
712inline void LogDestination::WaitForSinks(LogMessage::LogMessageData* data) {
713 absl::ReaderMutexLock l(&sink_mutex_);
714 if (sinks_) {
715 for (int i = sinks_->size() - 1; i >= 0; i--) {
716 (*sinks_)[i]->WaitTillSent();
717 }
718 }
719 const bool send_to_sink =
720 (data->send_method_ == &LogMessage::SendToSink) ||
721 (data->send_method_ == &LogMessage::SendToSinkAndLog);
722 if (send_to_sink && data->sink_ != NULL) {
723 data->sink_->WaitTillSent();
724 }
725}
726
727LogDestination* LogDestination::log_destinations_[NUM_SEVERITIES];
728
729inline LogDestination* LogDestination::log_destination(LogSeverity severity) {
730 assert(severity >= 0 && severity < NUM_SEVERITIES);
731 if (!log_destinations_[severity]) {
732 log_destinations_[severity] = new LogDestination(severity, NULL);
733 }
734 return log_destinations_[severity];
735}
736
738 for (int severity = 0; severity < NUM_SEVERITIES; ++severity) {
739 delete log_destinations_[severity];
740 log_destinations_[severity] = NULL;
741 }
742 absl::MutexLock l(&sink_mutex_);
743 delete sinks_;
744 sinks_ = NULL;
745}
746
747namespace {
748
749LogFileObject::LogFileObject(LogSeverity severity, const char* base_filename)
750 : base_filename_selected_(base_filename != NULL),
751 base_filename_((base_filename != NULL) ? base_filename : ""),
752 symlink_basename_(logging_internal::ProgramInvocationShortName()),
753 filename_extension_(),
754 file_(NULL),
755 severity_(severity),
756 bytes_since_flush_(0),
757 dropped_mem_length_(0),
758 file_length_(0),
759 rollover_attempt_(kRolloverAttemptFrequency - 1),
760 next_flush_time_(0) {
761 assert(severity >= 0);
762 assert(severity < NUM_SEVERITIES);
763}
764
765LogFileObject::~LogFileObject() {
766 absl::MutexLock l(&lock_);
767 if (file_ != NULL) {
768 fclose(file_);
769 file_ = NULL;
770 }
771}
772
773void LogFileObject::SetBasename(const char* basename) {
774 absl::MutexLock l(&lock_);
775 base_filename_selected_ = true;
776 if (base_filename_ != basename) {
777 // Get rid of old log file since we are changing names
778 if (file_ != NULL) {
779 fclose(file_);
780 file_ = NULL;
781 rollover_attempt_ = kRolloverAttemptFrequency - 1;
782 }
783 base_filename_ = basename;
784 }
785}
786
787void LogFileObject::SetExtension(const char* ext) {
788 absl::MutexLock l(&lock_);
789 if (filename_extension_ != ext) {
790 // Get rid of old log file since we are changing names
791 if (file_ != NULL) {
792 fclose(file_);
793 file_ = NULL;
794 rollover_attempt_ = kRolloverAttemptFrequency - 1;
795 }
796 filename_extension_ = ext;
797 }
798}
799
800void LogFileObject::SetSymlinkBasename(const char* symlink_basename) {
801 absl::MutexLock l(&lock_);
802 symlink_basename_ = symlink_basename;
803}
804
805void LogFileObject::Flush() {
806 absl::MutexLock l(&lock_);
807 FlushUnlocked();
808}
809
810void LogFileObject::FlushUnlocked() {
811 if (file_ != NULL) {
812 fflush(file_);
813 bytes_since_flush_ = 0;
814 }
815 // Figure out when we are due for another flush.
816 const int64_t next = (absl::GetFlag(FLAGS_logbufsecs) *
817 static_cast<int64_t>(1000000)); // in usec
818 next_flush_time_ =
820}
821
822bool LogFileObject::CreateLogfile(const string& time_pid_string) {
823 string string_filename =
824 base_filename_ + filename_extension_ + time_pid_string;
825 const char* filename = string_filename.c_str();
826 int fd = open(filename, O_WRONLY | O_CREAT | O_EXCL,
827 absl::GetFlag(FLAGS_logfile_mode));
828 if (fd == -1) return false;
829#if !defined(_MSC_VER)
830 // Mark the file close-on-exec. We don't really care if this fails
831 fcntl(fd, F_SETFD, FD_CLOEXEC);
832#endif
833
834 file_ = fdopen(fd, "a"); // Make a FILE*.
835 if (file_ == NULL) { // Man, we're screwed!
836 close(fd);
837 unlink(filename); // Erase the half-baked evidence: an unusable log file
838 return false;
839 }
840
841 // We try to create a symlink called <program_name>.<severity>,
842 // which is easier to use. (Every time we create a new logfile,
843 // we destroy the old symlink and create a new one, so it always
844 // points to the latest logfile.) If it fails, we're sad but it's
845 // no error.
846 if (!symlink_basename_.empty()) {
847 // take directory from filename
848 const char* slash = strrchr(filename, PATH_SEPARATOR);
849 const string linkname =
850 symlink_basename_ + '.' + LogSeverityNames[severity_];
851 string linkpath;
852 if (slash)
853 linkpath = string(filename, slash - filename + 1); // get dirname
854 linkpath += linkname;
855 unlink(linkpath.c_str()); // delete old one if it exists
856
857#if !defined(_MSC_VER)
858 // We must have unistd.h.
859 // Make the symlink be relative (in the same dir) so that if the
860 // entire log directory gets relocated the link is still valid.
861 const char* linkdest = slash ? (slash + 1) : filename;
862 if (symlink(linkdest, linkpath.c_str()) != 0) {
863 // silently ignore failures
864 }
865
866 // Make an additional link to the log file in a place specified by
867 // absl::GetFlag(FLAGS_log_link), if indicated
868 if (!absl::GetFlag(FLAGS_log_link).empty()) {
869 linkpath = absl::GetFlag(FLAGS_log_link) + "/" + linkname;
870 unlink(linkpath.c_str()); // delete old one if it exists
871 if (symlink(filename, linkpath.c_str()) != 0) {
872 // silently ignore failures
873 }
874 }
875#endif // !_MSC_VER
876 }
877
878 return true; // Everything worked
879}
880
881void LogFileObject::Write(bool force_flush, time_t timestamp,
882 const char* message, int message_len) {
883 absl::MutexLock l(&lock_);
884
885 // We don't log if the base_name_ is "" (which means "don't write")
886 if (base_filename_selected_ && base_filename_.empty()) {
887 return;
888 }
889
890 if (static_cast<int>(file_length_ >> 20) >= MaxLogSize()) {
891 if (file_ != NULL) fclose(file_);
892 file_ = NULL;
893 file_length_ = bytes_since_flush_ = dropped_mem_length_ = 0;
894 rollover_attempt_ = kRolloverAttemptFrequency - 1;
895 }
896
897 // If there's no destination file, make one before outputting
898 if (file_ == NULL) {
899 // Try to rollover the log file every 32 log messages. The only time
900 // this could matter would be when we have trouble creating the log
901 // file. If that happens, we'll lose lots of log messages, of course!
902 if (++rollover_attempt_ != kRolloverAttemptFrequency) return;
903 rollover_attempt_ = 0;
904
905 struct ::tm tm_time;
906 localtime_r(&timestamp, &tm_time);
907
908 // The logfile's filename will have the date/time & pid in it
909 ostringstream time_pid_stream;
910 time_pid_stream.fill('0');
911 time_pid_stream << 1900 + tm_time.tm_year << setw(2) << 1 + tm_time.tm_mon
912 << setw(2) << tm_time.tm_mday << '-' << setw(2)
913 << tm_time.tm_hour << setw(2) << tm_time.tm_min << setw(2)
914 << tm_time.tm_sec << '.'
916 const string& time_pid_string = time_pid_stream.str();
917
918 if (base_filename_selected_) {
919 if (!CreateLogfile(time_pid_string)) {
920 perror("Could not create log file");
921 fprintf(stderr, "COULD NOT CREATE LOGFILE '%s'!\n",
922 time_pid_string.c_str());
923 return;
924 }
925 } else {
926 // If no base filename for logs of this severity has been set, use a
927 // default base filename of
928 // "<program name>.<hostname>.<user name>.log.<severity level>.". So
929 // logfiles will have names like
930 // webserver.examplehost.root.log.INFO.19990817-150000.4354, where
931 // 19990817 is a date (1999 August 17), 150000 is a time (15:00:00),
932 // and 4354 is the pid of the logging process. The date & time reflect
933 // when the file was created for output.
934 //
935 // Where does the file get put? Successively try the directories
936 // "/tmp", and "."
937 string stripped_filename(logging_internal::ProgramInvocationShortName());
938 string hostname;
939 GetHostName(&hostname);
940
941 string uidname = logging_internal::MyUserName();
942 // We should not call CHECK() here because this function can be
943 // called after holding on to log_mutex. We don't want to
944 // attempt to hold on to the same absl::Mutex, and get into a
945 // deadlock. Simply use a name like invalid-user.
946 if (uidname.empty()) uidname = "invalid-user";
947
948 stripped_filename = stripped_filename + '.' + hostname + '.' + uidname +
949 ".log." + LogSeverityNames[severity_] + '.';
950 // We're going to (potentially) try to put logs in several different dirs
951 const vector<string>& log_dirs = GetLoggingDirectories();
952
953 // Go through the list of dirs, and try to create the log file in each
954 // until we succeed or run out of options
955 bool success = false;
956 for (vector<string>::const_iterator dir = log_dirs.begin();
957 dir != log_dirs.end(); ++dir) {
958 base_filename_ = *dir + "/" + stripped_filename;
959 if (CreateLogfile(time_pid_string)) {
960 success = true;
961 break;
962 }
963 }
964 // If we never succeeded, we have to give up
965 if (success == false) {
966 perror("Could not create logging file");
967 fprintf(stderr, "COULD NOT CREATE A LOGGINGFILE %s!",
968 time_pid_string.c_str());
969 return;
970 }
971 }
972
973 // Write a header message into the log file
974 ostringstream file_header_stream;
975 file_header_stream.fill('0');
976 file_header_stream << "Log file created at: " << 1900 + tm_time.tm_year
977 << '/' << setw(2) << 1 + tm_time.tm_mon << '/' << setw(2)
978 << tm_time.tm_mday << ' ' << setw(2) << tm_time.tm_hour
979 << ':' << setw(2) << tm_time.tm_min << ':' << setw(2)
980 << tm_time.tm_sec << '\n'
981 << "Running on machine: " << LogDestination::hostname()
982 << '\n'
983 << "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu "
984 << "threadid file:line] msg" << '\n';
985 const string& file_header_string = file_header_stream.str();
986
987 const int header_len = file_header_string.size();
988 fwrite(file_header_string.data(), 1, header_len, file_);
989 file_length_ += header_len;
990 bytes_since_flush_ += header_len;
991 }
992
993 // Write to LOG file
994 if (!stop_writing) {
995 // fwrite() doesn't return an error when the disk is full, for
996 // messages that are less than 4096 bytes. When the disk is full,
997 // it returns the message length for messages that are less than
998 // 4096 bytes. fwrite() returns 4096 for message lengths that are
999 // greater than 4096, thereby indicating an error.
1000 errno = 0;
1001 fwrite(message, 1, message_len, file_);
1002 if (absl::GetFlag(FLAGS_stop_logging_if_full_disk) &&
1003 errno == ENOSPC) { // disk full, stop writing to disk
1004 stop_writing = true; // until the disk is
1005 return;
1006 } else {
1007 file_length_ += message_len;
1008 bytes_since_flush_ += message_len;
1009 }
1010 } else {
1011 if (logging_internal::CycleClock_Now() >= next_flush_time_)
1012 stop_writing = false; // check to see if disk has free space.
1013 return; // no need to flush
1014 }
1015
1016 // See important msgs *now*. Also, flush logs at least every 10^6 chars,
1017 // or every "absl::GetFlag(FLAGS_logbufsecs)" seconds.
1018 if (force_flush || (bytes_since_flush_ >= 1000000) ||
1019 (logging_internal::CycleClock_Now() >= next_flush_time_)) {
1020 FlushUnlocked();
1021#if defined(__linux__)
1022 // Only consider files >= 3MiB
1023 if (absl::GetFlag(FLAGS_drop_log_memory) && file_length_ >= (3 << 20)) {
1024 // Don't evict the most recent 1-2MiB so as not to impact a tailer
1025 // of the log file and to avoid page rounding issue on linux < 4.7
1026 uint32_t total_drop_length =
1027 (file_length_ & ~((1 << 20) - 1)) - (1 << 20);
1028 uint32_t this_drop_length = total_drop_length - dropped_mem_length_;
1029 if (this_drop_length >= (2 << 20)) {
1030 // Only advise when >= 2MiB to drop
1031 posix_fadvise(fileno(file_), dropped_mem_length_, this_drop_length,
1032 POSIX_FADV_DONTNEED);
1033 dropped_mem_length_ = total_drop_length;
1034 }
1035 }
1036#endif
1037 }
1038}
1039
1040} // namespace
1041
1042// Static log data space to avoid alloc failures in a LOG(FATAL)
1043//
1044// Since multiple threads may call LOG(FATAL), and we want to preserve
1045// the data from the first call, we allocate two sets of space. One
1046// for exclusive use by the first thread, and one for shared use by
1047// all other threads.
1048static absl::Mutex fatal_msg_lock;
1050static bool fatal_msg_exclusive = true;
1053
1054// Static thread-local log data space to use, because typically at most one
1055// LogMessageData object exists (in this case glog makes zero heap memory
1056// allocations).
1057static thread_local bool thread_data_available = true;
1058
1059static thread_local std::aligned_storage<
1062
1063LogMessage::LogMessageData::LogMessageData()
1064 : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {}
1065
1066LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
1067 int ctr, void (LogMessage::*send_method)())
1068 : allocated_(NULL) {
1069 Init(file, line, severity, send_method);
1070 data_->stream_.set_ctr(ctr);
1071}
1072
1073LogMessage::LogMessage(const char* file, int line, const CheckOpString& result)
1074 : allocated_(NULL) {
1075 Init(file, line, GLOG_FATAL, &LogMessage::SendToLog);
1076 stream() << "Check failed: " << (*result.str_) << " ";
1077}
1078
1079LogMessage::LogMessage(const char* file, int line) : allocated_(NULL) {
1080 Init(file, line, GLOG_INFO, &LogMessage::SendToLog);
1081}
1082
1083LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
1084 : allocated_(NULL) {
1085 Init(file, line, severity, &LogMessage::SendToLog);
1086}
1087
1088LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
1089 LogSink* sink, bool also_send_to_log)
1090 : allocated_(NULL) {
1091 Init(file, line, severity,
1092 also_send_to_log ? &LogMessage::SendToSinkAndLog
1093 : &LogMessage::SendToSink);
1094 data_->sink_ = sink; // override Init()'s setting to NULL
1095}
1096
1097LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
1098 vector<string>* outvec)
1099 : allocated_(NULL) {
1100 Init(file, line, severity, &LogMessage::SaveOrSendToLog);
1101 data_->outvec_ = outvec; // override Init()'s setting to NULL
1102}
1103
1104LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
1105 string* message)
1106 : allocated_(NULL) {
1107 Init(file, line, severity, &LogMessage::WriteToStringAndLog);
1108 data_->message_ = message; // override Init()'s setting to NULL
1109}
1110
1111void LogMessage::Init(const char* file, int line, LogSeverity severity,
1112 void (LogMessage::*send_method)()) {
1113 allocated_ = NULL;
1114 if (severity != GLOG_FATAL || !exit_on_dfatal) {
1115 // No need for locking, because this is thread local.
1117 thread_data_available = false;
1118 data_ = new (&thread_msg_data) LogMessageData;
1119 } else {
1120 allocated_ = new LogMessageData();
1121 data_ = allocated_;
1122 }
1123 data_->first_fatal_ = false;
1124 } else {
1125 absl::MutexLock l(&fatal_msg_lock);
1126 if (fatal_msg_exclusive) {
1127 fatal_msg_exclusive = false;
1128 data_ = &fatal_msg_data_exclusive;
1129 data_->first_fatal_ = true;
1130 } else {
1131 data_ = &fatal_msg_data_shared;
1132 data_->first_fatal_ = false;
1133 }
1134 }
1135
1136 stream().fill('0');
1137 data_->preserved_errno_ = errno;
1138 data_->severity_ = severity;
1139 data_->line_ = line;
1140 data_->send_method_ = send_method;
1141 data_->sink_ = NULL;
1142 data_->outvec_ = NULL;
1143 timespec now_ts = absl::ToTimespec(absl::Now());
1144 data_->timestamp_ = now_ts.tv_sec;
1145 localtime_r(&data_->timestamp_, &data_->tm_time_);
1146 int usecs = now_ts.tv_nsec / 1000;
1147
1148 data_->num_chars_to_log_ = 0;
1149 data_->num_chars_to_syslog_ = 0;
1151 data_->fullname_ = file;
1152 data_->has_been_flushed_ = false;
1153
1154 // If specified, prepend a prefix to each line. For example:
1155 // I1018 160715 f5d4fbb0 logging.cc:1153]
1156 // (log level, GMT month, date, time, thread_id, file basename, line)
1157 // We exclude the thread_id for the default thread.
1158 if (absl::GetFlag(FLAGS_log_prefix) && (line != kNoLogPrefix)) {
1159 stream() << LogSeverityNames[severity][0] << setw(2)
1160 << 1 + data_->tm_time_.tm_mon << setw(2) << data_->tm_time_.tm_mday
1161 << ' ' << setw(2) << data_->tm_time_.tm_hour << ':' << setw(2)
1162 << data_->tm_time_.tm_min << ':' << setw(2)
1163 << data_->tm_time_.tm_sec << "." << setw(6) << usecs << ' '
1164 << setfill(' ') << setw(5) << logging_internal::GetTID()
1165 << setfill('0') << ' ' << data_->basename_ << ':' << data_->line_
1166 << "] ";
1167 }
1168 data_->num_prefix_chars_ = data_->stream_.pcount();
1169
1170 if (!absl::GetFlag(FLAGS_log_backtrace_at).empty()) {
1171 char fileline[128];
1172 snprintf(fileline, sizeof(fileline), "%s:%d", data_->basename_, line);
1173 if (!strcmp(absl::GetFlag(FLAGS_log_backtrace_at).c_str(), fileline)) {
1174 string stacktrace;
1176 stream() << " (stacktrace:\n" << stacktrace << ") ";
1177 }
1178 }
1179}
1180
1182 Flush();
1183#ifdef GLOG_THREAD_LOCAL_STORAGE
1184 if (data_ == static_cast<void*>(&thread_msg_data)) {
1185 data_->~LogMessageData();
1186 thread_data_available = true;
1187 } else {
1188 delete allocated_;
1189 }
1190#else // !defined(GLOG_THREAD_LOCAL_STORAGE)
1191 delete allocated_;
1192#endif // defined(GLOG_THREAD_LOCAL_STORAGE)
1193}
1194
1195int LogMessage::preserved_errno() const { return data_->preserved_errno_; }
1196
1197ostream& LogMessage::stream() { return data_->stream_; }
1198
1199// Flush buffered message, called by the destructor, or any other function
1200// that needs to synchronize the log.
1202 if (data_->has_been_flushed_ ||
1203 data_->severity_ < absl::GetFlag(FLAGS_minloglevel))
1204 return;
1205
1206 data_->num_chars_to_log_ = data_->stream_.pcount();
1207 data_->num_chars_to_syslog_ =
1208 data_->num_chars_to_log_ - data_->num_prefix_chars_;
1209
1210 // Do we need to add a \n to the end of this message?
1211 bool append_newline =
1212 (data_->message_text_[data_->num_chars_to_log_ - 1] != '\n');
1213 char original_final_char = '\0';
1214
1215 // If we do need to add a \n, we'll do it by violating the memory of the
1216 // ostrstream buffer. This is quick, and we'll make sure to undo our
1217 // modification before anything else is done with the ostrstream. It
1218 // would be preferable not to do things this way, but it seems to be
1219 // the best way to deal with this.
1220 if (append_newline) {
1221 original_final_char = data_->message_text_[data_->num_chars_to_log_];
1222 data_->message_text_[data_->num_chars_to_log_++] = '\n';
1223 }
1224
1225 // Prevent any subtle race conditions by wrapping a absl::Mutex lock around
1226 // the actual logging action per se.
1227 {
1228 absl::MutexLock l(&log_mutex);
1229 (this->*(data_->send_method_))();
1230 ++num_messages_[static_cast<int>(data_->severity_)];
1231 }
1232 LogDestination::WaitForSinks(data_);
1233
1234 if (append_newline) {
1235 // Fix the ostrstream back how it was before we screwed with it.
1236 // It's 99.44% certain that we don't need to worry about doing this.
1237 data_->message_text_[data_->num_chars_to_log_ - 1] = original_final_char;
1238 }
1239
1240 // If errno was already set before we enter the logging call, we'll
1241 // set it back to that value when we return from the logging call.
1242 // It happens often that we log an error message after a syscall
1243 // failure, which can potentially set the errno to some other
1244 // values. We would like to preserve the original errno.
1245 if (data_->preserved_errno_ != 0) {
1246 errno = data_->preserved_errno_;
1247 }
1248
1249 // Note that this message is now safely logged. If we're asked to flush
1250 // again, as a result of destruction, say, we'll do nothing on future calls.
1251 data_->has_been_flushed_ = true;
1252}
1253
1254// Copy of first FATAL log message so that we can print it out again
1255// after all the stack traces. To preserve legacy behavior, we don't
1256// use fatal_msg_data_exclusive.
1257static time_t fatal_time;
1258static char fatal_message[256];
1259
1261 if (fatal_message[0]) {
1262 const int n = strlen(fatal_message);
1263 if (!absl::GetFlag(FLAGS_logtostderr)) {
1264 // Also write to stderr (don't color to avoid terminal checks)
1266 }
1267 LogDestination::LogToAllLogfiles(GLOG_ERROR, fatal_time, fatal_message, n);
1268 }
1269}
1270
1271// L >= log_mutex (callers must hold the log_mutex).
1272void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
1273 static bool already_warned_before_initgoogle = false;
1274
1275 log_mutex.AssertHeld();
1276
1277 RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
1278 data_->message_text_[data_->num_chars_to_log_ - 1] == '\n',
1279 "");
1280
1281 // Messages of a given severity get logged to lower severity logs, too
1282
1283 if (!already_warned_before_initgoogle &&
1285 const char w[] =
1286 "WARNING: Logging before InitGoogleLogging() is "
1287 "written to STDERR\n";
1288 WriteToStderr(w, strlen(w));
1289 already_warned_before_initgoogle = true;
1290 }
1291
1292 // global flag: never log to file if set. Also -- don't log to a
1293 // file if we haven't parsed the command line flags to get the
1294 // program name.
1295 if (absl::GetFlag(FLAGS_logtostderr) ||
1298 data_->num_chars_to_log_);
1299
1300 // this could be protected by a flag if necessary.
1301 LogDestination::LogToSinks(
1302 data_->severity_, data_->fullname_, data_->basename_, data_->line_,
1303 &data_->tm_time_, data_->message_text_ + data_->num_prefix_chars_,
1304 (data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1));
1305 } else {
1306 // log this message to all log files of severity <= severity_
1307 LogDestination::LogToAllLogfiles(data_->severity_, data_->timestamp_,
1308 data_->message_text_,
1309 data_->num_chars_to_log_);
1310
1311 LogDestination::MaybeLogToStderr(data_->severity_, data_->message_text_,
1312 data_->num_chars_to_log_);
1313 LogDestination::LogToSinks(
1314 data_->severity_, data_->fullname_, data_->basename_, data_->line_,
1315 &data_->tm_time_, data_->message_text_ + data_->num_prefix_chars_,
1316 (data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1));
1317 // NOTE: -1 removes trailing \n
1318 }
1319
1320 // If we log a FATAL message, flush all the log destinations, then toss
1321 // a signal for others to catch. We leave the logs in a state that
1322 // someone else can use them (as long as they flush afterwards)
1323 if (data_->severity_ == GLOG_FATAL && exit_on_dfatal) {
1324 if (data_->first_fatal_) {
1325 // Store crash information so that it is accessible from within signal
1326 // handlers that may be invoked later.
1327 RecordCrashReason(&crash_reason);
1329
1330 // Store shortened fatal message for other logs and GWQ status
1331 const int copy =
1332 min<int>(data_->num_chars_to_log_, sizeof(fatal_message) - 1);
1333 memcpy(fatal_message, data_->message_text_, copy);
1334 fatal_message[copy] = '\0';
1335 fatal_time = data_->timestamp_;
1336 }
1337
1338 if (!absl::GetFlag(FLAGS_logtostderr)) {
1339 for (int i = 0; i < NUM_SEVERITIES; ++i) {
1340 if (LogDestination::log_destinations_[i])
1341 LogDestination::log_destinations_[i]->logger_->Write(true, 0, "", 0);
1342 }
1343 }
1344
1345 // release the lock that our caller (directly or indirectly)
1346 // LogMessage::~LogMessage() grabbed so that signal handlers
1347 // can use the logging facility. Alternately, we could add
1348 // an entire unsafe logging interface to bypass locking
1349 // for signal handlers but this seems simpler.
1350 log_mutex.Unlock();
1351 LogDestination::WaitForSinks(data_);
1352
1353 const char* message = "*** Check failure stack trace: ***\n";
1354 if (write(STDERR_FILENO, message, strlen(message)) < 0) {
1355 // Ignore errors.
1356 }
1357 Fail();
1358 }
1359}
1360
1361void LogMessage::RecordCrashReason(logging_internal::CrashReason* reason) {
1366 // Retrieve the stack trace, omitting the logging frames that got us here.
1367 reason->depth =
1368 absl::GetStackTrace(reason->stack, ABSL_ARRAYSIZE(reason->stack), 4);
1369}
1370
1371#if !defined(_MSC_VER)
1372#define ATTRIBUTE_NORETURN __attribute__((noreturn))
1373#else
1374#define ATTRIBUTE_NORETURN
1375#endif
1376
1377#if defined(_MSC_VER)
1378__declspec(noreturn)
1379#endif
1380 static void logging_fail() ATTRIBUTE_NORETURN;
1381
1382static void logging_fail() { abort(); }
1383
1385
1388
1389void InstallFailureFunction(void (*fail_func)()) {
1391}
1392
1394
1395// L >= log_mutex (callers must hold the log_mutex).
1396void LogMessage::SendToSink() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
1397 if (data_->sink_ != NULL) {
1398 RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
1399 data_->message_text_[data_->num_chars_to_log_ - 1] == '\n',
1400 "");
1401 data_->sink_->send(
1402 data_->severity_, data_->fullname_, data_->basename_, data_->line_,
1403 &data_->tm_time_, data_->message_text_ + data_->num_prefix_chars_,
1404 (data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1));
1405 }
1406}
1407
1408// L >= log_mutex (callers must hold the log_mutex).
1409void LogMessage::SendToSinkAndLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
1410 SendToSink();
1411 SendToLog();
1412}
1413
1414// L >= log_mutex (callers must hold the log_mutex).
1415void LogMessage::SaveOrSendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
1416 if (data_->outvec_ != NULL) {
1417 RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
1418 data_->message_text_[data_->num_chars_to_log_ - 1] == '\n',
1419 "");
1420 // Omit prefix of message and trailing newline when recording in outvec_.
1421 const char* start = data_->message_text_ + data_->num_prefix_chars_;
1422 int len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
1423 data_->outvec_->push_back(string(start, len));
1424 } else {
1425 SendToLog();
1426 }
1427}
1428
1429void LogMessage::WriteToStringAndLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
1430 if (data_->message_ != NULL) {
1431 RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
1432 data_->message_text_[data_->num_chars_to_log_ - 1] == '\n',
1433 "");
1434 // Omit prefix of message and trailing newline when writing to message_.
1435 const char* start = data_->message_text_ + data_->num_prefix_chars_;
1436 int len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
1437 data_->message_->assign(start, len);
1438 }
1439 SendToLog();
1440}
1441
1442// L >= log_mutex (callers must hold the log_mutex).
1444#if !defined(_MSC_VER)
1445 // Before any calls to syslog(), make a single call to openlog()
1446 static bool openlog_already_called = false;
1447 if (!openlog_already_called) {
1449 LOG_CONS | LOG_NDELAY | LOG_PID, LOG_USER);
1450 openlog_already_called = true;
1451 }
1452
1453 // This array maps Google severity levels to syslog levels
1454 const int SEVERITY_TO_LEVEL[] = {LOG_INFO, LOG_WARNING, LOG_ERR, LOG_EMERG};
1455 syslog(LOG_USER | SEVERITY_TO_LEVEL[static_cast<int>(data_->severity_)],
1456 "%.*s", static_cast<int>(data_->num_chars_to_syslog_),
1457 data_->message_text_ + data_->num_prefix_chars_);
1458 SendToLog();
1459#else
1460 LOG(ERROR) << "No syslog support: message=" << data_->message_text_;
1461#endif
1462}
1463
1465 absl::MutexLock l(&log_mutex);
1466 return LogDestination::log_destination(severity)->logger_;
1467}
1468
1470 absl::MutexLock l(&log_mutex);
1471 LogDestination::log_destination(severity)->logger_ = logger;
1472}
1473
1474// L < log_mutex. Acquires and releases absl::Mutex_.
1475int64_t LogMessage::num_messages(int severity) {
1476 absl::MutexLock l(&log_mutex);
1477 return num_messages_[severity];
1478}
1479
1480// Output the COUNTER value. This is only valid if ostream is a
1481// LogStream.
1482ostream& operator<<(ostream& os, const PRIVATE_Counter&) {
1483#ifdef DISABLE_RTTI
1484 LogMessage::LogStream* log = static_cast<LogMessage::LogStream*>(&os);
1485#else
1486 LogMessage::LogStream* log = dynamic_cast<LogMessage::LogStream*>(&os);
1487#endif
1488 CHECK(log && log == log->self())
1489 << "You must not use COUNTER with non-glog ostream";
1490 os << log->ctr();
1491 return os;
1492}
1493
1495 LogSeverity severity, int ctr,
1496 void (LogMessage::*send_method)())
1497 : LogMessage(file, line, severity, ctr, send_method) {}
1498
1500 // Don't access errno directly because it may have been altered
1501 // while streaming the message.
1502 stream() << ": " << StrError(preserved_errno()) << " [" << preserved_errno()
1503 << "]";
1504}
1505
1506void FlushLogFiles(LogSeverity min_severity) {
1507 LogDestination::FlushLogFiles(min_severity);
1508}
1509
1512}
1513
1514void SetLogDestination(LogSeverity severity, const char* base_filename) {
1515 LogDestination::SetLogDestination(severity, base_filename);
1516}
1517
1518void SetLogSymlink(LogSeverity severity, const char* symlink_basename) {
1519 LogDestination::SetLogSymlink(severity, symlink_basename);
1520}
1521
1523
1525 // noop default
1526}
1527
1528string LogSink::ToString(LogSeverity severity, const char* file, int line,
1529 const struct ::tm* tm_time, const char* message,
1530 size_t message_len) {
1531 ostringstream stream(string(message, message_len));
1532 stream.fill('0');
1533
1534 // FIXME(jrvb): Updating this to use the correct value for usecs
1535 // requires changing the signature for both this method and
1536 // LogSink::send(). This change needs to be done in a separate CL
1537 // so subclasses of LogSink can be updated at the same time.
1538 int usecs = 0;
1539
1540 stream << LogSeverityNames[severity][0] << setw(2) << 1 + tm_time->tm_mon
1541 << setw(2) << tm_time->tm_mday << ' ' << setw(2) << tm_time->tm_hour
1542 << ':' << setw(2) << tm_time->tm_min << ':' << setw(2)
1543 << tm_time->tm_sec << '.' << setw(6) << usecs << ' ' << setfill(' ')
1544 << setw(5) << logging_internal::GetTID() << setfill('0') << ' ' << file
1545 << ':' << line << "] ";
1546
1547 stream << string(message, message_len);
1548 return stream.str();
1549}
1550
1551void AddLogSink(LogSink* destination) {
1552 LogDestination::AddLogSink(destination);
1553}
1554
1555void RemoveLogSink(LogSink* destination) {
1556 LogDestination::RemoveLogSink(destination);
1557}
1558
1559void SetLogFilenameExtension(const char* ext) {
1561}
1562
1563void SetStderrLogging(LogSeverity min_severity) {
1565}
1566
1568
1569namespace base {
1570namespace internal {
1571
1572bool GetExitOnDFatal();
1574 absl::MutexLock l(&log_mutex);
1575 return exit_on_dfatal;
1576}
1577
1578// Determines whether we exit the program for a LOG(DFATAL) message in
1579// debug mode. It does this by skipping the call to Fail/FailQuietly.
1580// This is intended for testing only.
1581//
1582// This can have some effects on LOG(FATAL) as well. Failure messages
1583// are always allocated (rather than sharing a buffer), the crash
1584// reason is not recorded, the "gwq" status message is not updated,
1585// and the stack trace is not recorded. The LOG(FATAL) *will* still
1586// exit the program. Since this function is used only in testing,
1587// these differences are acceptable.
1588void SetExitOnDFatal(bool value);
1590 absl::MutexLock l(&log_mutex);
1592}
1593
1594} // namespace internal
1595} // namespace base
1596
1597// Shell-escaping as we need to shell out ot /bin/mail.
1598static const char kDontNeedShellEscapeChars[] =
1599 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1600 "abcdefghijklmnopqrstuvwxyz"
1601 "0123456789+-_.=/:,@";
1602
1603static string ShellEscape(const string& src) {
1604 string result;
1605 if (!src.empty() && // empty string needs quotes
1606 src.find_first_not_of(kDontNeedShellEscapeChars) == string::npos) {
1607 // only contains chars that don't need quotes; it's fine
1608 result.assign(src);
1609 } else if (src.find_first_of('\'') == string::npos) {
1610 // no single quotes; just wrap it in single quotes
1611 result.assign("'");
1612 result.append(src);
1613 result.append("'");
1614 } else {
1615 // needs double quote escaping
1616 result.assign("\"");
1617 for (size_t i = 0; i < src.size(); ++i) {
1618 switch (src[i]) {
1619 case '\\':
1620 case '$':
1621 case '"':
1622 case '`':
1623 result.append("\\");
1624 }
1625 result.append(src, i, 1);
1626 }
1627 result.append("\"");
1628 }
1629 return result;
1630}
1631
1632static void GetTempDirectories(vector<string>* list) {
1633 list->clear();
1634#ifdef _MSC_VER
1635 // On windows we'll try to find a directory in this order:
1636 // C:/Documents & Settings/whomever/TEMP (or whatever GetTempPath() is)
1637 // C:/TMP/
1638 // C:/TEMP/
1639 // C:/WINDOWS/ or C:/WINNT/
1640 // .
1641 char tmp[MAX_PATH];
1642 if (GetTempPathA(MAX_PATH, tmp)) list->push_back(tmp);
1643 list->push_back("C:\\tmp\\");
1644 list->push_back("C:\\temp\\");
1645#else
1646 // Directories, in order of preference. If we find a dir that
1647 // exists, we stop adding other less-preferred dirs
1648 const char* candidates[] = {
1649 // Non-null only during unittest/regtest
1650 getenv("TEST_TMPDIR"),
1651
1652 // Explicitly-supplied temp dirs
1653 getenv("TMPDIR"),
1654 getenv("TMP"),
1655
1656 // If all else fails
1657 "/tmp",
1658 };
1659
1660 for (size_t i = 0; i < ABSL_ARRAYSIZE(candidates); i++) {
1661 const char* d = candidates[i];
1662 if (!d) continue; // Empty env var
1663
1664 // Make sure we don't surprise anyone who's expecting a '/'
1665 string dstr = d;
1666 if (dstr[dstr.size() - 1] != '/') {
1667 dstr += "/";
1668 }
1669 list->push_back(dstr);
1670
1671 struct stat statbuf;
1672 if (!stat(d, &statbuf) && S_ISDIR(statbuf.st_mode)) {
1673 // We found a dir that exists - we're done.
1674 return;
1675 }
1676 }
1677
1678#endif
1679}
1680
1681static vector<string>* logging_directories_list;
1682
1683const vector<string>& GetLoggingDirectories() {
1684 // Not strictly thread-safe but we're called early in InitGoogle().
1685 if (logging_directories_list == NULL) {
1686 logging_directories_list = new vector<string>;
1687
1688 if (!absl::GetFlag(FLAGS_log_dir).empty()) {
1689 // A dir was specified, we should use it
1690 logging_directories_list->push_back(absl::GetFlag(FLAGS_log_dir).c_str());
1691 } else {
1693#ifdef _MSC_VER
1694 char tmp[MAX_PATH];
1695 if (GetWindowsDirectoryA(tmp, MAX_PATH))
1696 logging_directories_list->push_back(tmp);
1697 logging_directories_list->push_back(".\\");
1698#else
1699 logging_directories_list->push_back("./");
1700#endif
1701 }
1702 }
1704}
1705
1707 fprintf(stderr,
1708 "TestOnly_ClearLoggingDirectoriesList should only be "
1709 "called from test code.\n");
1712}
1713
1714void GetExistingTempDirectories(vector<string>* list) {
1715 GetTempDirectories(list);
1716 vector<string>::iterator i_dir = list->begin();
1717 while (i_dir != list->end()) {
1718 // zero arg to access means test for existence; no constant
1719 // defined on windows
1720 if (access(i_dir->c_str(), 0)) {
1721 i_dir = list->erase(i_dir);
1722 } else {
1723 ++i_dir;
1724 }
1725 }
1726}
1727
1728// Helper functions for string comparisons.
1729#define DEFINE_CHECK_STROP_IMPL(name, func, expected) \
1730 string* Check##func##expected##Impl(const char* s1, const char* s2, \
1731 const char* names) { \
1732 bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2)); \
1733 if (equal == expected) { \
1734 return NULL; \
1735 } else { \
1736 ostringstream ss; \
1737 if (!s1) s1 = ""; \
1738 if (!s2) s2 = ""; \
1739 ss << #name " failed: " << names << " (" << s1 << " vs. " << s2 << ")"; \
1740 return new string(ss.str()); \
1741 } \
1742 }
1746DEFINE_CHECK_STROP_IMPL(CHECK_STRCASENE, strcasecmp, false)
1747#undef DEFINE_CHECK_STROP_IMPL
1748
1749int posix_strerror_r(int err, char* buf, size_t len) {
1750 // Sanity check input parameters
1751 if (buf == NULL || len <= 0) {
1752 errno = EINVAL;
1753 return -1;
1754 }
1755
1756 // Reset buf and errno, and try calling whatever version of strerror_r()
1757 // is implemented by glibc
1758 buf[0] = '\000';
1759 int old_errno = errno;
1760 errno = 0;
1761 char* rc = reinterpret_cast<char*>(strerror_r(err, buf, len));
1762
1763 // Both versions set errno on failure
1764 if (errno) {
1765 // Should already be there, but better safe than sorry
1766 buf[0] = '\000';
1767 return -1;
1768 }
1769 errno = old_errno;
1770
1771 // POSIX is vague about whether the string will be terminated, although
1772 // is indirectly implies that typically ERANGE will be returned, instead
1773 // of truncating the string. This is different from the GNU implementation.
1774 // We play it safe by always terminating the string explicitly.
1775 buf[len - 1] = '\000';
1776
1777 // If the function succeeded, we can use its exit code to determine the
1778 // semantics implemented by glibc
1779 if (!rc) {
1780 return 0;
1781 } else {
1782 // GNU semantics detected
1783 if (rc == buf) {
1784 return 0;
1785 } else {
1786 buf[0] = '\000';
1787#if defined(OS_MACOSX) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
1788 if (reinterpret_cast<intptr_t>(rc) < sys_nerr) {
1789 // This means an error on MacOSX or FreeBSD.
1790 return -1;
1791 }
1792#endif
1793 strncat(buf, rc, len - 1);
1794 return 0;
1795 }
1796 }
1797}
1798
1799string StrError(int err) {
1800 char buf[100];
1801 int rc = posix_strerror_r(err, buf, sizeof(buf));
1802 if ((rc < 0) || (buf[0] == '\000')) {
1803 snprintf(buf, sizeof(buf), "Error number %d", err);
1804 }
1805 return buf;
1806}
1807
1809 : LogMessage(file, line, GLOG_FATAL) {}
1810
1812 const CheckOpString& result)
1813 : LogMessage(file, line, result) {}
1814
1816 Flush();
1818}
1819
1820namespace base {
1821
1823 : stream_(new ostringstream) {
1824 *stream_ << exprtext << " (";
1825}
1826
1828
1830 *stream_ << " vs. ";
1831 return stream_;
1832}
1833
1835 *stream_ << ")";
1836 return new string(stream_->str());
1837}
1838
1839} // namespace base
1840
1841template <>
1842void MakeCheckOpValueString(std::ostream* os, const char& v) {
1843 if (v >= 32 && v <= 126) {
1844 (*os) << "'" << v << "'";
1845 } else {
1846 (*os) << "char value " << (int16_t)v;
1847 }
1848}
1849
1850template <>
1851void MakeCheckOpValueString(std::ostream* os, const signed char& v) {
1852 if (v >= 32 && v <= 126) {
1853 (*os) << "'" << v << "'";
1854 } else {
1855 (*os) << "signed char value " << (int16_t)v;
1856 }
1857}
1858
1859template <>
1860void MakeCheckOpValueString(std::ostream* os, const unsigned char& v) {
1861 if (v >= 32 && v <= 126) {
1862 (*os) << "'" << v << "'";
1863 } else {
1864 (*os) << "unsigned char value " << (uint16_t)v;
1865 }
1866}
1867
1868template <>
1869void MakeCheckOpValueString(std::ostream* os, const std::nullptr_t& v) {
1870 (*os) << "nullptr";
1871}
1872
1873void InitGoogleLogging(const char* argv0) {
1875}
1876
1882}
1883
1884} // namespace google
int64_t min
Definition: alldiff_cst.cc:139
#define PATH_SEPARATOR
ABSL_DECLARE_FLAG(bool, log_prefix)
ABSL_FLAG(bool, logtostderr, false, "log messages go to stderr instead of logfiles")
static const char * DefaultLogDir()
static void GetHostName(string *hostname)
#define DEFINE_CHECK_STROP_IMPL(name, func, expected)
static bool TerminalSupportsColor()
void FixFlagsAndEnvironmentForSwig()
Definition: base/logging.cc:61
#define ATTRIBUTE_NORETURN
#define CHECK(condition)
Definition: base/logging.h:491
#define CHECK_STRNE(s1, s2)
Definition: base/logging.h:737
#define CHECK_LT(val1, val2)
Definition: base/logging.h:701
#define CHECK_GE(val1, val2)
Definition: base/logging.h:702
#define CHECK_STRCASEEQ(s1, s2)
Definition: base/logging.h:738
#define CHECK_STRCASENE(s1, s2)
Definition: base/logging.h:739
#define LOG(severity)
Definition: base/logging.h:416
#define CHECK_STREQ(s1, s2)
Definition: base/logging.h:736
ErrnoLogMessage(const char *file, int line, LogSeverity severity, int ctr, void(LogMessage::*send_method)())
static void AddLogSink(LogSink *destination)
static void RemoveLogSink(LogSink *destination)
static void SetStderrLogging(LogSeverity min_severity)
static void FlushLogFilesUnsafe(int min_severity)
static void SetLogSymlink(LogSeverity severity, const char *symlink_basename)
static void SetLogFilenameExtension(const char *filename_extension)
static void LogToStderr()
static void SetLogDestination(LogSeverity severity, const char *base_filename)
static void DeleteLogDestinations()
static const bool & terminal_supports_color()
static const string & hostname()
static void FlushLogFiles(int min_severity)
LogStream * self() const
LogMessageFatal(const char *file, int line)
ATTRIBUTE_NORETURN ~LogMessageFatal()
int preserved_errno() const
LogMessage(const char *file, int line, LogSeverity severity, int ctr, SendMethod send_method)
std::ostream & stream()
static int64_t num_messages(int severity)
static const size_t kMaxLogMessageLen
static void ATTRIBUTE_NORETURN Fail()
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
virtual ~LogSink()
static std::string ToString(LogSeverity severity, const char *file, int line, const struct ::tm *tm_time, const char *message, size_t message_len)
virtual void WaitTillSent()
CheckOpMessageBuilder(const char *exprtext)
virtual void Flush()=0
Block * next
int64_t value
int LogSeverity
Definition: log_severity.h:22
const int ERROR
Definition: log_severity.h:32
#define GOOGLE_GLOG_DLL_DECL
void SetExitOnDFatal(bool value)
GOOGLE_GLOG_DLL_DECL Logger * GetLogger(LogSeverity level)
GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger *logger)
void DumpStackTraceToString(std::string *stacktrace)
void InitGoogleLoggingUtilities(const char *argv0)
const char * ProgramInvocationShortName()
const std::string & MyUserName()
void SetCrashReason(const CrashReason *r)
int64_t UsecToCycles(int64_t usec)
const char * const_basename(const char *filepath)
ostream & operator<<(ostream &os, const PRIVATE_Counter &)
static thread_local bool thread_data_available
static char fatal_message[256]
const int GLOG_WARNING
Definition: log_severity.h:25
void InitGoogleLogging(const char *argv0)
static GLogColor SeverityToColor(LogSeverity severity)
static thread_local std::aligned_storage< sizeof(LogMessage::LogMessageData), alignof(LogMessage::LogMessageData)>::type thread_msg_data
static absl::Mutex log_mutex
GOOGLE_GLOG_DLL_DECL logging_fail_func_t g_logging_fail_func
void FlushLogFilesUnsafe(LogSeverity min_severity)
void(* logging_fail_func_t)() ATTRIBUTE_NORETURN
static absl::Mutex fatal_msg_lock
static vector< string > * logging_directories_list
void SetLogFilenameExtension(const char *ext)
static void ColoredWriteToStderr(LogSeverity severity, const char *message, size_t len)
static bool exit_on_dfatal
void SetLogDestination(LogSeverity severity, const char *base_filename)
void SetStderrLogging(LogSeverity min_severity)
const char * GetLogSeverityName(LogSeverity severity)
const int NUM_SEVERITIES
Definition: log_severity.h:26
void GetExistingTempDirectories(vector< string > *list)
void MakeCheckOpValueString(std::ostream *os, const char &v)
void ShutdownGoogleLogging()
static bool fatal_msg_exclusive
void InstallFailureFunction(void(*fail_func)())
static const char * GetAnsiColorCode(GLogColor color)
static LogMessage::LogMessageData fatal_msg_data_exclusive
GOOGLE_GLOG_DLL_DECL const char *const LogSeverityNames[NUM_SEVERITIES]
static LogMessage::LogMessageData fatal_msg_data_shared
string StrError(int err)
int posix_strerror_r(int err, char *buf, size_t len)
const vector< string > & GetLoggingDirectories()
void SetLogSymlink(LogSeverity severity, const char *symlink_basename)
static string ShellEscape(const string &src)
@ COLOR_DEFAULT
@ COLOR_YELLOW
static const char kDontNeedShellEscapeChars[]
static int32_t MaxLogSize()
void AddLogSink(LogSink *destination)
static time_t fatal_time
void LogToStderr()
const int GLOG_FATAL
Definition: log_severity.h:25
void FlushLogFiles(LogSeverity min_severity)
static logging_internal::CrashReason crash_reason
static bool stop_writing
void TestOnly_ClearLoggingDirectoriesList()
static void WriteToStderr(const char *message, size_t len)
const int GLOG_ERROR
Definition: log_severity.h:25
static void logging_fail() ATTRIBUTE_NORETURN
static void GetTempDirectories(vector< string > *list)
const int GLOG_INFO
Definition: log_severity.h:25
void RemoveLogSink(LogSink *destination)
void ReprintFatalMessage()
#define RAW_DCHECK(condition, message)
Definition: raw_logging.h:117
std::string * str_
Definition: base/logging.h:504
char message_text_[LogMessage::kMaxLogMessageLen+1]
void(LogMessage::* send_method_)()
std::vector< std::string > * outvec_
std::string message
Definition: trace.cc:398