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