tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

log_message.h (16893B)


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