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