• 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/config.h"
41 #include "absl/log/internal/nullguard.h"
42 #include "absl/log/log_entry.h"
43 #include "absl/log/log_sink.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 
51 constexpr int kLogMessageBufferSize = 15000;
52 
53 class LogMessage {
54  public:
55   // Used for `LOG`.
56   LogMessage(const char* file, int line,
57              absl::LogSeverity severity) ABSL_ATTRIBUTE_COLD;
58   LogMessage(const LogMessage&) = delete;
59   LogMessage& operator=(const LogMessage&) = delete;
60   ~LogMessage() ABSL_ATTRIBUTE_COLD;
61 
62   // Overrides the location inferred from the callsite.  The string pointed to
63   // by `file` must be valid until the end of the statement.
64   LogMessage& AtLocation(absl::string_view file, int line);
65   // Omits the prefix from this line.  The prefix includes metadata about the
66   // logged data such as source code location and timestamp.
67   LogMessage& NoPrefix();
68   // Sets the verbosity field of the logged message as if it was logged by
69   // `VLOG(verbose_level)`.  Unlike `VLOG`, this method does not affect
70   // evaluation of the statement when the specified `verbose_level` has been
71   // disabled.  The only effect is on `absl::LogSink` implementations which
72   // make use of the `absl::LogSink::verbosity()` value.  The value
73   // `absl::LogEntry::kNoVerbosityLevel` can be specified to mark the message
74   // not verbose.
75   LogMessage& WithVerbosity(int verbose_level);
76   // Uses the specified timestamp instead of one collected in the constructor.
77   LogMessage& WithTimestamp(absl::Time timestamp);
78   // Uses the specified thread ID instead of one collected in the constructor.
79   LogMessage& WithThreadID(absl::LogEntry::tid_t tid);
80   // Copies all metadata (but no data) from the specified `absl::LogEntry`.
81   LogMessage& WithMetadataFrom(const absl::LogEntry& entry);
82   // Appends to the logged message a colon, a space, a textual description of
83   // the current value of `errno` (as by strerror(3)), and the numerical value
84   // of `errno`.
85   LogMessage& WithPerror();
86   // Sends this message to `*sink` in addition to whatever other sinks it would
87   // otherwise have been sent to.  `sink` must not be null.
88   LogMessage& ToSinkAlso(absl::LogSink* sink);
89   // Sends this message to `*sink` and no others.  `sink` must not be null.
90   LogMessage& ToSinkOnly(absl::LogSink* sink);
91 
92   // Don't call this method from outside this library.
InternalStream()93   LogMessage& InternalStream() { return *this; }
94 
95   // By-value overloads for small, common types let us overlook common failures
96   // to define globals and static data members (i.e. in a .cc file).
97   // clang-format off
98   // The CUDA toolchain cannot handle these <<<'s:
99   LogMessage& operator<<(char v) { return operator<< <char>(v); }
100   LogMessage& operator<<(signed char v) { return operator<< <signed char>(v); }
101   LogMessage& operator<<(unsigned char v) {
102     return operator<< <unsigned char>(v);
103   }
104   LogMessage& operator<<(signed short v) {  // NOLINT
105     return operator<< <signed short>(v);  // NOLINT
106   }
107   LogMessage& operator<<(signed int v) { return operator<< <signed int>(v); }
108   LogMessage& operator<<(signed long v) {  // NOLINT
109     return operator<< <signed long>(v);  // NOLINT
110   }
111   LogMessage& operator<<(signed long long v) {  // NOLINT
112     return operator<< <signed long long>(v);  // NOLINT
113   }
114   LogMessage& operator<<(unsigned short v) {  // NOLINT
115     return operator<< <unsigned short>(v);  // NOLINT
116   }
117   LogMessage& operator<<(unsigned int v) {
118     return operator<< <unsigned int>(v);
119   }
120   LogMessage& operator<<(unsigned long v) {  // NOLINT
121     return operator<< <unsigned long>(v);  // NOLINT
122   }
123   LogMessage& operator<<(unsigned long long v) {  // NOLINT
124     return operator<< <unsigned long long>(v);  // NOLINT
125   }
126   LogMessage& operator<<(void* v) { return operator<< <void*>(v); }
127   LogMessage& operator<<(const void* v) { return operator<< <const void*>(v); }
128   LogMessage& operator<<(float v) { return operator<< <float>(v); }
129   LogMessage& operator<<(double v) { return operator<< <double>(v); }
130   LogMessage& operator<<(bool v) { return operator<< <bool>(v); }
131   // clang-format on
132 
133   // Handle stream manipulators e.g. std::endl.
134   LogMessage& operator<<(std::ostream& (*m)(std::ostream& os));
135   LogMessage& operator<<(std::ios_base& (*m)(std::ios_base& os));
136 
137   // Literal strings.  This allows us to record C string literals as literals in
138   // the logging.proto.Value.
139   //
140   // Allow this overload to be inlined to prevent generating instantiations of
141   // this template for every value of `SIZE` encountered in each source code
142   // file. That significantly increases linker input sizes. Inlining is cheap
143   // because the argument to this overload is almost always a string literal so
144   // the call to `strlen` can be replaced at compile time. The overload for
145   // `char[]` below should not be inlined. The compiler typically does not have
146   // the string at compile time and cannot replace the call to `strlen` so
147   // inlining it increases the binary size. See the discussion on
148   // cl/107527369.
149   template <int SIZE>
150   LogMessage& operator<<(const char (&buf)[SIZE]);
151 
152   // This prevents non-const `char[]` arrays from looking like literals.
153   template <int SIZE>
154   LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE;
155 
156   // Default: uses `ostream` logging to convert `v` to a string.
157   template <typename T>
158   LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE;
159 
160   // Note: We explicitly do not support `operator<<` for non-const references
161   // because it breaks logging of non-integer bitfield types (i.e., enums).
162 
163  protected:
164   // Call `abort()` or similar to perform `LOG(FATAL)` crash.  It is assumed
165   // that the caller has already generated and written the trace as appropriate.
166   ABSL_ATTRIBUTE_NORETURN static void FailWithoutStackTrace();
167 
168   // Similar to `FailWithoutStackTrace()`, but without `abort()`.  Terminates
169   // the process with an error exit code.
170   ABSL_ATTRIBUTE_NORETURN static void FailQuietly();
171 
172   // Dispatches the completed `absl::LogEntry` to applicable `absl::LogSink`s.
173   // This might as well be inlined into `~LogMessage` except that
174   // `~LogMessageFatal` needs to call it early.
175   void Flush();
176 
177   // After this is called, failures are done as quiet as possible for this log
178   // message.
179   void SetFailQuietly();
180 
181  private:
182   struct LogMessageData;  // Opaque type containing message state
183 
184   // Returns `true` if the message is fatal or enabled debug-fatal.
185   bool IsFatal() const;
186 
187   // Records some tombstone-type data in anticipation of `Die`.
188   void PrepareToDie();
189   void Die();
190 
191   void SendToLog();
192 
193   // Checks `FLAGS_log_backtrace_at` and appends a backtrace if appropriate.
194   void LogBacktraceIfNeeded();
195 
196   // This should be the first data member so that its initializer captures errno
197   // before any other initializers alter it (e.g. with calls to new) and so that
198   // no other destructors run afterward an alter it (e.g. with calls to delete).
199   absl::base_internal::ErrnoSaver errno_saver_;
200 
201   // We keep the data in a separate struct so that each instance of `LogMessage`
202   // uses less stack space.
203   std::unique_ptr<LogMessageData> data_;
204 
205   std::ostream stream_;
206 };
207 
208 // Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
209 template <typename T>
210 LogMessage& LogMessage::operator<<(const T& v) {
211   stream_ << log_internal::NullGuard<T>().Guard(v);
212   return *this;
213 }
214 inline LogMessage& LogMessage::operator<<(
215     std::ostream& (*m)(std::ostream& os)) {
216   stream_ << m;
217   return *this;
218 }
219 inline LogMessage& LogMessage::operator<<(
220     std::ios_base& (*m)(std::ios_base& os)) {
221   stream_ << m;
222   return *this;
223 }
224 template <int SIZE>
225 LogMessage& LogMessage::operator<<(const char (&buf)[SIZE]) {
226   stream_ << buf;
227   return *this;
228 }
229 // Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
230 template <int SIZE>
231 LogMessage& LogMessage::operator<<(char (&buf)[SIZE]) {
232   stream_ << buf;
233   return *this;
234 }
235 // We instantiate these specializations in the library's TU to save space in
236 // other TUs.  Since the template is marked `ABSL_ATTRIBUTE_NOINLINE` we will be
237 // emitting a function call either way.
238 extern template LogMessage& LogMessage::operator<<(const char& v);
239 extern template LogMessage& LogMessage::operator<<(const signed char& v);
240 extern template LogMessage& LogMessage::operator<<(const unsigned char& v);
241 extern template LogMessage& LogMessage::operator<<(const short& v);  // NOLINT
242 extern template LogMessage& LogMessage::operator<<(
243     const unsigned short& v);  // NOLINT
244 extern template LogMessage& LogMessage::operator<<(const int& v);
245 extern template LogMessage& LogMessage::operator<<(
246     const unsigned int& v);                                         // NOLINT
247 extern template LogMessage& LogMessage::operator<<(const long& v);  // NOLINT
248 extern template LogMessage& LogMessage::operator<<(
249     const unsigned long& v);  // NOLINT
250 extern template LogMessage& LogMessage::operator<<(
251     const long long& v);  // NOLINT
252 extern template LogMessage& LogMessage::operator<<(
253     const unsigned long long& v);  // NOLINT
254 extern template LogMessage& LogMessage::operator<<(void* const& v);
255 extern template LogMessage& LogMessage::operator<<(const void* const& v);
256 extern template LogMessage& LogMessage::operator<<(const float& v);
257 extern template LogMessage& LogMessage::operator<<(const double& v);
258 extern template LogMessage& LogMessage::operator<<(const bool& v);
259 extern template LogMessage& LogMessage::operator<<(const std::string& v);
260 extern template LogMessage& LogMessage::operator<<(const absl::string_view& v);
261 
262 // `LogMessageFatal` ensures the process will exit in failure after logging this
263 // message.
264 class LogMessageFatal final : public LogMessage {
265  public:
266   LogMessageFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD;
267   LogMessageFatal(const char* file, int line,
268                   absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD;
269   ABSL_ATTRIBUTE_NORETURN ~LogMessageFatal();
270 };
271 
272 class LogMessageQuietlyFatal final : public LogMessage {
273  public:
274   LogMessageQuietlyFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD;
275   LogMessageQuietlyFatal(const char* file, int line,
276                          absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD;
277   ABSL_ATTRIBUTE_NORETURN ~LogMessageQuietlyFatal();
278 };
279 
280 }  // namespace log_internal
281 ABSL_NAMESPACE_END
282 }  // namespace absl
283 
284 extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
285     AbslInternalOnFatalLogMessage)(const absl::LogEntry&);
286 
287 #endif  // ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
288