Coverage Report

Created: 2025-10-10 07:13

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