Coverage Report

Created: 2023-09-25 06:27

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