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