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