Coverage Report

Created: 2025-07-11 06:37

/src/abseil-cpp/absl/log/internal/log_message.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2022 The Abseil Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
//
15
// -----------------------------------------------------------------------------
16
// File: log/internal/log_message.h
17
// -----------------------------------------------------------------------------
18
//
19
// This file declares `class absl::log_internal::LogMessage`. This class more or
20
// less represents a particular log message. LOG/CHECK macros create a temporary
21
// instance of `LogMessage` and then stream values to it.  At the end of the
22
// LOG/CHECK statement, the LogMessage is voidified by operator&&, and `Flush()`
23
// directs the message to the registered log sinks.  Heap-allocation of
24
// `LogMessage` is unsupported.  Construction outside of a `LOG` macro is
25
// unsupported.
26
27
#ifndef ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
28
#define ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
29
30
#include <wchar.h>
31
32
#include <cstddef>
33
#include <ios>
34
#include <memory>
35
#include <ostream>
36
#include <streambuf>
37
#include <string>
38
#include <string_view>
39
#include <type_traits>
40
41
#include "absl/base/attributes.h"
42
#include "absl/base/config.h"
43
#include "absl/base/internal/errno_saver.h"
44
#include "absl/base/log_severity.h"
45
#include "absl/base/nullability.h"
46
#include "absl/log/internal/nullguard.h"
47
#include "absl/log/internal/structured_proto.h"
48
#include "absl/log/log_entry.h"
49
#include "absl/log/log_sink.h"
50
#include "absl/strings/has_absl_stringify.h"
51
#include "absl/strings/string_view.h"
52
#include "absl/time/time.h"
53
54
namespace absl {
55
ABSL_NAMESPACE_BEGIN
56
namespace log_internal {
57
constexpr int kLogMessageBufferSize = 15000;
58
59
enum class StructuredStringType;
60
61
class LogMessage {
62
 public:
63
  struct InfoTag {};
64
  struct WarningTag {};
65
  struct ErrorTag {};
66
67
  // Used for `LOG`.
68
  LogMessage(const char* absl_nonnull file, int line,
69
             absl::LogSeverity severity) ABSL_ATTRIBUTE_COLD;
70
  // These constructors are slightly smaller/faster to call; the severity is
71
  // curried into the function pointer.
72
  LogMessage(const char* absl_nonnull file, int line,
73
             InfoTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
74
  LogMessage(const char* absl_nonnull file, int line,
75
             WarningTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
76
  LogMessage(const char* absl_nonnull file, int line,
77
             ErrorTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
78
  LogMessage(const LogMessage&) = delete;
79
  LogMessage& operator=(const LogMessage&) = delete;
80
  ~LogMessage() ABSL_ATTRIBUTE_COLD;
81
82
  // Overrides the location inferred from the callsite.  The string pointed to
83
  // by `file` must be valid until the end of the statement.
84
  LogMessage& AtLocation(absl::string_view file, int line);
85
  // Omits the prefix from this line.  The prefix includes metadata about the
86
  // logged data such as source code location and timestamp.
87
  LogMessage& NoPrefix();
88
  // Sets the verbosity field of the logged message as if it was logged by
89
  // `VLOG(verbose_level)`.  Unlike `VLOG`, this method does not affect
90
  // evaluation of the statement when the specified `verbose_level` has been
91
  // disabled.  The only effect is on `absl::LogSink` implementations which
92
  // make use of the `absl::LogSink::verbosity()` value.  The value
93
  // `absl::LogEntry::kNoVerbosityLevel` can be specified to mark the message
94
  // not verbose.
95
  LogMessage& WithVerbosity(int verbose_level);
96
  // Uses the specified timestamp instead of one collected in the constructor.
97
  LogMessage& WithTimestamp(absl::Time timestamp);
98
  // Uses the specified thread ID instead of one collected in the constructor.
99
  LogMessage& WithThreadID(absl::LogEntry::tid_t tid);
100
  // Copies all metadata (but no data) from the specified `absl::LogEntry`.
101
  LogMessage& WithMetadataFrom(const absl::LogEntry& entry);
102
  // Appends to the logged message a colon, a space, a textual description of
103
  // the current value of `errno` (as by strerror(3)), and the numerical value
104
  // of `errno`.
105
  LogMessage& WithPerror();
106
  // Sends this message to `*sink` in addition to whatever other sinks it would
107
  // otherwise have been sent to.
108
  LogMessage& ToSinkAlso(absl::LogSink* absl_nonnull sink);
109
  // Sends this message to `*sink` and no others.
110
  LogMessage& ToSinkOnly(absl::LogSink* absl_nonnull sink);
111
112
  // Don't call this method from outside this library.
113
0
  LogMessage& InternalStream() { return *this; }
114
115
  // By-value overloads for small, common types let us overlook common failures
116
  // to define globals and static data members (i.e. in a .cc file).
117
  // NOLINTBEGIN(runtime/int)
118
  // NOLINTBEGIN(google-runtime-int)
119
  // clang-format off:  The CUDA toolchain cannot handle these <<<'s
120
0
  LogMessage& operator<<(char v) { return operator<< <char>(v); }
121
0
  LogMessage& operator<<(signed char v) { return operator<< <signed char>(v); }
122
0
  LogMessage& operator<<(unsigned char v) {
123
0
    return operator<< <unsigned char>(v);
124
0
  }
125
0
  LogMessage& operator<<(signed short v) {
126
0
    return operator<< <signed short>(v);
127
0
  }
128
0
  LogMessage& operator<<(signed int v) { return operator<< <signed int>(v); }
129
0
  LogMessage& operator<<(signed long v) {
130
0
    return operator<< <signed long>(v);
131
0
  }
132
0
  LogMessage& operator<<(signed long long v) {
133
0
    return operator<< <signed long long>(v);
134
0
  }
135
0
  LogMessage& operator<<(unsigned short v) {
136
0
    return operator<< <unsigned short>(v);
137
0
  }
138
0
  LogMessage& operator<<(unsigned int v) {
139
0
    return operator<< <unsigned int>(v);
140
0
  }
141
0
  LogMessage& operator<<(unsigned long v) {
142
0
    return operator<< <unsigned long>(v);
143
0
  }
144
0
  LogMessage& operator<<(unsigned long long v) {
145
0
    return operator<< <unsigned long long>(v);
146
0
  }
147
0
  LogMessage& operator<<(void* absl_nullable  v) {
148
0
    return operator<< <void*>(v);
149
0
  }
150
0
  LogMessage& operator<<(const void* absl_nullable  v) {
151
0
    return operator<< <const void*>(v);
152
0
  }
153
0
  LogMessage& operator<<(float v) { return operator<< <float>(v); }
154
0
  LogMessage& operator<<(double v) { return operator<< <double>(v); }
155
0
  LogMessage& operator<<(bool v) { return operator<< <bool>(v); }
156
  // clang-format on
157
  // NOLINTEND(google-runtime-int)
158
  // NOLINTEND(runtime/int)
159
160
  // These overloads are more efficient since no `ostream` is involved.
161
  LogMessage& operator<<(const std::string& v);
162
  LogMessage& operator<<(absl::string_view v);
163
164
  // Wide string overloads (since std::ostream does not provide them).
165
  LogMessage& operator<<(const std::wstring& v);
166
  LogMessage& operator<<(std::wstring_view v);
167
  // `const wchar_t*` is handled by `operator<< <const wchar_t*>`.
168
  LogMessage& operator<<(wchar_t* absl_nullable v);
169
  LogMessage& operator<<(wchar_t v);
170
171
  // Handle stream manipulators e.g. std::endl.
172
  LogMessage& operator<<(std::ostream& (*absl_nonnull m)(std::ostream& os));
173
  LogMessage& operator<<(std::ios_base& (*absl_nonnull m)(std::ios_base& os));
174
175
  // Literal strings.  This allows us to record C string literals as literals in
176
  // the logging.proto.Value.
177
  //
178
  // Allow this overload to be inlined to prevent generating instantiations of
179
  // this template for every value of `SIZE` encountered in each source code
180
  // file. That significantly increases linker input sizes. Inlining is cheap
181
  // because the argument to this overload is almost always a string literal so
182
  // the call to `strlen` can be replaced at compile time. The overloads for
183
  // `char[]`/`wchar_t[]` below should not be inlined. The compiler typically
184
  // does not have the string at compile time and cannot replace the call to
185
  // `strlen` so inlining it increases the binary size. See the discussion on
186
  // cl/107527369.
187
  template <int SIZE>
188
  LogMessage& operator<<(const char (&buf)[SIZE]);
189
  template <int SIZE>
190
  LogMessage& operator<<(const wchar_t (&buf)[SIZE]);
191
192
  // This prevents non-const `char[]` arrays from looking like literals.
193
  template <int SIZE>
194
  LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE;
195
  // `wchar_t[SIZE]` is handled by `operator<< <const wchar_t*>`.
196
197
  // Types that support `AbslStringify()` are serialized that way.
198
  // Types that don't support `AbslStringify()` but do support streaming into a
199
  // `std::ostream&` are serialized that way.
200
  template <typename T>
201
  LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE;
202
203
  // Dispatches the completed `absl::LogEntry` to applicable `absl::LogSink`s.
204
  void Flush();
205
206
  // Note: We explicitly do not support `operator<<` for non-const references
207
  // because it breaks logging of non-integer bitfield types (i.e., enums).
208
209
 protected:
210
  // Call `abort()` or similar to perform `LOG(FATAL)` crash.  It is assumed
211
  // that the caller has already generated and written the trace as appropriate.
212
  [[noreturn]] static void FailWithoutStackTrace();
213
214
  // Similar to `FailWithoutStackTrace()`, but without `abort()`.  Terminates
215
  // the process with an error exit code.
216
  [[noreturn]] static void FailQuietly();
217
218
  // After this is called, failures are done as quiet as possible for this log
219
  // message.
220
  void SetFailQuietly();
221
222
 private:
223
  struct LogMessageData;  // Opaque type containing message state
224
  friend class AsLiteralImpl;
225
  friend class StringifySink;
226
  template <StructuredStringType str_type>
227
  friend class AsStructuredStringTypeImpl;
228
  template <typename T>
229
  friend class AsStructuredValueImpl;
230
231
  // This streambuf writes directly into the structured logging buffer so that
232
  // arbitrary types can be encoded as string data (using
233
  // `operator<<(std::ostream &, ...)` without any extra allocation or copying.
234
  // Space is reserved before the data to store the length field, which is
235
  // filled in by `~OstreamView`.
236
  class OstreamView final : public std::streambuf {
237
   public:
238
    explicit OstreamView(LogMessageData& message_data);
239
    ~OstreamView() override;
240
    OstreamView(const OstreamView&) = delete;
241
    OstreamView& operator=(const OstreamView&) = delete;
242
    std::ostream& stream();
243
244
   private:
245
    LogMessageData& data_;
246
    absl::Span<char> encoded_remaining_copy_;
247
    absl::Span<char> message_start_;
248
    absl::Span<char> string_start_;
249
  };
250
251
  enum class StringType {
252
    kLiteral,
253
    kNotLiteral,
254
  };
255
  template <StringType str_type>
256
  void CopyToEncodedBuffer(absl::string_view str) ABSL_ATTRIBUTE_NOINLINE;
257
  template <StringType str_type>
258
  void CopyToEncodedBuffer(char ch, size_t num) ABSL_ATTRIBUTE_NOINLINE;
259
  template <StringType str_type>
260
  void CopyToEncodedBuffer(std::wstring_view str) ABSL_ATTRIBUTE_NOINLINE;
261
262
  // Copies `field` to the encoded buffer, then appends `str` after it
263
  // (truncating `str` if necessary to fit).
264
  template <StringType str_type>
265
  void CopyToEncodedBufferWithStructuredProtoField(StructuredProtoField field,
266
                                                   absl::string_view str)
267
      ABSL_ATTRIBUTE_NOINLINE;
268
269
  // Returns `true` if the message is fatal or enabled debug-fatal.
270
  bool IsFatal() const;
271
272
  // Records some tombstone-type data in anticipation of `Die`.
273
  void PrepareToDie();
274
  void Die();
275
276
  void SendToLog();
277
278
  // Checks `FLAGS_log_backtrace_at` and appends a backtrace if appropriate.
279
  void LogBacktraceIfNeeded();
280
281
  // This should be the first data member so that its initializer captures errno
282
  // before any other initializers alter it (e.g. with calls to new) and so that
283
  // no other destructors run afterward an alter it (e.g. with calls to delete).
284
  absl::base_internal::ErrnoSaver errno_saver_;
285
286
  // We keep the data in a separate struct so that each instance of `LogMessage`
287
  // uses less stack space.
288
  absl_nonnull std::unique_ptr<LogMessageData> data_;
289
};
290
291
// Explicitly specializes the generic operator<< for `const wchar_t*`
292
// arguments.
293
//
294
// This method is used instead of a non-template `const wchar_t*` overload,
295
// as the latter was found to take precedence over the array template
296
// (`operator<<(const wchar_t(&)[SIZE])`) when handling string literals.
297
// This specialization ensures the array template now correctly processes
298
// literals.
299
template <>
300
LogMessage& LogMessage::operator<< <const wchar_t*>(
301
    const wchar_t* absl_nullable const& v);
302
303
0
inline LogMessage& LogMessage::operator<<(wchar_t* absl_nullable v) {
304
0
  return operator<<(const_cast<const wchar_t*>(v));
305
0
}
306
307
// Helper class so that `AbslStringify()` can modify the LogMessage.
308
class StringifySink final {
309
 public:
310
0
  explicit StringifySink(LogMessage& message) : message_(message) {}
311
312
0
  void Append(size_t count, char ch) {
313
0
    message_.CopyToEncodedBuffer<LogMessage::StringType::kNotLiteral>(ch,
314
0
                                                                      count);
315
0
  }
316
317
0
  void Append(absl::string_view v) {
318
0
    message_.CopyToEncodedBuffer<LogMessage::StringType::kNotLiteral>(v);
319
0
  }
320
321
  // For types that implement `AbslStringify` using `absl::Format()`.
322
  friend void AbslFormatFlush(StringifySink* absl_nonnull sink,
323
0
                              absl::string_view v) {
324
0
    sink->Append(v);
325
0
  }
326
327
 private:
328
  LogMessage& message_;
329
};
330
331
// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
332
template <typename T>
333
0
LogMessage& LogMessage::operator<<(const T& v) {
334
  if constexpr (absl::HasAbslStringify<T>::value) {
335
    StringifySink sink(*this);
336
    // Replace with public API.
337
    AbslStringify(sink, v);
338
0
  } else {
339
0
    OstreamView view(*data_);
340
0
    view.stream() << log_internal::NullGuard<T>().Guard(v);
341
0
  }
342
0
  return *this;
343
0
}
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <char>(char const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <signed char>(signed char const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <unsigned char>(unsigned char const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <short>(short const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <unsigned short>(unsigned short const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <int>(int const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <unsigned int>(unsigned int const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <long>(long const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <unsigned long>(unsigned long const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <long long>(long long const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <unsigned long long>(unsigned long long const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <void*>(void* const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <void const*>(void const* const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <float>(float const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <double>(double const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <bool>(bool const&)
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <char const*>(char const* const&)
344
345
template <int SIZE>
346
0
LogMessage& LogMessage::operator<<(const char (&buf)[SIZE]) {
347
0
  CopyToEncodedBuffer<StringType::kLiteral>(buf);
348
0
  return *this;
349
0
}
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <3>(char const (&) [3])
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <2>(char const (&) [2])
Unexecuted instantiation: absl::log_internal::LogMessage& absl::log_internal::LogMessage::operator<< <15>(char const (&) [15])
350
351
template <int SIZE>
352
LogMessage& LogMessage::operator<<(const wchar_t (&buf)[SIZE]) {
353
  CopyToEncodedBuffer<StringType::kLiteral>(buf);
354
  return *this;
355
}
356
357
// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
358
template <int SIZE>
359
LogMessage& LogMessage::operator<<(char (&buf)[SIZE]) {
360
  CopyToEncodedBuffer<StringType::kNotLiteral>(buf);
361
  return *this;
362
}
363
// We instantiate these specializations in the library's TU to save space in
364
// other TUs.  Since the template is marked `ABSL_ATTRIBUTE_NOINLINE` we will be
365
// emitting a function call either way.
366
// NOLINTBEGIN(runtime/int)
367
// NOLINTBEGIN(google-runtime-int)
368
extern template LogMessage& LogMessage::operator<<(const char& v);
369
extern template LogMessage& LogMessage::operator<<(const signed char& v);
370
extern template LogMessage& LogMessage::operator<<(const unsigned char& v);
371
extern template LogMessage& LogMessage::operator<<(const short& v);
372
extern template LogMessage& LogMessage::operator<<(const unsigned short& v);
373
extern template LogMessage& LogMessage::operator<<(const int& v);
374
extern template LogMessage& LogMessage::operator<<(const unsigned int& v);
375
extern template LogMessage& LogMessage::operator<<(const long& v);
376
extern template LogMessage& LogMessage::operator<<(const unsigned long& v);
377
extern template LogMessage& LogMessage::operator<<(const long long& v);
378
extern template LogMessage& LogMessage::operator<<(const unsigned long long& v);
379
extern template LogMessage& LogMessage::operator<<(
380
    void* absl_nullable const& v);
381
extern template LogMessage& LogMessage::operator<<(
382
    const void* absl_nullable const& v);
383
extern template LogMessage& LogMessage::operator<<(const float& v);
384
extern template LogMessage& LogMessage::operator<<(const double& v);
385
extern template LogMessage& LogMessage::operator<<(const bool& v);
386
// NOLINTEND(google-runtime-int)
387
// NOLINTEND(runtime/int)
388
389
extern template void LogMessage::CopyToEncodedBuffer<
390
    LogMessage::StringType::kLiteral>(absl::string_view str);
391
extern template void LogMessage::CopyToEncodedBuffer<
392
    LogMessage::StringType::kNotLiteral>(absl::string_view str);
393
extern template void
394
LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(char ch,
395
                                                                  size_t num);
396
extern template void LogMessage::CopyToEncodedBuffer<
397
    LogMessage::StringType::kNotLiteral>(char ch, size_t num);
398
extern template void LogMessage::CopyToEncodedBuffer<
399
    LogMessage::StringType::kLiteral>(std::wstring_view str);
400
extern template void LogMessage::CopyToEncodedBuffer<
401
    LogMessage::StringType::kNotLiteral>(std::wstring_view str);
402
403
// `LogMessageFatal` ensures the process will exit in failure after logging this
404
// message.
405
class LogMessageFatal final : public LogMessage {
406
 public:
407
  LogMessageFatal(const char* absl_nonnull file, int line) ABSL_ATTRIBUTE_COLD;
408
  LogMessageFatal(const char* absl_nonnull file, int line,
409
                  const char* absl_nonnull failure_msg) ABSL_ATTRIBUTE_COLD;
410
  [[noreturn]] ~LogMessageFatal();
411
};
412
413
// `LogMessageDebugFatal` ensures the process will exit in failure after logging
414
// this message. It matches LogMessageFatal but is not [[noreturn]] as it's used
415
// for DLOG(FATAL) variants.
416
class LogMessageDebugFatal final : public LogMessage {
417
 public:
418
  LogMessageDebugFatal(const char* absl_nonnull file,
419
                       int line) ABSL_ATTRIBUTE_COLD;
420
  ~LogMessageDebugFatal();
421
};
422
423
class LogMessageQuietlyDebugFatal final : public LogMessage {
424
 public:
425
  // DLOG(QFATAL) calls this instead of LogMessageQuietlyFatal to make sure the
426
  // destructor is not [[noreturn]] even if this is always FATAL as this is only
427
  // invoked when DLOG() is enabled.
428
  LogMessageQuietlyDebugFatal(const char* absl_nonnull file,
429
                              int line) ABSL_ATTRIBUTE_COLD;
430
  ~LogMessageQuietlyDebugFatal();
431
};
432
433
// Used for LOG(QFATAL) to make sure it's properly understood as [[noreturn]].
434
class LogMessageQuietlyFatal final : public LogMessage {
435
 public:
436
  LogMessageQuietlyFatal(const char* absl_nonnull file,
437
                         int line) ABSL_ATTRIBUTE_COLD;
438
  LogMessageQuietlyFatal(const char* absl_nonnull file, int line,
439
                         const char* absl_nonnull failure_msg)
440
      ABSL_ATTRIBUTE_COLD;
441
  [[noreturn]] ~LogMessageQuietlyFatal();
442
};
443
444
}  // namespace log_internal
445
ABSL_NAMESPACE_END
446
}  // namespace absl
447
448
extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
449
    AbslInternalOnFatalLogMessage)(const absl::LogEntry&);
450
451
#endif  // ABSL_LOG_INTERNAL_LOG_MESSAGE_H_