xref: /aosp_15_r20/external/abseil-cpp/absl/log/log_streamer.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2022 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker //
15*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
16*9356374aSAndroid Build Coastguard Worker // File: log/log_streamer.h
17*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
18*9356374aSAndroid Build Coastguard Worker //
19*9356374aSAndroid Build Coastguard Worker // This header declares the class `LogStreamer` and convenience functions to
20*9356374aSAndroid Build Coastguard Worker // construct LogStreamer objects with different associated log severity levels.
21*9356374aSAndroid Build Coastguard Worker 
22*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_LOG_LOG_STREAMER_H_
23*9356374aSAndroid Build Coastguard Worker #define ABSL_LOG_LOG_STREAMER_H_
24*9356374aSAndroid Build Coastguard Worker 
25*9356374aSAndroid Build Coastguard Worker #include <ios>
26*9356374aSAndroid Build Coastguard Worker #include <memory>
27*9356374aSAndroid Build Coastguard Worker #include <ostream>
28*9356374aSAndroid Build Coastguard Worker #include <string>
29*9356374aSAndroid Build Coastguard Worker #include <utility>
30*9356374aSAndroid Build Coastguard Worker 
31*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
32*9356374aSAndroid Build Coastguard Worker #include "absl/base/log_severity.h"
33*9356374aSAndroid Build Coastguard Worker #include "absl/log/absl_log.h"
34*9356374aSAndroid Build Coastguard Worker #include "absl/strings/internal/ostringstream.h"
35*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
36*9356374aSAndroid Build Coastguard Worker #include "absl/types/optional.h"
37*9356374aSAndroid Build Coastguard Worker #include "absl/utility/utility.h"
38*9356374aSAndroid Build Coastguard Worker 
39*9356374aSAndroid Build Coastguard Worker namespace absl {
40*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
41*9356374aSAndroid Build Coastguard Worker 
42*9356374aSAndroid Build Coastguard Worker // LogStreamer
43*9356374aSAndroid Build Coastguard Worker //
44*9356374aSAndroid Build Coastguard Worker // Although you can stream into `LOG(INFO)`, you can't pass it into a function
45*9356374aSAndroid Build Coastguard Worker // that takes a `std::ostream` parameter. `LogStreamer::stream()` provides a
46*9356374aSAndroid Build Coastguard Worker // `std::ostream` that buffers everything that's streamed in.  The buffer's
47*9356374aSAndroid Build Coastguard Worker // contents are logged as if by `LOG` when the `LogStreamer` is destroyed.
48*9356374aSAndroid Build Coastguard Worker // If nothing is streamed in, an empty message is logged.  If the specified
49*9356374aSAndroid Build Coastguard Worker // severity is `absl::LogSeverity::kFatal`, the program will be terminated when
50*9356374aSAndroid Build Coastguard Worker // the `LogStreamer` is destroyed regardless of whether any data were streamed
51*9356374aSAndroid Build Coastguard Worker // in.
52*9356374aSAndroid Build Coastguard Worker //
53*9356374aSAndroid Build Coastguard Worker // Factory functions corresponding to the `absl::LogSeverity` enumerators
54*9356374aSAndroid Build Coastguard Worker // are provided for convenience; if the desired severity is variable, invoke the
55*9356374aSAndroid Build Coastguard Worker // constructor directly.
56*9356374aSAndroid Build Coastguard Worker //
57*9356374aSAndroid Build Coastguard Worker // LogStreamer is movable, but not copyable.
58*9356374aSAndroid Build Coastguard Worker //
59*9356374aSAndroid Build Coastguard Worker // Examples:
60*9356374aSAndroid Build Coastguard Worker //
61*9356374aSAndroid Build Coastguard Worker //   ShaveYakAndWriteToStream(
62*9356374aSAndroid Build Coastguard Worker //       yak, absl::LogInfoStreamer(__FILE__, __LINE__).stream());
63*9356374aSAndroid Build Coastguard Worker //
64*9356374aSAndroid Build Coastguard Worker //   {
65*9356374aSAndroid Build Coastguard Worker //     // This logs a single line containing data streamed by all three function
66*9356374aSAndroid Build Coastguard Worker //     // calls.
67*9356374aSAndroid Build Coastguard Worker //     absl::LogStreamer streamer(absl::LogSeverity::kInfo, __FILE__, __LINE__);
68*9356374aSAndroid Build Coastguard Worker //     ShaveYakAndWriteToStream(yak1, streamer.stream());
69*9356374aSAndroid Build Coastguard Worker //     streamer.stream() << " ";
70*9356374aSAndroid Build Coastguard Worker //     ShaveYakAndWriteToStream(yak2, streamer.stream());
71*9356374aSAndroid Build Coastguard Worker //     streamer.stream() << " ";
72*9356374aSAndroid Build Coastguard Worker //     ShaveYakAndWriteToStreamPointer(yak3, &streamer.stream());
73*9356374aSAndroid Build Coastguard Worker //   }
74*9356374aSAndroid Build Coastguard Worker class LogStreamer final {
75*9356374aSAndroid Build Coastguard Worker  public:
76*9356374aSAndroid Build Coastguard Worker   // LogStreamer::LogStreamer()
77*9356374aSAndroid Build Coastguard Worker   //
78*9356374aSAndroid Build Coastguard Worker   // Creates a LogStreamer with a given `severity` that will log a message
79*9356374aSAndroid Build Coastguard Worker   // attributed to the given `file` and `line`.
LogStreamer(absl::LogSeverity severity,absl::string_view file,int line)80*9356374aSAndroid Build Coastguard Worker   explicit LogStreamer(absl::LogSeverity severity, absl::string_view file,
81*9356374aSAndroid Build Coastguard Worker                        int line)
82*9356374aSAndroid Build Coastguard Worker       : severity_(severity),
83*9356374aSAndroid Build Coastguard Worker         line_(line),
84*9356374aSAndroid Build Coastguard Worker         file_(file),
85*9356374aSAndroid Build Coastguard Worker         stream_(absl::in_place, &buf_) {
86*9356374aSAndroid Build Coastguard Worker     // To match `LOG`'s defaults:
87*9356374aSAndroid Build Coastguard Worker     stream_->setf(std::ios_base::showbase | std::ios_base::boolalpha);
88*9356374aSAndroid Build Coastguard Worker   }
89*9356374aSAndroid Build Coastguard Worker 
90*9356374aSAndroid Build Coastguard Worker   // A moved-from `absl::LogStreamer` does not `LOG` when destroyed,
91*9356374aSAndroid Build Coastguard Worker   // and a program that streams into one has undefined behavior.
LogStreamer(LogStreamer && that)92*9356374aSAndroid Build Coastguard Worker   LogStreamer(LogStreamer&& that) noexcept
93*9356374aSAndroid Build Coastguard Worker       : severity_(that.severity_),
94*9356374aSAndroid Build Coastguard Worker         line_(that.line_),
95*9356374aSAndroid Build Coastguard Worker         file_(std::move(that.file_)),
96*9356374aSAndroid Build Coastguard Worker         buf_(std::move(that.buf_)),
97*9356374aSAndroid Build Coastguard Worker         stream_(std::move(that.stream_)) {
98*9356374aSAndroid Build Coastguard Worker     if (stream_.has_value()) stream_->str(&buf_);
99*9356374aSAndroid Build Coastguard Worker     that.stream_.reset();
100*9356374aSAndroid Build Coastguard Worker   }
101*9356374aSAndroid Build Coastguard Worker   LogStreamer& operator=(LogStreamer&& that) {
102*9356374aSAndroid Build Coastguard Worker     ABSL_LOG_IF(LEVEL(severity_), stream_).AtLocation(file_, line_) << buf_;
103*9356374aSAndroid Build Coastguard Worker     severity_ = that.severity_;
104*9356374aSAndroid Build Coastguard Worker     file_ = std::move(that.file_);
105*9356374aSAndroid Build Coastguard Worker     line_ = that.line_;
106*9356374aSAndroid Build Coastguard Worker     buf_ = std::move(that.buf_);
107*9356374aSAndroid Build Coastguard Worker     stream_ = std::move(that.stream_);
108*9356374aSAndroid Build Coastguard Worker     if (stream_.has_value()) stream_->str(&buf_);
109*9356374aSAndroid Build Coastguard Worker     that.stream_.reset();
110*9356374aSAndroid Build Coastguard Worker     return *this;
111*9356374aSAndroid Build Coastguard Worker   }
112*9356374aSAndroid Build Coastguard Worker 
113*9356374aSAndroid Build Coastguard Worker   // LogStreamer::~LogStreamer()
114*9356374aSAndroid Build Coastguard Worker   //
115*9356374aSAndroid Build Coastguard Worker   // Logs this LogStreamer's buffered content as if by LOG.
~LogStreamer()116*9356374aSAndroid Build Coastguard Worker   ~LogStreamer() {
117*9356374aSAndroid Build Coastguard Worker     ABSL_LOG_IF(LEVEL(severity_), stream_.has_value()).AtLocation(file_, line_)
118*9356374aSAndroid Build Coastguard Worker         << buf_;
119*9356374aSAndroid Build Coastguard Worker   }
120*9356374aSAndroid Build Coastguard Worker 
121*9356374aSAndroid Build Coastguard Worker   // LogStreamer::stream()
122*9356374aSAndroid Build Coastguard Worker   //
123*9356374aSAndroid Build Coastguard Worker   // Returns the `std::ostream` to use to write into this LogStreamer' internal
124*9356374aSAndroid Build Coastguard Worker   // buffer.
stream()125*9356374aSAndroid Build Coastguard Worker   std::ostream& stream() { return *stream_; }
126*9356374aSAndroid Build Coastguard Worker 
127*9356374aSAndroid Build Coastguard Worker  private:
128*9356374aSAndroid Build Coastguard Worker   absl::LogSeverity severity_;
129*9356374aSAndroid Build Coastguard Worker   int line_;
130*9356374aSAndroid Build Coastguard Worker   std::string file_;
131*9356374aSAndroid Build Coastguard Worker   std::string buf_;
132*9356374aSAndroid Build Coastguard Worker   // A disengaged `stream_` indicates a moved-from `LogStreamer` that should not
133*9356374aSAndroid Build Coastguard Worker   // `LOG` upon destruction.
134*9356374aSAndroid Build Coastguard Worker   absl::optional<absl::strings_internal::OStringStream> stream_;
135*9356374aSAndroid Build Coastguard Worker };
136*9356374aSAndroid Build Coastguard Worker 
137*9356374aSAndroid Build Coastguard Worker // LogInfoStreamer()
138*9356374aSAndroid Build Coastguard Worker //
139*9356374aSAndroid Build Coastguard Worker // Returns a LogStreamer that writes at level LogSeverity::kInfo.
LogInfoStreamer(absl::string_view file,int line)140*9356374aSAndroid Build Coastguard Worker inline LogStreamer LogInfoStreamer(absl::string_view file, int line) {
141*9356374aSAndroid Build Coastguard Worker   return absl::LogStreamer(absl::LogSeverity::kInfo, file, line);
142*9356374aSAndroid Build Coastguard Worker }
143*9356374aSAndroid Build Coastguard Worker 
144*9356374aSAndroid Build Coastguard Worker // LogWarningStreamer()
145*9356374aSAndroid Build Coastguard Worker //
146*9356374aSAndroid Build Coastguard Worker // Returns a LogStreamer that writes at level LogSeverity::kWarning.
LogWarningStreamer(absl::string_view file,int line)147*9356374aSAndroid Build Coastguard Worker inline LogStreamer LogWarningStreamer(absl::string_view file, int line) {
148*9356374aSAndroid Build Coastguard Worker   return absl::LogStreamer(absl::LogSeverity::kWarning, file, line);
149*9356374aSAndroid Build Coastguard Worker }
150*9356374aSAndroid Build Coastguard Worker 
151*9356374aSAndroid Build Coastguard Worker // LogErrorStreamer()
152*9356374aSAndroid Build Coastguard Worker //
153*9356374aSAndroid Build Coastguard Worker // Returns a LogStreamer that writes at level LogSeverity::kError.
LogErrorStreamer(absl::string_view file,int line)154*9356374aSAndroid Build Coastguard Worker inline LogStreamer LogErrorStreamer(absl::string_view file, int line) {
155*9356374aSAndroid Build Coastguard Worker   return absl::LogStreamer(absl::LogSeverity::kError, file, line);
156*9356374aSAndroid Build Coastguard Worker }
157*9356374aSAndroid Build Coastguard Worker 
158*9356374aSAndroid Build Coastguard Worker // LogFatalStreamer()
159*9356374aSAndroid Build Coastguard Worker //
160*9356374aSAndroid Build Coastguard Worker // Returns a LogStreamer that writes at level LogSeverity::kFatal.
161*9356374aSAndroid Build Coastguard Worker //
162*9356374aSAndroid Build Coastguard Worker // The program will be terminated when this `LogStreamer` is destroyed,
163*9356374aSAndroid Build Coastguard Worker // regardless of whether any data were streamed in.
LogFatalStreamer(absl::string_view file,int line)164*9356374aSAndroid Build Coastguard Worker inline LogStreamer LogFatalStreamer(absl::string_view file, int line) {
165*9356374aSAndroid Build Coastguard Worker   return absl::LogStreamer(absl::LogSeverity::kFatal, file, line);
166*9356374aSAndroid Build Coastguard Worker }
167*9356374aSAndroid Build Coastguard Worker 
168*9356374aSAndroid Build Coastguard Worker // LogDebugFatalStreamer()
169*9356374aSAndroid Build Coastguard Worker //
170*9356374aSAndroid Build Coastguard Worker // Returns a LogStreamer that writes at level LogSeverity::kLogDebugFatal.
171*9356374aSAndroid Build Coastguard Worker //
172*9356374aSAndroid Build Coastguard Worker // In debug mode, the program will be terminated when this `LogStreamer` is
173*9356374aSAndroid Build Coastguard Worker // destroyed, regardless of whether any data were streamed in.
LogDebugFatalStreamer(absl::string_view file,int line)174*9356374aSAndroid Build Coastguard Worker inline LogStreamer LogDebugFatalStreamer(absl::string_view file, int line) {
175*9356374aSAndroid Build Coastguard Worker   return absl::LogStreamer(absl::kLogDebugFatal, file, line);
176*9356374aSAndroid Build Coastguard Worker }
177*9356374aSAndroid Build Coastguard Worker 
178*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
179*9356374aSAndroid Build Coastguard Worker }  // namespace absl
180*9356374aSAndroid Build Coastguard Worker 
181*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_LOG_LOG_STREAMER_H_
182