log_streamer.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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/log_streamer.h
  17. // -----------------------------------------------------------------------------
  18. //
  19. // This header declares the class `LogStreamer` and convenience functions to
  20. // construct LogStreamer objects with different associated log severity levels.
  21. #ifndef Y_ABSL_LOG_LOG_STREAMER_H_
  22. #define Y_ABSL_LOG_LOG_STREAMER_H_
  23. #include <ios>
  24. #include <memory>
  25. #include <ostream>
  26. #include <util/generic/string.h>
  27. #include <utility>
  28. #include "y_absl/base/config.h"
  29. #include "y_absl/base/log_severity.h"
  30. #include "y_absl/log/absl_log.h"
  31. #include "y_absl/strings/internal/ostringstream.h"
  32. #include "y_absl/strings/string_view.h"
  33. #include "y_absl/types/optional.h"
  34. #include "y_absl/utility/utility.h"
  35. namespace y_absl {
  36. Y_ABSL_NAMESPACE_BEGIN
  37. // LogStreamer
  38. //
  39. // Although you can stream into `LOG(INFO)`, you can't pass it into a function
  40. // that takes a `std::ostream` parameter. `LogStreamer::stream()` provides a
  41. // `std::ostream` that buffers everything that's streamed in. The buffer's
  42. // contents are logged as if by `LOG` when the `LogStreamer` is destroyed.
  43. // If nothing is streamed in, an empty message is logged. If the specified
  44. // severity is `y_absl::LogSeverity::kFatal`, the program will be terminated when
  45. // the `LogStreamer` is destroyed regardless of whether any data were streamed
  46. // in.
  47. //
  48. // Factory functions corresponding to the `y_absl::LogSeverity` enumerators
  49. // are provided for convenience; if the desired severity is variable, invoke the
  50. // constructor directly.
  51. //
  52. // LogStreamer is movable, but not copyable.
  53. //
  54. // Examples:
  55. //
  56. // ShaveYakAndWriteToStream(
  57. // yak, y_absl::LogInfoStreamer(__FILE__, __LINE__).stream());
  58. //
  59. // {
  60. // // This logs a single line containing data streamed by all three function
  61. // // calls.
  62. // y_absl::LogStreamer streamer(y_absl::LogSeverity::kInfo, __FILE__, __LINE__);
  63. // ShaveYakAndWriteToStream(yak1, streamer.stream());
  64. // streamer.stream() << " ";
  65. // ShaveYakAndWriteToStream(yak2, streamer.stream());
  66. // streamer.stream() << " ";
  67. // ShaveYakAndWriteToStreamPointer(yak3, &streamer.stream());
  68. // }
  69. class LogStreamer final {
  70. public:
  71. // LogStreamer::LogStreamer()
  72. //
  73. // Creates a LogStreamer with a given `severity` that will log a message
  74. // attributed to the given `file` and `line`.
  75. explicit LogStreamer(y_absl::LogSeverity severity, y_absl::string_view file,
  76. int line)
  77. : severity_(severity),
  78. line_(line),
  79. file_(file),
  80. stream_(y_absl::in_place, &buf_) {
  81. // To match `LOG`'s defaults:
  82. stream_->setf(std::ios_base::showbase | std::ios_base::boolalpha);
  83. }
  84. // A moved-from `y_absl::LogStreamer` does not `LOG` when destroyed,
  85. // and a program that streams into one has undefined behavior.
  86. LogStreamer(LogStreamer&& that) noexcept
  87. : severity_(that.severity_),
  88. line_(that.line_),
  89. file_(std::move(that.file_)),
  90. buf_(std::move(that.buf_)),
  91. stream_(std::move(that.stream_)) {
  92. if (stream_.has_value()) stream_->str(&buf_);
  93. that.stream_.reset();
  94. }
  95. LogStreamer& operator=(LogStreamer&& that) {
  96. Y_ABSL_LOG_IF(LEVEL(severity_), stream_).AtLocation(file_, line_) << buf_;
  97. severity_ = that.severity_;
  98. file_ = std::move(that.file_);
  99. line_ = that.line_;
  100. buf_ = std::move(that.buf_);
  101. stream_ = std::move(that.stream_);
  102. if (stream_.has_value()) stream_->str(&buf_);
  103. that.stream_.reset();
  104. return *this;
  105. }
  106. // LogStreamer::~LogStreamer()
  107. //
  108. // Logs this LogStreamer's buffered content as if by LOG.
  109. ~LogStreamer() {
  110. Y_ABSL_LOG_IF(LEVEL(severity_), stream_.has_value()).AtLocation(file_, line_)
  111. << buf_;
  112. }
  113. // LogStreamer::stream()
  114. //
  115. // Returns the `std::ostream` to use to write into this LogStreamer' internal
  116. // buffer.
  117. std::ostream& stream() { return *stream_; }
  118. private:
  119. y_absl::LogSeverity severity_;
  120. int line_;
  121. TString file_;
  122. TString buf_;
  123. // A disengaged `stream_` indicates a moved-from `LogStreamer` that should not
  124. // `LOG` upon destruction.
  125. y_absl::optional<y_absl::strings_internal::OStringStream> stream_;
  126. };
  127. // LogInfoStreamer()
  128. //
  129. // Returns a LogStreamer that writes at level LogSeverity::kInfo.
  130. inline LogStreamer LogInfoStreamer(y_absl::string_view file, int line) {
  131. return y_absl::LogStreamer(y_absl::LogSeverity::kInfo, file, line);
  132. }
  133. // LogWarningStreamer()
  134. //
  135. // Returns a LogStreamer that writes at level LogSeverity::kWarning.
  136. inline LogStreamer LogWarningStreamer(y_absl::string_view file, int line) {
  137. return y_absl::LogStreamer(y_absl::LogSeverity::kWarning, file, line);
  138. }
  139. // LogErrorStreamer()
  140. //
  141. // Returns a LogStreamer that writes at level LogSeverity::kError.
  142. inline LogStreamer LogErrorStreamer(y_absl::string_view file, int line) {
  143. return y_absl::LogStreamer(y_absl::LogSeverity::kError, file, line);
  144. }
  145. // LogFatalStreamer()
  146. //
  147. // Returns a LogStreamer that writes at level LogSeverity::kFatal.
  148. //
  149. // The program will be terminated when this `LogStreamer` is destroyed,
  150. // regardless of whether any data were streamed in.
  151. inline LogStreamer LogFatalStreamer(y_absl::string_view file, int line) {
  152. return y_absl::LogStreamer(y_absl::LogSeverity::kFatal, file, line);
  153. }
  154. // LogDebugFatalStreamer()
  155. //
  156. // Returns a LogStreamer that writes at level LogSeverity::kLogDebugFatal.
  157. //
  158. // In debug mode, the program will be terminated when this `LogStreamer` is
  159. // destroyed, regardless of whether any data were streamed in.
  160. inline LogStreamer LogDebugFatalStreamer(y_absl::string_view file, int line) {
  161. return y_absl::LogStreamer(y_absl::kLogDebugFatal, file, line);
  162. }
  163. Y_ABSL_NAMESPACE_END
  164. } // namespace y_absl
  165. #endif // Y_ABSL_LOG_LOG_STREAMER_H_