xref: /aosp_15_r20/external/abseil-cpp/absl/log/internal/log_message.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
1 //
2 // Copyright 2022 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "absl/log/internal/log_message.h"
17 
18 #include <stddef.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #ifndef _WIN32
24 #include <unistd.h>
25 #endif
26 
27 #include <algorithm>
28 #include <array>
29 #include <atomic>
30 #include <ios>
31 #include <memory>
32 #include <ostream>
33 #include <string>
34 #include <tuple>
35 
36 #include "absl/base/attributes.h"
37 #include "absl/base/config.h"
38 #include "absl/base/internal/raw_logging.h"
39 #include "absl/base/internal/strerror.h"
40 #include "absl/base/internal/sysinfo.h"
41 #include "absl/base/log_severity.h"
42 #include "absl/container/inlined_vector.h"
43 #include "absl/debugging/internal/examine_stack.h"
44 #include "absl/log/globals.h"
45 #include "absl/log/internal/append_truncated.h"
46 #include "absl/log/internal/globals.h"
47 #include "absl/log/internal/log_format.h"
48 #include "absl/log/internal/log_sink_set.h"
49 #include "absl/log/internal/proto.h"
50 #include "absl/log/log_entry.h"
51 #include "absl/log/log_sink.h"
52 #include "absl/log/log_sink_registry.h"
53 #include "absl/memory/memory.h"
54 #include "absl/strings/string_view.h"
55 #include "absl/time/clock.h"
56 #include "absl/time/time.h"
57 #include "absl/types/span.h"
58 
ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)59 extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
60     AbslInternalOnFatalLogMessage)(const absl::LogEntry&) {
61   // Default - Do nothing
62 }
63 
64 namespace absl {
65 ABSL_NAMESPACE_BEGIN
66 namespace log_internal {
67 
68 namespace {
69 // message `logging.proto.Event`
70 enum EventTag : uint8_t {
71   kFileName = 2,
72   kFileLine = 3,
73   kTimeNsecs = 4,
74   kSeverity = 5,
75   kThreadId = 6,
76   kValue = 7,
77   kSequenceNumber = 9,
78   kThreadName = 10,
79 };
80 
81 // message `logging.proto.Value`
82 enum ValueTag : uint8_t {
83   kString = 1,
84   kStringLiteral = 6,
85 };
86 
87 // Decodes a `logging.proto.Value` from `buf` and writes a string representation
88 // into `dst`.  The string representation will be truncated if `dst` is not
89 // large enough to hold it.  Returns false if `dst` has size zero or one (i.e.
90 // sufficient only for a nul-terminator) and no decoded data could be written.
91 // This function may or may not write a nul-terminator into `dst`, and it may or
92 // may not truncate the data it writes in order to do make space for that nul
93 // terminator.  In any case, `dst` will be advanced to point at the byte where
94 // subsequent writes should begin.
PrintValue(absl::Span<char> & dst,absl::Span<const char> buf)95 bool PrintValue(absl::Span<char>& dst, absl::Span<const char> buf) {
96   if (dst.size() <= 1) return false;
97   ProtoField field;
98   while (field.DecodeFrom(&buf)) {
99     switch (field.tag()) {
100       case ValueTag::kString:
101       case ValueTag::kStringLiteral:
102         if (field.type() == WireType::kLengthDelimited)
103           if (log_internal::AppendTruncated(field.string_value(), dst) <
104               field.string_value().size())
105             return false;
106     }
107   }
108   return true;
109 }
110 
111 // See `logging.proto.Severity`
ProtoSeverity(absl::LogSeverity severity,int verbose_level)112 int32_t ProtoSeverity(absl::LogSeverity severity, int verbose_level) {
113   switch (severity) {
114     case absl::LogSeverity::kInfo:
115       if (verbose_level == absl::LogEntry::kNoVerbosityLevel) return 800;
116       return 600 - verbose_level;
117     case absl::LogSeverity::kWarning:
118       return 900;
119     case absl::LogSeverity::kError:
120       return 950;
121     case absl::LogSeverity::kFatal:
122       return 1100;
123     default:
124       return 800;
125   }
126 }
127 
Basename(absl::string_view filepath)128 absl::string_view Basename(absl::string_view filepath) {
129 #ifdef _WIN32
130   size_t path = filepath.find_last_of("/\\");
131 #else
132   size_t path = filepath.find_last_of('/');
133 #endif
134   if (path != filepath.npos) filepath.remove_prefix(path + 1);
135   return filepath;
136 }
137 
WriteToString(const char * data,void * str)138 void WriteToString(const char* data, void* str) {
139   reinterpret_cast<std::string*>(str)->append(data);
140 }
WriteToStream(const char * data,void * os)141 void WriteToStream(const char* data, void* os) {
142   auto* cast_os = static_cast<std::ostream*>(os);
143   *cast_os << data;
144 }
145 }  // namespace
146 
147 struct LogMessage::LogMessageData final {
148   LogMessageData(const char* file, int line, absl::LogSeverity severity,
149                  absl::Time timestamp);
150   LogMessageData(const LogMessageData&) = delete;
151   LogMessageData& operator=(const LogMessageData&) = delete;
152 
153   // `LogEntry` sent to `LogSink`s; contains metadata.
154   absl::LogEntry entry;
155 
156   // true => this was first fatal msg
157   bool first_fatal;
158   // true => all failures should be quiet
159   bool fail_quietly;
160   // true => PLOG was requested
161   bool is_perror;
162 
163   // Extra `LogSink`s to log to, in addition to `global_sinks`.
164   absl::InlinedVector<absl::LogSink*, 16> extra_sinks;
165   // If true, log to `extra_sinks` but not to `global_sinks` or hardcoded
166   // non-sink targets (e.g. stderr, log files).
167   bool extra_sinks_only;
168 
169   std::ostream manipulated;  // ostream with IO manipulators applied
170 
171   // A `logging.proto.Event` proto message is built into `encoded_buf`.
172   std::array<char, kLogMessageBufferSize> encoded_buf;
173   // `encoded_remaining()` is the suffix of `encoded_buf` that has not been
174   // filled yet.  If a datum to be encoded does not fit into
175   // `encoded_remaining()` and cannot be truncated to fit, the size of
176   // `encoded_remaining()` will be zeroed to prevent encoding of any further
177   // data.  Note that in this case its `data()` pointer will not point past the
178   // end of `encoded_buf`.
179   // The first use of `encoded_remaining()` is our chance to record metadata
180   // after any modifications (e.g. by `AtLocation()`) but before any data have
181   // been recorded.  We want to record metadata before data so that data are
182   // preferentially truncated if we run out of buffer.
encoded_remainingabsl::log_internal::LogMessage::LogMessageData183   absl::Span<char>& encoded_remaining() {
184     if (encoded_remaining_actual_do_not_use_directly.data() == nullptr) {
185       encoded_remaining_actual_do_not_use_directly =
186           absl::MakeSpan(encoded_buf);
187       InitializeEncodingAndFormat();
188     }
189     return encoded_remaining_actual_do_not_use_directly;
190   }
191   absl::Span<char> encoded_remaining_actual_do_not_use_directly;
192 
193   // A formatted string message is built in `string_buf`.
194   std::array<char, kLogMessageBufferSize> string_buf;
195 
196   void InitializeEncodingAndFormat();
197   void FinalizeEncodingAndFormat();
198 };
199 
LogMessageData(const char * file,int line,absl::LogSeverity severity,absl::Time timestamp)200 LogMessage::LogMessageData::LogMessageData(const char* file, int line,
201                                            absl::LogSeverity severity,
202                                            absl::Time timestamp)
203     : extra_sinks_only(false), manipulated(nullptr) {
204   // Legacy defaults for LOG's ostream:
205   manipulated.setf(std::ios_base::showbase | std::ios_base::boolalpha);
206   entry.full_filename_ = file;
207   entry.base_filename_ = Basename(file);
208   entry.line_ = line;
209   entry.prefix_ = absl::ShouldPrependLogPrefix();
210   entry.severity_ = absl::NormalizeLogSeverity(severity);
211   entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
212   entry.timestamp_ = timestamp;
213   entry.tid_ = absl::base_internal::GetCachedTID();
214 }
215 
InitializeEncodingAndFormat()216 void LogMessage::LogMessageData::InitializeEncodingAndFormat() {
217   EncodeStringTruncate(EventTag::kFileName, entry.source_filename(),
218                        &encoded_remaining());
219   EncodeVarint(EventTag::kFileLine, entry.source_line(), &encoded_remaining());
220   EncodeVarint(EventTag::kTimeNsecs, absl::ToUnixNanos(entry.timestamp()),
221                &encoded_remaining());
222   EncodeVarint(EventTag::kSeverity,
223                ProtoSeverity(entry.log_severity(), entry.verbosity()),
224                &encoded_remaining());
225   EncodeVarint(EventTag::kThreadId, entry.tid(), &encoded_remaining());
226 }
227 
FinalizeEncodingAndFormat()228 void LogMessage::LogMessageData::FinalizeEncodingAndFormat() {
229   // Note that `encoded_remaining()` may have zero size without pointing past
230   // the end of `encoded_buf`, so the difference between `data()` pointers is
231   // used to compute the size of `encoded_data`.
232   absl::Span<const char> encoded_data(
233       encoded_buf.data(),
234       static_cast<size_t>(encoded_remaining().data() - encoded_buf.data()));
235   // `string_remaining` is the suffix of `string_buf` that has not been filled
236   // yet.
237   absl::Span<char> string_remaining(string_buf);
238   // We may need to write a newline and nul-terminator at the end of the decoded
239   // string data.  Rather than worry about whether those should overwrite the
240   // end of the string (if the buffer is full) or be appended, we avoid writing
241   // into the last two bytes so we always have space to append.
242   string_remaining.remove_suffix(2);
243   entry.prefix_len_ =
244       entry.prefix() ? log_internal::FormatLogPrefix(
245                            entry.log_severity(), entry.timestamp(), entry.tid(),
246                            entry.source_basename(), entry.source_line(),
247                            log_internal::ThreadIsLoggingToLogSink()
248                                ? PrefixFormat::kRaw
249                                : PrefixFormat::kNotRaw,
250                            string_remaining)
251                      : 0;
252   // Decode data from `encoded_buf` until we run out of data or we run out of
253   // `string_remaining`.
254   ProtoField field;
255   while (field.DecodeFrom(&encoded_data)) {
256     switch (field.tag()) {
257       case EventTag::kValue:
258         if (field.type() != WireType::kLengthDelimited) continue;
259         if (PrintValue(string_remaining, field.bytes_value())) continue;
260         break;
261     }
262   }
263   auto chars_written =
264       static_cast<size_t>(string_remaining.data() - string_buf.data());
265     string_buf[chars_written++] = '\n';
266   string_buf[chars_written++] = '\0';
267   entry.text_message_with_prefix_and_newline_and_nul_ =
268       absl::MakeSpan(string_buf).subspan(0, chars_written);
269 }
270 
LogMessage(const char * file,int line,absl::LogSeverity severity)271 LogMessage::LogMessage(const char* file, int line, absl::LogSeverity severity)
272     : data_(absl::make_unique<LogMessageData>(file, line, severity,
273                                               absl::Now())) {
274   data_->first_fatal = false;
275   data_->is_perror = false;
276   data_->fail_quietly = false;
277 
278   // This logs a backtrace even if the location is subsequently changed using
279   // AtLocation.  This quirk, and the behavior when AtLocation is called twice,
280   // are fixable but probably not worth fixing.
281   LogBacktraceIfNeeded();
282 }
283 
LogMessage(const char * file,int line,InfoTag)284 LogMessage::LogMessage(const char* file, int line, InfoTag)
285     : LogMessage(file, line, absl::LogSeverity::kInfo) {}
LogMessage(const char * file,int line,WarningTag)286 LogMessage::LogMessage(const char* file, int line, WarningTag)
287     : LogMessage(file, line, absl::LogSeverity::kWarning) {}
LogMessage(const char * file,int line,ErrorTag)288 LogMessage::LogMessage(const char* file, int line, ErrorTag)
289     : LogMessage(file, line, absl::LogSeverity::kError) {}
290 
~LogMessage()291 LogMessage::~LogMessage() {
292 #ifdef ABSL_MIN_LOG_LEVEL
293   if (data_->entry.log_severity() <
294           static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
295       data_->entry.log_severity() < absl::LogSeverity::kFatal) {
296     return;
297   }
298 #endif
299   Flush();
300 }
301 
AtLocation(absl::string_view file,int line)302 LogMessage& LogMessage::AtLocation(absl::string_view file, int line) {
303   data_->entry.full_filename_ = file;
304   data_->entry.base_filename_ = Basename(file);
305   data_->entry.line_ = line;
306   LogBacktraceIfNeeded();
307   return *this;
308 }
309 
NoPrefix()310 LogMessage& LogMessage::NoPrefix() {
311   data_->entry.prefix_ = false;
312   return *this;
313 }
314 
WithVerbosity(int verbose_level)315 LogMessage& LogMessage::WithVerbosity(int verbose_level) {
316   if (verbose_level == absl::LogEntry::kNoVerbosityLevel) {
317     data_->entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
318   } else {
319     data_->entry.verbose_level_ = std::max(0, verbose_level);
320   }
321   return *this;
322 }
323 
WithTimestamp(absl::Time timestamp)324 LogMessage& LogMessage::WithTimestamp(absl::Time timestamp) {
325   data_->entry.timestamp_ = timestamp;
326   return *this;
327 }
328 
WithThreadID(absl::LogEntry::tid_t tid)329 LogMessage& LogMessage::WithThreadID(absl::LogEntry::tid_t tid) {
330   data_->entry.tid_ = tid;
331   return *this;
332 }
333 
WithMetadataFrom(const absl::LogEntry & entry)334 LogMessage& LogMessage::WithMetadataFrom(const absl::LogEntry& entry) {
335   data_->entry.full_filename_ = entry.full_filename_;
336   data_->entry.base_filename_ = entry.base_filename_;
337   data_->entry.line_ = entry.line_;
338   data_->entry.prefix_ = entry.prefix_;
339   data_->entry.severity_ = entry.severity_;
340   data_->entry.verbose_level_ = entry.verbose_level_;
341   data_->entry.timestamp_ = entry.timestamp_;
342   data_->entry.tid_ = entry.tid_;
343   return *this;
344 }
345 
WithPerror()346 LogMessage& LogMessage::WithPerror() {
347   data_->is_perror = true;
348   return *this;
349 }
350 
ToSinkAlso(absl::LogSink * sink)351 LogMessage& LogMessage::ToSinkAlso(absl::LogSink* sink) {
352   ABSL_INTERNAL_CHECK(sink, "null LogSink*");
353   data_->extra_sinks.push_back(sink);
354   return *this;
355 }
356 
ToSinkOnly(absl::LogSink * sink)357 LogMessage& LogMessage::ToSinkOnly(absl::LogSink* sink) {
358   ABSL_INTERNAL_CHECK(sink, "null LogSink*");
359   data_->extra_sinks.clear();
360   data_->extra_sinks.push_back(sink);
361   data_->extra_sinks_only = true;
362   return *this;
363 }
364 
365 #ifdef __ELF__
366 extern "C" void __gcov_dump() ABSL_ATTRIBUTE_WEAK;
367 extern "C" void __gcov_flush() ABSL_ATTRIBUTE_WEAK;
368 #endif
369 
FailWithoutStackTrace()370 void LogMessage::FailWithoutStackTrace() {
371   // Now suppress repeated trace logging:
372   log_internal::SetSuppressSigabortTrace(true);
373 #if defined _DEBUG && defined COMPILER_MSVC
374   // When debugging on windows, avoid the obnoxious dialog.
375   __debugbreak();
376 #endif
377 
378 #ifdef __ELF__
379   // For b/8737634, flush coverage if we are in coverage mode.
380   if (&__gcov_dump != nullptr) {
381     __gcov_dump();
382   } else if (&__gcov_flush != nullptr) {
383     __gcov_flush();
384   }
385 #endif
386 
387   abort();
388 }
389 
FailQuietly()390 void LogMessage::FailQuietly() {
391   // _exit. Calling abort() would trigger all sorts of death signal handlers
392   // and a detailed stack trace. Calling exit() would trigger the onexit
393   // handlers, including the heap-leak checker, which is guaranteed to fail in
394   // this case: we probably just new'ed the std::string that we logged.
395   // Anyway, if you're calling Fail or FailQuietly, you're trying to bail out
396   // of the program quickly, and it doesn't make much sense for FailQuietly to
397   // offer different guarantees about exit behavior than Fail does. (And as a
398   // consequence for QCHECK and CHECK to offer different exit behaviors)
399   _exit(1);
400 }
401 
operator <<(const std::string & v)402 LogMessage& LogMessage::operator<<(const std::string& v) {
403   CopyToEncodedBuffer<StringType::kNotLiteral>(v);
404   return *this;
405 }
406 
operator <<(absl::string_view v)407 LogMessage& LogMessage::operator<<(absl::string_view v) {
408   CopyToEncodedBuffer<StringType::kNotLiteral>(v);
409   return *this;
410 }
operator <<(std::ostream & (* m)(std::ostream & os))411 LogMessage& LogMessage::operator<<(std::ostream& (*m)(std::ostream& os)) {
412   OstreamView view(*data_);
413   data_->manipulated << m;
414   return *this;
415 }
operator <<(std::ios_base & (* m)(std::ios_base & os))416 LogMessage& LogMessage::operator<<(std::ios_base& (*m)(std::ios_base& os)) {
417   OstreamView view(*data_);
418   data_->manipulated << m;
419   return *this;
420 }
421 template LogMessage& LogMessage::operator<<(const char& v);
422 template LogMessage& LogMessage::operator<<(const signed char& v);
423 template LogMessage& LogMessage::operator<<(const unsigned char& v);
424 template LogMessage& LogMessage::operator<<(const short& v);           // NOLINT
425 template LogMessage& LogMessage::operator<<(const unsigned short& v);  // NOLINT
426 template LogMessage& LogMessage::operator<<(const int& v);
427 template LogMessage& LogMessage::operator<<(const unsigned int& v);
428 template LogMessage& LogMessage::operator<<(const long& v);           // NOLINT
429 template LogMessage& LogMessage::operator<<(const unsigned long& v);  // NOLINT
430 template LogMessage& LogMessage::operator<<(const long long& v);      // NOLINT
431 template LogMessage& LogMessage::operator<<(
432     const unsigned long long& v);  // NOLINT
433 template LogMessage& LogMessage::operator<<(void* const& v);
434 template LogMessage& LogMessage::operator<<(const void* const& v);
435 template LogMessage& LogMessage::operator<<(const float& v);
436 template LogMessage& LogMessage::operator<<(const double& v);
437 template LogMessage& LogMessage::operator<<(const bool& v);
438 
Flush()439 void LogMessage::Flush() {
440   if (data_->entry.log_severity() < absl::MinLogLevel()) return;
441 
442   if (data_->is_perror) {
443     InternalStream() << ": " << absl::base_internal::StrError(errno_saver_())
444                      << " [" << errno_saver_() << "]";
445   }
446 
447   // Have we already seen a fatal message?
448   ABSL_CONST_INIT static std::atomic<bool> seen_fatal(false);
449   if (data_->entry.log_severity() == absl::LogSeverity::kFatal &&
450       absl::log_internal::ExitOnDFatal()) {
451     // Exactly one LOG(FATAL) message is responsible for aborting the process,
452     // even if multiple threads LOG(FATAL) concurrently.
453     bool expected_seen_fatal = false;
454     if (seen_fatal.compare_exchange_strong(expected_seen_fatal, true,
455                                            std::memory_order_relaxed)) {
456       data_->first_fatal = true;
457     }
458   }
459 
460   data_->FinalizeEncodingAndFormat();
461   data_->entry.encoding_ =
462       absl::string_view(data_->encoded_buf.data(),
463                         static_cast<size_t>(data_->encoded_remaining().data() -
464                                             data_->encoded_buf.data()));
465   SendToLog();
466 }
467 
SetFailQuietly()468 void LogMessage::SetFailQuietly() { data_->fail_quietly = true; }
469 
OstreamView(LogMessageData & message_data)470 LogMessage::OstreamView::OstreamView(LogMessageData& message_data)
471     : data_(message_data), encoded_remaining_copy_(data_.encoded_remaining()) {
472   // This constructor sets the `streambuf` up so that streaming into an attached
473   // ostream encodes string data in-place.  To do that, we write appropriate
474   // headers into the buffer using a copy of the buffer view so that we can
475   // decide not to keep them later if nothing is ever streamed in.  We don't
476   // know how much data we'll get, but we can use the size of the remaining
477   // buffer as an upper bound and fill in the right size once we know it.
478   message_start_ =
479       EncodeMessageStart(EventTag::kValue, encoded_remaining_copy_.size(),
480                          &encoded_remaining_copy_);
481   string_start_ =
482       EncodeMessageStart(ValueTag::kString, encoded_remaining_copy_.size(),
483                          &encoded_remaining_copy_);
484   setp(encoded_remaining_copy_.data(),
485        encoded_remaining_copy_.data() + encoded_remaining_copy_.size());
486   data_.manipulated.rdbuf(this);
487 }
488 
~OstreamView()489 LogMessage::OstreamView::~OstreamView() {
490   data_.manipulated.rdbuf(nullptr);
491   if (!string_start_.data()) {
492     // The second field header didn't fit.  Whether the first one did or not, we
493     // shouldn't commit `encoded_remaining_copy_`, and we also need to zero the
494     // size of `data_->encoded_remaining()` so that no more data are encoded.
495     data_.encoded_remaining().remove_suffix(data_.encoded_remaining().size());
496     return;
497   }
498   const absl::Span<const char> contents(pbase(),
499                                         static_cast<size_t>(pptr() - pbase()));
500   if (contents.empty()) return;
501   encoded_remaining_copy_.remove_prefix(contents.size());
502   EncodeMessageLength(string_start_, &encoded_remaining_copy_);
503   EncodeMessageLength(message_start_, &encoded_remaining_copy_);
504   data_.encoded_remaining() = encoded_remaining_copy_;
505 }
506 
stream()507 std::ostream& LogMessage::OstreamView::stream() { return data_.manipulated; }
508 
IsFatal() const509 bool LogMessage::IsFatal() const {
510   return data_->entry.log_severity() == absl::LogSeverity::kFatal &&
511          absl::log_internal::ExitOnDFatal();
512 }
513 
PrepareToDie()514 void LogMessage::PrepareToDie() {
515   // If we log a FATAL message, flush all the log destinations, then toss
516   // a signal for others to catch. We leave the logs in a state that
517   // someone else can use them (as long as they flush afterwards)
518   if (data_->first_fatal) {
519     // Notify observers about the upcoming fatal error.
520     ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)(data_->entry);
521   }
522 
523   if (!data_->fail_quietly) {
524     // Log the message first before we start collecting stack trace.
525     log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
526                              data_->extra_sinks_only);
527 
528     // `DumpStackTrace` generates an empty string under MSVC.
529     // Adding the constant prefix here simplifies testing.
530     data_->entry.stacktrace_ = "*** Check failure stack trace: ***\n";
531     debugging_internal::DumpStackTrace(
532         0, log_internal::MaxFramesInLogStackTrace(),
533         log_internal::ShouldSymbolizeLogStackTrace(), WriteToString,
534         &data_->entry.stacktrace_);
535   }
536 }
537 
Die()538 void LogMessage::Die() {
539   absl::FlushLogSinks();
540 
541   if (data_->fail_quietly) {
542     FailQuietly();
543   } else {
544     FailWithoutStackTrace();
545   }
546 }
547 
SendToLog()548 void LogMessage::SendToLog() {
549   if (IsFatal()) PrepareToDie();
550   // Also log to all registered sinks, even if OnlyLogToStderr() is set.
551   log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
552                            data_->extra_sinks_only);
553   if (IsFatal()) Die();
554 }
555 
LogBacktraceIfNeeded()556 void LogMessage::LogBacktraceIfNeeded() {
557   if (!absl::log_internal::IsInitialized()) return;
558 
559   if (!absl::log_internal::ShouldLogBacktraceAt(data_->entry.source_basename(),
560                                                 data_->entry.source_line()))
561     return;
562   OstreamView view(*data_);
563   view.stream() << " (stacktrace:\n";
564   debugging_internal::DumpStackTrace(
565       1, log_internal::MaxFramesInLogStackTrace(),
566       log_internal::ShouldSymbolizeLogStackTrace(), WriteToStream,
567       &view.stream());
568   view.stream() << ") ";
569 }
570 
571 // Encodes into `data_->encoded_remaining()` a partial `logging.proto.Event`
572 // containing the specified string data using a `Value` field appropriate to
573 // `str_type`.  Truncates `str` if necessary, but emits nothing and marks the
574 // buffer full if  even the field headers do not fit.
575 template <LogMessage::StringType str_type>
CopyToEncodedBuffer(absl::string_view str)576 void LogMessage::CopyToEncodedBuffer(absl::string_view str) {
577   auto encoded_remaining_copy = data_->encoded_remaining();
578   auto start = EncodeMessageStart(
579       EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + str.size(),
580       &encoded_remaining_copy);
581   // If the `logging.proto.Event.value` field header did not fit,
582   // `EncodeMessageStart` will have zeroed `encoded_remaining_copy`'s size and
583   // `EncodeStringTruncate` will fail too.
584   if (EncodeStringTruncate(str_type == StringType::kLiteral
585                                ? ValueTag::kStringLiteral
586                                : ValueTag::kString,
587                            str, &encoded_remaining_copy)) {
588     // The string may have been truncated, but the field header fit.
589     EncodeMessageLength(start, &encoded_remaining_copy);
590     data_->encoded_remaining() = encoded_remaining_copy;
591   } else {
592     // The field header(s) did not fit; zero `encoded_remaining()` so we don't
593     // write anything else later.
594     data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());
595   }
596 }
597 template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
598     absl::string_view str);
599 template void LogMessage::CopyToEncodedBuffer<
600     LogMessage::StringType::kNotLiteral>(absl::string_view str);
601 template <LogMessage::StringType str_type>
CopyToEncodedBuffer(char ch,size_t num)602 void LogMessage::CopyToEncodedBuffer(char ch, size_t num) {
603   auto encoded_remaining_copy = data_->encoded_remaining();
604   auto value_start = EncodeMessageStart(
605       EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + num,
606       &encoded_remaining_copy);
607   auto str_start = EncodeMessageStart(str_type == StringType::kLiteral
608                                           ? ValueTag::kStringLiteral
609                                           : ValueTag::kString,
610                                       num, &encoded_remaining_copy);
611   if (str_start.data()) {
612     // The field headers fit.
613     log_internal::AppendTruncated(ch, num, encoded_remaining_copy);
614     EncodeMessageLength(str_start, &encoded_remaining_copy);
615     EncodeMessageLength(value_start, &encoded_remaining_copy);
616     data_->encoded_remaining() = encoded_remaining_copy;
617   } else {
618     // The field header(s) did not fit; zero `encoded_remaining()` so we don't
619     // write anything else later.
620     data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());
621   }
622 }
623 template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
624     char ch, size_t num);
625 template void LogMessage::CopyToEncodedBuffer<
626     LogMessage::StringType::kNotLiteral>(char ch, size_t num);
627 
628 // We intentionally don't return from these destructors. Disable MSVC's warning
629 // about the destructor never returning as we do so intentionally here.
630 #if defined(_MSC_VER) && !defined(__clang__)
631 #pragma warning(push)
632 #pragma warning(disable : 4722)
633 #endif
634 
LogMessageFatal(const char * file,int line)635 LogMessageFatal::LogMessageFatal(const char* file, int line)
636     : LogMessage(file, line, absl::LogSeverity::kFatal) {}
637 
LogMessageFatal(const char * file,int line,absl::string_view failure_msg)638 LogMessageFatal::LogMessageFatal(const char* file, int line,
639                                  absl::string_view failure_msg)
640     : LogMessage(file, line, absl::LogSeverity::kFatal) {
641   *this << "Check failed: " << failure_msg << " ";
642 }
643 
~LogMessageFatal()644 LogMessageFatal::~LogMessageFatal() {
645   Flush();
646   FailWithoutStackTrace();
647 }
648 
LogMessageDebugFatal(const char * file,int line)649 LogMessageDebugFatal::LogMessageDebugFatal(const char* file, int line)
650     : LogMessage(file, line, absl::LogSeverity::kFatal) {}
651 
~LogMessageDebugFatal()652 LogMessageDebugFatal::~LogMessageDebugFatal() {
653   Flush();
654   FailWithoutStackTrace();
655 }
656 
LogMessageQuietlyDebugFatal(const char * file,int line)657 LogMessageQuietlyDebugFatal::LogMessageQuietlyDebugFatal(const char* file,
658                                                          int line)
659     : LogMessage(file, line, absl::LogSeverity::kFatal) {
660   SetFailQuietly();
661 }
662 
~LogMessageQuietlyDebugFatal()663 LogMessageQuietlyDebugFatal::~LogMessageQuietlyDebugFatal() {
664   Flush();
665   FailQuietly();
666 }
667 
LogMessageQuietlyFatal(const char * file,int line)668 LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line)
669     : LogMessage(file, line, absl::LogSeverity::kFatal) {
670   SetFailQuietly();
671 }
672 
LogMessageQuietlyFatal(const char * file,int line,absl::string_view failure_msg)673 LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line,
674                                                absl::string_view failure_msg)
675     : LogMessageQuietlyFatal(file, line) {
676     *this << "Check failed: " << failure_msg << " ";
677 }
678 
~LogMessageQuietlyFatal()679 LogMessageQuietlyFatal::~LogMessageQuietlyFatal() {
680   Flush();
681   FailQuietly();
682 }
683 #if defined(_MSC_VER) && !defined(__clang__)
684 #pragma warning(pop)
685 #endif
686 
687 }  // namespace log_internal
688 
689 ABSL_NAMESPACE_END
690 }  // namespace absl
691