xref: /aosp_15_r20/external/federated-compute/fcp/base/monitoring.h (revision 14675a029014e728ec732f129a32e299b2da0601)
1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker  * Copyright 2017 Google LLC
3*14675a02SAndroid Build Coastguard Worker  *
4*14675a02SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker  *
8*14675a02SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker  *
10*14675a02SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker  * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker  */
16*14675a02SAndroid Build Coastguard Worker #ifndef FCP_BASE_MONITORING_H_
17*14675a02SAndroid Build Coastguard Worker #define FCP_BASE_MONITORING_H_
18*14675a02SAndroid Build Coastguard Worker 
19*14675a02SAndroid Build Coastguard Worker #include <string>
20*14675a02SAndroid Build Coastguard Worker #include <utility>
21*14675a02SAndroid Build Coastguard Worker 
22*14675a02SAndroid Build Coastguard Worker #include "fcp/base/new.h"
23*14675a02SAndroid Build Coastguard Worker 
24*14675a02SAndroid Build Coastguard Worker #ifdef FCP_BAREMETAL
25*14675a02SAndroid Build Coastguard Worker #include "fcp/base/string_stream.h"
26*14675a02SAndroid Build Coastguard Worker #else
27*14675a02SAndroid Build Coastguard Worker #include <cstdlib>
28*14675a02SAndroid Build Coastguard Worker #include <iostream>
29*14675a02SAndroid Build Coastguard Worker #include <ostream>
30*14675a02SAndroid Build Coastguard Worker #include <sstream>
31*14675a02SAndroid Build Coastguard Worker 
32*14675a02SAndroid Build Coastguard Worker #include "absl/base/attributes.h"
33*14675a02SAndroid Build Coastguard Worker #include "absl/base/log_severity.h"
34*14675a02SAndroid Build Coastguard Worker #include "absl/base/optimization.h"
35*14675a02SAndroid Build Coastguard Worker #include "absl/status/status.h"
36*14675a02SAndroid Build Coastguard Worker #include "absl/status/statusor.h"
37*14675a02SAndroid Build Coastguard Worker #endif  // FCP_BAREMETAL
38*14675a02SAndroid Build Coastguard Worker 
39*14675a02SAndroid Build Coastguard Worker namespace fcp {
40*14675a02SAndroid Build Coastguard Worker 
41*14675a02SAndroid Build Coastguard Worker // General Definitions
42*14675a02SAndroid Build Coastguard Worker // ===================
43*14675a02SAndroid Build Coastguard Worker 
44*14675a02SAndroid Build Coastguard Worker /**
45*14675a02SAndroid Build Coastguard Worker  * Indicates to run the functionality in this file in debugging mode. This
46*14675a02SAndroid Build Coastguard Worker  * creates more exhaustive diagnostics in some cases, as documented case by
47*14675a02SAndroid Build Coastguard Worker  * case.
48*14675a02SAndroid Build Coastguard Worker  *
49*14675a02SAndroid Build Coastguard Worker  * We may want to make this a flag if this turns out to be often needed.
50*14675a02SAndroid Build Coastguard Worker  */
51*14675a02SAndroid Build Coastguard Worker constexpr bool fcp_debug = false;
52*14675a02SAndroid Build Coastguard Worker 
53*14675a02SAndroid Build Coastguard Worker // Logging and Assertions
54*14675a02SAndroid Build Coastguard Worker // ======================
55*14675a02SAndroid Build Coastguard Worker 
56*14675a02SAndroid Build Coastguard Worker /**
57*14675a02SAndroid Build Coastguard Worker  * Defines a subset of Google style logging. Use FCP_LOG(INFO),
58*14675a02SAndroid Build Coastguard Worker  * FCP_LOG(WARNING), FCP_LOG(ERROR) or FCP_LOG(FATAL) to stream log messages.
59*14675a02SAndroid Build Coastguard Worker  * Example:
60*14675a02SAndroid Build Coastguard Worker  *
61*14675a02SAndroid Build Coastguard Worker  *     FCP_LOG(INFO) << "some info log";
62*14675a02SAndroid Build Coastguard Worker  */
63*14675a02SAndroid Build Coastguard Worker // TODO(team): adapt to absl logging once available
64*14675a02SAndroid Build Coastguard Worker #define FCP_LOG(severity) _FCP_LOG_##severity
65*14675a02SAndroid Build Coastguard Worker 
66*14675a02SAndroid Build Coastguard Worker #define FCP_LOG_IF(severity, condition) \
67*14675a02SAndroid Build Coastguard Worker   !(condition) ? (void)0                \
68*14675a02SAndroid Build Coastguard Worker                : ::fcp::internal::LogMessageVoidify() & _FCP_LOG_##severity
69*14675a02SAndroid Build Coastguard Worker 
70*14675a02SAndroid Build Coastguard Worker /**
71*14675a02SAndroid Build Coastguard Worker  * Log Severity
72*14675a02SAndroid Build Coastguard Worker  */
73*14675a02SAndroid Build Coastguard Worker #ifdef FCP_BAREMETAL
74*14675a02SAndroid Build Coastguard Worker enum class LogSeverity : int {
75*14675a02SAndroid Build Coastguard Worker   kInfo = 0,
76*14675a02SAndroid Build Coastguard Worker   kWarning = 1,
77*14675a02SAndroid Build Coastguard Worker   kError = 2,
78*14675a02SAndroid Build Coastguard Worker   kFatal = 3,
79*14675a02SAndroid Build Coastguard Worker };
80*14675a02SAndroid Build Coastguard Worker #else
81*14675a02SAndroid Build Coastguard Worker using LogSeverity = absl::LogSeverity;
82*14675a02SAndroid Build Coastguard Worker #endif  // FCP_BAREMETAL
83*14675a02SAndroid Build Coastguard Worker 
84*14675a02SAndroid Build Coastguard Worker #define _FCP_LOG_INFO \
85*14675a02SAndroid Build Coastguard Worker   ::fcp::internal::LogMessage(__FILE__, __LINE__, ::fcp::LogSeverity::kInfo)
86*14675a02SAndroid Build Coastguard Worker #define _FCP_LOG_WARNING \
87*14675a02SAndroid Build Coastguard Worker   ::fcp::internal::LogMessage(__FILE__, __LINE__, ::fcp::LogSeverity::kWarning)
88*14675a02SAndroid Build Coastguard Worker #define _FCP_LOG_ERROR \
89*14675a02SAndroid Build Coastguard Worker   ::fcp::internal::LogMessage(__FILE__, __LINE__, ::fcp::LogSeverity::kError)
90*14675a02SAndroid Build Coastguard Worker #define _FCP_LOG_FATAL \
91*14675a02SAndroid Build Coastguard Worker   ::fcp::internal::LogMessage(__FILE__, __LINE__, ::fcp::LogSeverity::kFatal)
92*14675a02SAndroid Build Coastguard Worker 
93*14675a02SAndroid Build Coastguard Worker #ifdef FCP_BAREMETAL
94*14675a02SAndroid Build Coastguard Worker #define FCP_PREDICT_FALSE(x) (x)
95*14675a02SAndroid Build Coastguard Worker #define FCP_PREDICT_TRUE(x) (x)
96*14675a02SAndroid Build Coastguard Worker #else
97*14675a02SAndroid Build Coastguard Worker #define FCP_PREDICT_FALSE(x) ABSL_PREDICT_FALSE(x)
98*14675a02SAndroid Build Coastguard Worker #define FCP_PREDICT_TRUE(x) ABSL_PREDICT_TRUE(x)
99*14675a02SAndroid Build Coastguard Worker #endif
100*14675a02SAndroid Build Coastguard Worker 
101*14675a02SAndroid Build Coastguard Worker /**
102*14675a02SAndroid Build Coastguard Worker  * Check that the condition holds, otherwise die. Any additional messages can
103*14675a02SAndroid Build Coastguard Worker  * be streamed into the invocation. Example:
104*14675a02SAndroid Build Coastguard Worker  *
105*14675a02SAndroid Build Coastguard Worker  *     FCP_CHECK(condition) << "stuff went wrong";
106*14675a02SAndroid Build Coastguard Worker  */
107*14675a02SAndroid Build Coastguard Worker #define FCP_CHECK(condition)                         \
108*14675a02SAndroid Build Coastguard Worker   FCP_LOG_IF(FATAL, FCP_PREDICT_FALSE(!(condition))) \
109*14675a02SAndroid Build Coastguard Worker       << ("Check failed: " #condition ". ")
110*14675a02SAndroid Build Coastguard Worker 
111*14675a02SAndroid Build Coastguard Worker /**
112*14675a02SAndroid Build Coastguard Worker  * Check that the expression generating a status code is OK, otherwise die.
113*14675a02SAndroid Build Coastguard Worker  * Any additional messages can be streamed into the invocation.
114*14675a02SAndroid Build Coastguard Worker  */
115*14675a02SAndroid Build Coastguard Worker #define FCP_CHECK_STATUS(status)                                     \
116*14675a02SAndroid Build Coastguard Worker   for (auto __check_status = (status);                               \
117*14675a02SAndroid Build Coastguard Worker        __check_status.code() != ::fcp::StatusCode::kOk;)             \
118*14675a02SAndroid Build Coastguard Worker   FCP_LOG_IF(FATAL, __check_status.code() != ::fcp::StatusCode::kOk) \
119*14675a02SAndroid Build Coastguard Worker       << "status not OK: " << __check_status
120*14675a02SAndroid Build Coastguard Worker 
121*14675a02SAndroid Build Coastguard Worker // Logging Implementation Details
122*14675a02SAndroid Build Coastguard Worker // ==============================
123*14675a02SAndroid Build Coastguard Worker 
124*14675a02SAndroid Build Coastguard Worker namespace internal {
125*14675a02SAndroid Build Coastguard Worker 
126*14675a02SAndroid Build Coastguard Worker /**
127*14675a02SAndroid Build Coastguard Worker  * An object which implements a logger sink. The default sink sends log
128*14675a02SAndroid Build Coastguard Worker  * messages to stderr.
129*14675a02SAndroid Build Coastguard Worker  */
130*14675a02SAndroid Build Coastguard Worker class Logger {
131*14675a02SAndroid Build Coastguard Worker  public:
132*14675a02SAndroid Build Coastguard Worker   virtual ~Logger() = default;
133*14675a02SAndroid Build Coastguard Worker 
134*14675a02SAndroid Build Coastguard Worker   /**
135*14675a02SAndroid Build Coastguard Worker    * Basic log function.
136*14675a02SAndroid Build Coastguard Worker    *
137*14675a02SAndroid Build Coastguard Worker    * @param file The name of the associated file.
138*14675a02SAndroid Build Coastguard Worker    * @param line  The line in this file.
139*14675a02SAndroid Build Coastguard Worker    * @param severity  Severity of the log message.
140*14675a02SAndroid Build Coastguard Worker    * @param message  The message to log.
141*14675a02SAndroid Build Coastguard Worker    */
142*14675a02SAndroid Build Coastguard Worker   virtual void Log(const char* file, int line, LogSeverity severity,
143*14675a02SAndroid Build Coastguard Worker                    const char* message);
144*14675a02SAndroid Build Coastguard Worker };
145*14675a02SAndroid Build Coastguard Worker 
146*14675a02SAndroid Build Coastguard Worker /**
147*14675a02SAndroid Build Coastguard Worker  * Gets/sets the active logger object.
148*14675a02SAndroid Build Coastguard Worker  */
149*14675a02SAndroid Build Coastguard Worker Logger* logger();
150*14675a02SAndroid Build Coastguard Worker void set_logger(Logger* logger);
151*14675a02SAndroid Build Coastguard Worker 
152*14675a02SAndroid Build Coastguard Worker #ifndef FCP_BAREMETAL
153*14675a02SAndroid Build Coastguard Worker using StringStream = std::ostringstream;
154*14675a02SAndroid Build Coastguard Worker #endif  // FCP_BAREMETAL
155*14675a02SAndroid Build Coastguard Worker 
156*14675a02SAndroid Build Coastguard Worker /**
157*14675a02SAndroid Build Coastguard Worker  * Object allowing to construct a log message by streaming into it. This is
158*14675a02SAndroid Build Coastguard Worker  * used by the macro LOG(severity).
159*14675a02SAndroid Build Coastguard Worker  */
160*14675a02SAndroid Build Coastguard Worker class LogMessage {
161*14675a02SAndroid Build Coastguard Worker  public:
LogMessage(const char * file,int line,LogSeverity severity)162*14675a02SAndroid Build Coastguard Worker   LogMessage(const char* file, int line, LogSeverity severity)
163*14675a02SAndroid Build Coastguard Worker       : file_(file), line_(line), severity_(severity) {}
164*14675a02SAndroid Build Coastguard Worker 
165*14675a02SAndroid Build Coastguard Worker   template <typename T>
166*14675a02SAndroid Build Coastguard Worker   LogMessage& operator<<(const T& x) {
167*14675a02SAndroid Build Coastguard Worker     message_ << x;
168*14675a02SAndroid Build Coastguard Worker     return *this;
169*14675a02SAndroid Build Coastguard Worker   }
170*14675a02SAndroid Build Coastguard Worker 
171*14675a02SAndroid Build Coastguard Worker #ifndef FCP_BAREMETAL
172*14675a02SAndroid Build Coastguard Worker   LogMessage& operator<<(std::ostream& (*pf)(std::ostream&)) {
173*14675a02SAndroid Build Coastguard Worker     message_ << pf;
174*14675a02SAndroid Build Coastguard Worker     return *this;
175*14675a02SAndroid Build Coastguard Worker   }
176*14675a02SAndroid Build Coastguard Worker #endif
177*14675a02SAndroid Build Coastguard Worker 
~LogMessage()178*14675a02SAndroid Build Coastguard Worker   ~LogMessage() {
179*14675a02SAndroid Build Coastguard Worker     logger()->Log(file_, line_, severity_, message_.str().c_str());
180*14675a02SAndroid Build Coastguard Worker     if (severity_ == LogSeverity::kFatal) {
181*14675a02SAndroid Build Coastguard Worker       abort();
182*14675a02SAndroid Build Coastguard Worker     }
183*14675a02SAndroid Build Coastguard Worker   }
184*14675a02SAndroid Build Coastguard Worker 
185*14675a02SAndroid Build Coastguard Worker  private:
186*14675a02SAndroid Build Coastguard Worker   const char* file_;
187*14675a02SAndroid Build Coastguard Worker   int line_;
188*14675a02SAndroid Build Coastguard Worker   LogSeverity severity_;
189*14675a02SAndroid Build Coastguard Worker   StringStream message_;
190*14675a02SAndroid Build Coastguard Worker };
191*14675a02SAndroid Build Coastguard Worker 
192*14675a02SAndroid Build Coastguard Worker /**
193*14675a02SAndroid Build Coastguard Worker  * This class is used to cast a LogMessage instance to void within a ternary
194*14675a02SAndroid Build Coastguard Worker  * expression in the expansion of FCP_LOG_IF.  The cast is necessary so
195*14675a02SAndroid Build Coastguard Worker  * that the types of the expressions on either side of the : match, and the &
196*14675a02SAndroid Build Coastguard Worker  * operator is used because its precedence is lower than << but higher than
197*14675a02SAndroid Build Coastguard Worker  * ?:.
198*14675a02SAndroid Build Coastguard Worker  */
199*14675a02SAndroid Build Coastguard Worker class LogMessageVoidify {
200*14675a02SAndroid Build Coastguard Worker  public:
201*14675a02SAndroid Build Coastguard Worker   void operator&(LogMessage&) {}  // NOLINT
202*14675a02SAndroid Build Coastguard Worker };
203*14675a02SAndroid Build Coastguard Worker 
204*14675a02SAndroid Build Coastguard Worker }  // namespace internal
205*14675a02SAndroid Build Coastguard Worker 
206*14675a02SAndroid Build Coastguard Worker // Status and StatusOr
207*14675a02SAndroid Build Coastguard Worker // ===================
208*14675a02SAndroid Build Coastguard Worker 
209*14675a02SAndroid Build Coastguard Worker /**
210*14675a02SAndroid Build Coastguard Worker  * Constructor for a status. A status message can be streamed into it. This
211*14675a02SAndroid Build Coastguard Worker  * captures the current file and line position and includes it into the status
212*14675a02SAndroid Build Coastguard Worker  * message if the status code is not OK.
213*14675a02SAndroid Build Coastguard Worker  *
214*14675a02SAndroid Build Coastguard Worker  * Use as in:
215*14675a02SAndroid Build Coastguard Worker  *
216*14675a02SAndroid Build Coastguard Worker  *   FCP_STATUS(OK);                // signal success
217*14675a02SAndroid Build Coastguard Worker  *   FCP_STATUS(code) << message;   // signal failure
218*14675a02SAndroid Build Coastguard Worker  *
219*14675a02SAndroid Build Coastguard Worker  * FCP_STATUS can be used in places which either expect a Status or a
220*14675a02SAndroid Build Coastguard Worker  * StatusOr<T>.
221*14675a02SAndroid Build Coastguard Worker  *
222*14675a02SAndroid Build Coastguard Worker  * You can configure the constructed status to also emit a log entry if the
223*14675a02SAndroid Build Coastguard Worker  * status is not OK by using LogInfo, LogWarning, LogError, or LogFatal as
224*14675a02SAndroid Build Coastguard Worker  * below:
225*14675a02SAndroid Build Coastguard Worker  *
226*14675a02SAndroid Build Coastguard Worker  *   FCP_STATUS(code).LogInfo() << message;
227*14675a02SAndroid Build Coastguard Worker  *
228*14675a02SAndroid Build Coastguard Worker  * If the constant rx_debug is true, by default, all FCP_STATUS invocations
229*14675a02SAndroid Build Coastguard Worker  * will be logged on INFO level.
230*14675a02SAndroid Build Coastguard Worker  */
231*14675a02SAndroid Build Coastguard Worker #define FCP_STATUS(code) \
232*14675a02SAndroid Build Coastguard Worker   ::fcp::internal::MakeStatusBuilder(code, __FILE__, __LINE__)
233*14675a02SAndroid Build Coastguard Worker 
234*14675a02SAndroid Build Coastguard Worker #ifdef FCP_BAREMETAL
235*14675a02SAndroid Build Coastguard Worker #define FCP_MUST_USE_RESULT __attribute__((warn_unused_result))
236*14675a02SAndroid Build Coastguard Worker #else
237*14675a02SAndroid Build Coastguard Worker #define FCP_MUST_USE_RESULT ABSL_MUST_USE_RESULT
238*14675a02SAndroid Build Coastguard Worker #endif
239*14675a02SAndroid Build Coastguard Worker 
240*14675a02SAndroid Build Coastguard Worker #ifdef FCP_BAREMETAL
241*14675a02SAndroid Build Coastguard Worker 
242*14675a02SAndroid Build Coastguard Worker // The bare-metal implementation doesn't depend on Abseil library and
243*14675a02SAndroid Build Coastguard Worker // provides its own implementations of StatusCode, Status and StatusOr that are
244*14675a02SAndroid Build Coastguard Worker // source code compatible with absl::StatusCode, absl::Status,
245*14675a02SAndroid Build Coastguard Worker // and absl::StatusOr.
246*14675a02SAndroid Build Coastguard Worker 
247*14675a02SAndroid Build Coastguard Worker // See absl::StatusCode for details.
248*14675a02SAndroid Build Coastguard Worker enum StatusCode : int {
249*14675a02SAndroid Build Coastguard Worker   kOk = 0,
250*14675a02SAndroid Build Coastguard Worker   kCancelled = 1,
251*14675a02SAndroid Build Coastguard Worker   kUnknown = 2,
252*14675a02SAndroid Build Coastguard Worker   kInvalidArgument = 3,
253*14675a02SAndroid Build Coastguard Worker   kDeadlineExceeded = 4,
254*14675a02SAndroid Build Coastguard Worker   kNotFound = 5,
255*14675a02SAndroid Build Coastguard Worker   kAlreadyExists = 6,
256*14675a02SAndroid Build Coastguard Worker   kPermissionDenied = 7,
257*14675a02SAndroid Build Coastguard Worker   kResourceExhausted = 8,
258*14675a02SAndroid Build Coastguard Worker   kFailedPrecondition = 9,
259*14675a02SAndroid Build Coastguard Worker   kAborted = 10,
260*14675a02SAndroid Build Coastguard Worker   kOutOfRange = 11,
261*14675a02SAndroid Build Coastguard Worker   kUnimplemented = 12,
262*14675a02SAndroid Build Coastguard Worker   kInternal = 13,
263*14675a02SAndroid Build Coastguard Worker   kUnavailable = 14,
264*14675a02SAndroid Build Coastguard Worker   kDataLoss = 15,
265*14675a02SAndroid Build Coastguard Worker   kUnauthenticated = 16,
266*14675a02SAndroid Build Coastguard Worker };
267*14675a02SAndroid Build Coastguard Worker 
268*14675a02SAndroid Build Coastguard Worker class FCP_MUST_USE_RESULT Status final {
269*14675a02SAndroid Build Coastguard Worker  public:
Status()270*14675a02SAndroid Build Coastguard Worker   Status() : code_(StatusCode::kOk) {}
Status(StatusCode code,const std::string & message)271*14675a02SAndroid Build Coastguard Worker   Status(StatusCode code, const std::string& message)
272*14675a02SAndroid Build Coastguard Worker       : code_(code), message_(message) {}
273*14675a02SAndroid Build Coastguard Worker 
274*14675a02SAndroid Build Coastguard Worker   // Status is copyable and moveable.
275*14675a02SAndroid Build Coastguard Worker   Status(const Status&) = default;
276*14675a02SAndroid Build Coastguard Worker   Status& operator=(const Status&) = default;
277*14675a02SAndroid Build Coastguard Worker   Status(Status&&) = default;
278*14675a02SAndroid Build Coastguard Worker   Status& operator=(Status&&) = default;
279*14675a02SAndroid Build Coastguard Worker 
280*14675a02SAndroid Build Coastguard Worker   // Tests whether this status is OK.
ok()281*14675a02SAndroid Build Coastguard Worker   bool ok() const { return code_ == StatusCode::kOk; }
282*14675a02SAndroid Build Coastguard Worker 
283*14675a02SAndroid Build Coastguard Worker   // Gets this status code.
code()284*14675a02SAndroid Build Coastguard Worker   StatusCode code() const { return code_; }
285*14675a02SAndroid Build Coastguard Worker 
286*14675a02SAndroid Build Coastguard Worker   // Gets this status message.
message()287*14675a02SAndroid Build Coastguard Worker   const std::string& message() const { return message_; }
288*14675a02SAndroid Build Coastguard Worker 
289*14675a02SAndroid Build Coastguard Worker  private:
290*14675a02SAndroid Build Coastguard Worker   StatusCode code_;
291*14675a02SAndroid Build Coastguard Worker   std::string message_;
292*14675a02SAndroid Build Coastguard Worker };
293*14675a02SAndroid Build Coastguard Worker 
294*14675a02SAndroid Build Coastguard Worker template <typename T>
295*14675a02SAndroid Build Coastguard Worker class FCP_MUST_USE_RESULT StatusOr final {
296*14675a02SAndroid Build Coastguard Worker  public:
297*14675a02SAndroid Build Coastguard Worker   // Default constructor initializes StatusOr with kUnknown code.
StatusOr()298*14675a02SAndroid Build Coastguard Worker   explicit StatusOr() : StatusOr(StatusCode::kUnknown) {}
299*14675a02SAndroid Build Coastguard Worker 
300*14675a02SAndroid Build Coastguard Worker   // Constructs a StatusOr from a failed status. The passed status must not be
301*14675a02SAndroid Build Coastguard Worker   // OK. This constructor is expected to be implicitly called.
StatusOr(Status status)302*14675a02SAndroid Build Coastguard Worker   StatusOr(Status status)  // NOLINT
303*14675a02SAndroid Build Coastguard Worker       : status_(std::move(status)) {
304*14675a02SAndroid Build Coastguard Worker     FCP_CHECK(!this->status().ok());
305*14675a02SAndroid Build Coastguard Worker   }
306*14675a02SAndroid Build Coastguard Worker 
307*14675a02SAndroid Build Coastguard Worker   // Constructs a StatusOr from a status code.
StatusOr(StatusCode code)308*14675a02SAndroid Build Coastguard Worker   explicit StatusOr(StatusCode code) : StatusOr(code, "") {}
309*14675a02SAndroid Build Coastguard Worker 
310*14675a02SAndroid Build Coastguard Worker   // Constructs a StatusOr from a status code and a message.
StatusOr(StatusCode code,const std::string & message)311*14675a02SAndroid Build Coastguard Worker   StatusOr(StatusCode code, const std::string& message)
312*14675a02SAndroid Build Coastguard Worker       : status_(Status(code, message)) {
313*14675a02SAndroid Build Coastguard Worker     FCP_CHECK(!this->status().ok());
314*14675a02SAndroid Build Coastguard Worker   }
315*14675a02SAndroid Build Coastguard Worker 
316*14675a02SAndroid Build Coastguard Worker   // Construct a StatusOr from a value.
StatusOr(const T & value)317*14675a02SAndroid Build Coastguard Worker   StatusOr(const T& value)  // NOLINT
318*14675a02SAndroid Build Coastguard Worker       : value_(value) {}
319*14675a02SAndroid Build Coastguard Worker 
320*14675a02SAndroid Build Coastguard Worker   // Construct a StatusOr from an R-value.
StatusOr(T && value)321*14675a02SAndroid Build Coastguard Worker   StatusOr(T&& value)  // NOLINT
322*14675a02SAndroid Build Coastguard Worker       : value_(std::move(value)) {}
323*14675a02SAndroid Build Coastguard Worker 
324*14675a02SAndroid Build Coastguard Worker   // StatusOr is copyable and moveable.
StatusOr(const StatusOr & other)325*14675a02SAndroid Build Coastguard Worker   StatusOr(const StatusOr& other) : status_(other.status_) {
326*14675a02SAndroid Build Coastguard Worker     if (ok()) {
327*14675a02SAndroid Build Coastguard Worker       AssignValue(other.value_);
328*14675a02SAndroid Build Coastguard Worker     }
329*14675a02SAndroid Build Coastguard Worker   }
330*14675a02SAndroid Build Coastguard Worker 
StatusOr(StatusOr && other)331*14675a02SAndroid Build Coastguard Worker   StatusOr(StatusOr&& other) : status_(std::move(other.status_)) {
332*14675a02SAndroid Build Coastguard Worker     if (ok()) {
333*14675a02SAndroid Build Coastguard Worker       AssignValue(std::move(other.value_));
334*14675a02SAndroid Build Coastguard Worker     }
335*14675a02SAndroid Build Coastguard Worker   }
336*14675a02SAndroid Build Coastguard Worker 
337*14675a02SAndroid Build Coastguard Worker   StatusOr& operator=(const StatusOr& other) {
338*14675a02SAndroid Build Coastguard Worker     if (this != &other) {
339*14675a02SAndroid Build Coastguard Worker       ClearValue();
340*14675a02SAndroid Build Coastguard Worker       if (other.ok()) {
341*14675a02SAndroid Build Coastguard Worker         AssignValue(other.value_);
342*14675a02SAndroid Build Coastguard Worker       }
343*14675a02SAndroid Build Coastguard Worker       status_ = other.status_;
344*14675a02SAndroid Build Coastguard Worker     }
345*14675a02SAndroid Build Coastguard Worker     return *this;
346*14675a02SAndroid Build Coastguard Worker   }
347*14675a02SAndroid Build Coastguard Worker 
348*14675a02SAndroid Build Coastguard Worker   StatusOr& operator=(StatusOr&& other) {
349*14675a02SAndroid Build Coastguard Worker     if (this != &other) {
350*14675a02SAndroid Build Coastguard Worker       ClearValue();
351*14675a02SAndroid Build Coastguard Worker       if (other.ok()) {
352*14675a02SAndroid Build Coastguard Worker         AssignValue(std::move(other.value_));
353*14675a02SAndroid Build Coastguard Worker       }
354*14675a02SAndroid Build Coastguard Worker       status_ = std::move(other.status_);
355*14675a02SAndroid Build Coastguard Worker     }
356*14675a02SAndroid Build Coastguard Worker     return *this;
357*14675a02SAndroid Build Coastguard Worker   }
358*14675a02SAndroid Build Coastguard Worker 
~StatusOr()359*14675a02SAndroid Build Coastguard Worker   ~StatusOr() { ClearValue(); }
360*14675a02SAndroid Build Coastguard Worker 
361*14675a02SAndroid Build Coastguard Worker   // Tests whether this StatusOr is OK and has a value.
ok()362*14675a02SAndroid Build Coastguard Worker   bool ok() const { return status_.ok(); }
363*14675a02SAndroid Build Coastguard Worker 
364*14675a02SAndroid Build Coastguard Worker   // Returns the status.
status()365*14675a02SAndroid Build Coastguard Worker   const Status& status() const { return status_; }
366*14675a02SAndroid Build Coastguard Worker 
367*14675a02SAndroid Build Coastguard Worker   // Returns the value if the StatusOr is OK.
value()368*14675a02SAndroid Build Coastguard Worker   const T& value() const& {
369*14675a02SAndroid Build Coastguard Worker     CheckOk();
370*14675a02SAndroid Build Coastguard Worker     return value_;
371*14675a02SAndroid Build Coastguard Worker   }
value()372*14675a02SAndroid Build Coastguard Worker   T& value() & {
373*14675a02SAndroid Build Coastguard Worker     CheckOk();
374*14675a02SAndroid Build Coastguard Worker     return value_;
375*14675a02SAndroid Build Coastguard Worker   }
value()376*14675a02SAndroid Build Coastguard Worker   T&& value() && {
377*14675a02SAndroid Build Coastguard Worker     CheckOk();
378*14675a02SAndroid Build Coastguard Worker     return std::move(value_);
379*14675a02SAndroid Build Coastguard Worker   }
380*14675a02SAndroid Build Coastguard Worker 
381*14675a02SAndroid Build Coastguard Worker   // Operator *
382*14675a02SAndroid Build Coastguard Worker   const T& operator*() const& { return value(); }
383*14675a02SAndroid Build Coastguard Worker   T& operator*() & { return value(); }
384*14675a02SAndroid Build Coastguard Worker   T&& operator*() && { return std::move(value()); }
385*14675a02SAndroid Build Coastguard Worker 
386*14675a02SAndroid Build Coastguard Worker   // Operator ->
387*14675a02SAndroid Build Coastguard Worker   const T* operator->() const { return &value(); }
388*14675a02SAndroid Build Coastguard Worker   T* operator->() { return &value(); }
389*14675a02SAndroid Build Coastguard Worker 
390*14675a02SAndroid Build Coastguard Worker   // Used to explicitly ignore a StatusOr (avoiding unused-result warnings).
Ignore()391*14675a02SAndroid Build Coastguard Worker   void Ignore() const {}
392*14675a02SAndroid Build Coastguard Worker 
393*14675a02SAndroid Build Coastguard Worker  private:
CheckOk()394*14675a02SAndroid Build Coastguard Worker   void CheckOk() const { FCP_CHECK(ok()) << "StatusOr has no value"; }
395*14675a02SAndroid Build Coastguard Worker 
396*14675a02SAndroid Build Coastguard Worker   // This is used to assign the value in place without invoking the assignment
397*14675a02SAndroid Build Coastguard Worker   // operator. Using the assignment operator wouldn't work in case the value_
398*14675a02SAndroid Build Coastguard Worker   // wasn't previously initialized. For example the value_ object might try
399*14675a02SAndroid Build Coastguard Worker   // to clear its previous value.
400*14675a02SAndroid Build Coastguard Worker   template <typename Arg>
AssignValue(Arg && arg)401*14675a02SAndroid Build Coastguard Worker   void AssignValue(Arg&& arg) {
402*14675a02SAndroid Build Coastguard Worker     new (&unused_) T(std::forward<Arg>(arg));
403*14675a02SAndroid Build Coastguard Worker   }
404*14675a02SAndroid Build Coastguard Worker 
405*14675a02SAndroid Build Coastguard Worker   // Destroy the current value if it was initialized.
ClearValue()406*14675a02SAndroid Build Coastguard Worker   void ClearValue() {
407*14675a02SAndroid Build Coastguard Worker     if (ok()) value_.~T();
408*14675a02SAndroid Build Coastguard Worker   }
409*14675a02SAndroid Build Coastguard Worker 
410*14675a02SAndroid Build Coastguard Worker   Status status_;
411*14675a02SAndroid Build Coastguard Worker 
412*14675a02SAndroid Build Coastguard Worker   // Using the union allows to avoid initializing the value_ field when
413*14675a02SAndroid Build Coastguard Worker   // StatusOr is constructed with Status.
414*14675a02SAndroid Build Coastguard Worker   struct Unused {};
415*14675a02SAndroid Build Coastguard Worker   union {
416*14675a02SAndroid Build Coastguard Worker     Unused unused_;
417*14675a02SAndroid Build Coastguard Worker     T value_;
418*14675a02SAndroid Build Coastguard Worker   };
419*14675a02SAndroid Build Coastguard Worker };
420*14675a02SAndroid Build Coastguard Worker 
421*14675a02SAndroid Build Coastguard Worker #else
422*14675a02SAndroid Build Coastguard Worker 
423*14675a02SAndroid Build Coastguard Worker // By default absl::Status and absl::StatusOr classes are used.
424*14675a02SAndroid Build Coastguard Worker using Status = absl::Status;
425*14675a02SAndroid Build Coastguard Worker using StatusCode = absl::StatusCode;
426*14675a02SAndroid Build Coastguard Worker template <typename T>
427*14675a02SAndroid Build Coastguard Worker using StatusOr = absl::StatusOr<T>;
428*14675a02SAndroid Build Coastguard Worker 
429*14675a02SAndroid Build Coastguard Worker #endif  // FCP_BAREMETAL
430*14675a02SAndroid Build Coastguard Worker 
431*14675a02SAndroid Build Coastguard Worker constexpr auto OK = StatusCode::kOk;
432*14675a02SAndroid Build Coastguard Worker constexpr auto CANCELLED = StatusCode::kCancelled;
433*14675a02SAndroid Build Coastguard Worker constexpr auto UNKNOWN = StatusCode::kUnknown;
434*14675a02SAndroid Build Coastguard Worker constexpr auto INVALID_ARGUMENT = StatusCode::kInvalidArgument;
435*14675a02SAndroid Build Coastguard Worker constexpr auto DEADLINE_EXCEEDED = StatusCode::kDeadlineExceeded;
436*14675a02SAndroid Build Coastguard Worker constexpr auto NOT_FOUND = StatusCode::kNotFound;
437*14675a02SAndroid Build Coastguard Worker constexpr auto ALREADY_EXISTS = StatusCode::kAlreadyExists;
438*14675a02SAndroid Build Coastguard Worker constexpr auto PERMISSION_DENIED = StatusCode::kPermissionDenied;
439*14675a02SAndroid Build Coastguard Worker constexpr auto RESOURCE_EXHAUSTED = StatusCode::kResourceExhausted;
440*14675a02SAndroid Build Coastguard Worker constexpr auto FAILED_PRECONDITION = StatusCode::kFailedPrecondition;
441*14675a02SAndroid Build Coastguard Worker constexpr auto ABORTED = StatusCode::kAborted;
442*14675a02SAndroid Build Coastguard Worker constexpr auto OUT_OF_RANGE = StatusCode::kOutOfRange;
443*14675a02SAndroid Build Coastguard Worker constexpr auto UNIMPLEMENTED = StatusCode::kUnimplemented;
444*14675a02SAndroid Build Coastguard Worker constexpr auto INTERNAL = StatusCode::kInternal;
445*14675a02SAndroid Build Coastguard Worker constexpr auto UNAVAILABLE = StatusCode::kUnavailable;
446*14675a02SAndroid Build Coastguard Worker constexpr auto DATA_LOSS = StatusCode::kDataLoss;
447*14675a02SAndroid Build Coastguard Worker constexpr auto UNAUTHENTICATED = StatusCode::kUnauthenticated;
448*14675a02SAndroid Build Coastguard Worker 
449*14675a02SAndroid Build Coastguard Worker namespace internal {
450*14675a02SAndroid Build Coastguard Worker /** Functions to assist with FCP_RETURN_IF_ERROR() */
AsStatus(const Status & status)451*14675a02SAndroid Build Coastguard Worker inline const Status AsStatus(const Status& status) { return status; }
452*14675a02SAndroid Build Coastguard Worker template <typename T>
AsStatus(const StatusOr<T> & status_or)453*14675a02SAndroid Build Coastguard Worker inline const Status AsStatus(const StatusOr<T>& status_or) {
454*14675a02SAndroid Build Coastguard Worker   return status_or.status();
455*14675a02SAndroid Build Coastguard Worker }
456*14675a02SAndroid Build Coastguard Worker }  // namespace internal
457*14675a02SAndroid Build Coastguard Worker 
458*14675a02SAndroid Build Coastguard Worker /**
459*14675a02SAndroid Build Coastguard Worker  * Macro which allows to check for a Status (or StatusOr) and return from the
460*14675a02SAndroid Build Coastguard Worker  * current method if not OK. Example:
461*14675a02SAndroid Build Coastguard Worker  *
462*14675a02SAndroid Build Coastguard Worker  *     Status DoSomething() {
463*14675a02SAndroid Build Coastguard Worker  *       FCP_RETURN_IF_ERROR(Step1());
464*14675a02SAndroid Build Coastguard Worker  *       FCP_RETURN_IF_ERROR(Step2ReturningStatusOr().status());
465*14675a02SAndroid Build Coastguard Worker  *       return FCP_STATUS(OK);
466*14675a02SAndroid Build Coastguard Worker  *     }
467*14675a02SAndroid Build Coastguard Worker  */
468*14675a02SAndroid Build Coastguard Worker #define FCP_RETURN_IF_ERROR(expr)                             \
469*14675a02SAndroid Build Coastguard Worker   do {                                                        \
470*14675a02SAndroid Build Coastguard Worker     ::fcp::Status __status = ::fcp::internal::AsStatus(expr); \
471*14675a02SAndroid Build Coastguard Worker     if (__status.code() != ::fcp::StatusCode::kOk) {          \
472*14675a02SAndroid Build Coastguard Worker       return (__status);                                      \
473*14675a02SAndroid Build Coastguard Worker     }                                                         \
474*14675a02SAndroid Build Coastguard Worker   } while (false)
475*14675a02SAndroid Build Coastguard Worker 
476*14675a02SAndroid Build Coastguard Worker /**
477*14675a02SAndroid Build Coastguard Worker  * Macro which allows to check for a StatusOr and return it's status if not OK,
478*14675a02SAndroid Build Coastguard Worker  * otherwise assign the value in the StatusOr to variable or declaration. Usage:
479*14675a02SAndroid Build Coastguard Worker  *
480*14675a02SAndroid Build Coastguard Worker  *     StatusOr<bool> DoSomething() {
481*14675a02SAndroid Build Coastguard Worker  *       FCP_ASSIGN_OR_RETURN(auto value, TryComputeSomething());
482*14675a02SAndroid Build Coastguard Worker  *       if (!value) {
483*14675a02SAndroid Build Coastguard Worker  *         FCP_ASSIGN_OR_RETURN(value, TryComputeSomethingElse());
484*14675a02SAndroid Build Coastguard Worker  *       }
485*14675a02SAndroid Build Coastguard Worker  *       return value;
486*14675a02SAndroid Build Coastguard Worker  *     }
487*14675a02SAndroid Build Coastguard Worker  */
488*14675a02SAndroid Build Coastguard Worker #define FCP_ASSIGN_OR_RETURN(lhs, expr) \
489*14675a02SAndroid Build Coastguard Worker   _FCP_ASSIGN_OR_RETURN_1(              \
490*14675a02SAndroid Build Coastguard Worker       _FCP_ASSIGN_OR_RETURN_CONCAT(statusor_for_aor, __LINE__), lhs, expr)
491*14675a02SAndroid Build Coastguard Worker 
492*14675a02SAndroid Build Coastguard Worker #define _FCP_ASSIGN_OR_RETURN_1(statusor, lhs, expr) \
493*14675a02SAndroid Build Coastguard Worker   auto statusor = (expr);                            \
494*14675a02SAndroid Build Coastguard Worker   if (!statusor.ok()) {                              \
495*14675a02SAndroid Build Coastguard Worker     return statusor.status();                        \
496*14675a02SAndroid Build Coastguard Worker   }                                                  \
497*14675a02SAndroid Build Coastguard Worker   lhs = std::move(statusor).value()
498*14675a02SAndroid Build Coastguard Worker 
499*14675a02SAndroid Build Coastguard Worker // See https://goo.gl/x3iba2 for the reason of this construction.
500*14675a02SAndroid Build Coastguard Worker #define _FCP_ASSIGN_OR_RETURN_CONCAT(x, y) \
501*14675a02SAndroid Build Coastguard Worker   _FCP_ASSIGN_OR_RETURN_CONCAT_INNER(x, y)
502*14675a02SAndroid Build Coastguard Worker #define _FCP_ASSIGN_OR_RETURN_CONCAT_INNER(x, y) x##y
503*14675a02SAndroid Build Coastguard Worker 
504*14675a02SAndroid Build Coastguard Worker // Status Implementation Details
505*14675a02SAndroid Build Coastguard Worker // =============================
506*14675a02SAndroid Build Coastguard Worker 
507*14675a02SAndroid Build Coastguard Worker namespace internal {
508*14675a02SAndroid Build Coastguard Worker 
509*14675a02SAndroid Build Coastguard Worker /**
510*14675a02SAndroid Build Coastguard Worker  * Helper class which allows to construct a status with message by streaming
511*14675a02SAndroid Build Coastguard Worker  * into it. Implicitly converts to Status and StatusOr so can be used as a drop
512*14675a02SAndroid Build Coastguard Worker  * in replacement when those types are expected.
513*14675a02SAndroid Build Coastguard Worker  */
514*14675a02SAndroid Build Coastguard Worker class FCP_MUST_USE_RESULT StatusBuilder {
515*14675a02SAndroid Build Coastguard Worker  public:
516*14675a02SAndroid Build Coastguard Worker   /** Construct a StatusBuilder from status code. */
517*14675a02SAndroid Build Coastguard Worker   StatusBuilder(StatusCode code, const char* file, int line);
518*14675a02SAndroid Build Coastguard Worker 
519*14675a02SAndroid Build Coastguard Worker   /**
520*14675a02SAndroid Build Coastguard Worker    * Copy constructor for status builder. Most of the time not needed because of
521*14675a02SAndroid Build Coastguard Worker    * copy ellision. */
522*14675a02SAndroid Build Coastguard Worker   StatusBuilder(StatusBuilder const& other);
523*14675a02SAndroid Build Coastguard Worker 
524*14675a02SAndroid Build Coastguard Worker   /** Return true if the constructed status will be OK. */
ok()525*14675a02SAndroid Build Coastguard Worker   inline bool ok() const { return code_ == OK; }
526*14675a02SAndroid Build Coastguard Worker 
527*14675a02SAndroid Build Coastguard Worker   /** Returns the code of the constructed status. */
code()528*14675a02SAndroid Build Coastguard Worker   inline StatusCode code() const { return code_; }
529*14675a02SAndroid Build Coastguard Worker 
530*14675a02SAndroid Build Coastguard Worker   /** Stream into status message of this builder. */
531*14675a02SAndroid Build Coastguard Worker   template <typename T>
532*14675a02SAndroid Build Coastguard Worker   StatusBuilder& operator<<(T x) {
533*14675a02SAndroid Build Coastguard Worker     message_ << x;
534*14675a02SAndroid Build Coastguard Worker     return *this;
535*14675a02SAndroid Build Coastguard Worker   }
536*14675a02SAndroid Build Coastguard Worker 
537*14675a02SAndroid Build Coastguard Worker   /** Mark this builder to emit a log message when the result is constructed. */
LogInfo()538*14675a02SAndroid Build Coastguard Worker   inline StatusBuilder& LogInfo() {
539*14675a02SAndroid Build Coastguard Worker     log_severity_ = LogSeverity::kInfo;
540*14675a02SAndroid Build Coastguard Worker     return *this;
541*14675a02SAndroid Build Coastguard Worker   }
542*14675a02SAndroid Build Coastguard Worker 
543*14675a02SAndroid Build Coastguard Worker   /** Mark this builder to emit a log message when the result is constructed. */
LogWarning()544*14675a02SAndroid Build Coastguard Worker   inline StatusBuilder& LogWarning() {
545*14675a02SAndroid Build Coastguard Worker     log_severity_ = LogSeverity::kWarning;
546*14675a02SAndroid Build Coastguard Worker     return *this;
547*14675a02SAndroid Build Coastguard Worker   }
548*14675a02SAndroid Build Coastguard Worker 
549*14675a02SAndroid Build Coastguard Worker   /** Mark this builder to emit a log message when the result is constructed. */
LogError()550*14675a02SAndroid Build Coastguard Worker   inline StatusBuilder& LogError() {
551*14675a02SAndroid Build Coastguard Worker     log_severity_ = LogSeverity::kError;
552*14675a02SAndroid Build Coastguard Worker     return *this;
553*14675a02SAndroid Build Coastguard Worker   }
554*14675a02SAndroid Build Coastguard Worker 
555*14675a02SAndroid Build Coastguard Worker   /** Mark this builder to emit a log message when the result is constructed. */
LogFatal()556*14675a02SAndroid Build Coastguard Worker   inline StatusBuilder& LogFatal() {
557*14675a02SAndroid Build Coastguard Worker     log_severity_ = LogSeverity::kFatal;
558*14675a02SAndroid Build Coastguard Worker     return *this;
559*14675a02SAndroid Build Coastguard Worker   }
560*14675a02SAndroid Build Coastguard Worker 
561*14675a02SAndroid Build Coastguard Worker   /** Implicit conversion to Status. */
562*14675a02SAndroid Build Coastguard Worker   operator Status();  // NOLINT
563*14675a02SAndroid Build Coastguard Worker 
564*14675a02SAndroid Build Coastguard Worker   /** Implicit conversion to StatusOr. */
565*14675a02SAndroid Build Coastguard Worker   template <typename T>
566*14675a02SAndroid Build Coastguard Worker   inline operator StatusOr<T>() {  // NOLINT
567*14675a02SAndroid Build Coastguard Worker     return StatusOr<T>(static_cast<Status>(*this));
568*14675a02SAndroid Build Coastguard Worker   }
569*14675a02SAndroid Build Coastguard Worker 
570*14675a02SAndroid Build Coastguard Worker  private:
571*14675a02SAndroid Build Coastguard Worker   static constexpr LogSeverity kNoLog = static_cast<LogSeverity>(-1);
572*14675a02SAndroid Build Coastguard Worker   const char* const file_;
573*14675a02SAndroid Build Coastguard Worker   const int line_;
574*14675a02SAndroid Build Coastguard Worker   const StatusCode code_;
575*14675a02SAndroid Build Coastguard Worker   StringStream message_;
576*14675a02SAndroid Build Coastguard Worker   LogSeverity log_severity_ = fcp_debug ? LogSeverity::kInfo : kNoLog;
577*14675a02SAndroid Build Coastguard Worker };
578*14675a02SAndroid Build Coastguard Worker 
MakeStatusBuilder(StatusCode code,const char * file,int line)579*14675a02SAndroid Build Coastguard Worker inline StatusBuilder MakeStatusBuilder(StatusCode code, const char* file,
580*14675a02SAndroid Build Coastguard Worker                                        int line) {
581*14675a02SAndroid Build Coastguard Worker   return StatusBuilder(code, file, line);
582*14675a02SAndroid Build Coastguard Worker }
583*14675a02SAndroid Build Coastguard Worker 
584*14675a02SAndroid Build Coastguard Worker }  // namespace internal
585*14675a02SAndroid Build Coastguard Worker }  // namespace fcp
586*14675a02SAndroid Build Coastguard Worker 
587*14675a02SAndroid Build Coastguard Worker #endif  // FCP_BASE_MONITORING_H_
588