Google Cloud C++ Client 2.10.1
C++ Client Library for Google Cloud Platform
Loading...
Searching...
No Matches
status.h
1// Copyright 2018 Google LLC
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#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STATUS_H
16#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STATUS_H
17
18#include "google/cloud/version.h"
19#include "absl/types/optional.h"
20#include <iostream>
21#include <memory>
22#include <string>
23#include <unordered_map>
24
25namespace google {
26namespace cloud {
28
29/**
30 * Well-known status codes with `grpc::StatusCode`-compatible values.
31 *
32 * The semantics of these values are documented in:
33 * https://grpc.io/grpc/cpp/classgrpc_1_1_status.html
34 */
35enum class StatusCode {
36 /// Not an error; returned on success.
37 kOk = 0,
38
39 /// `kCancelled` (gRPC code `CANCELLED`) indicates the operation was
40 /// cancelled, typically by the caller.
41 kCancelled = 1,
42
43 /// `kUnknown` (gRPC code `UNKNOWN`) indicates an unknown error occurred.
44 ///
45 /// In general, more specific errors should be raised, if possible. Errors
46 /// raised by APIs that do not return enough error information may be
47 /// converted to this error.
48 kUnknown = 2,
49
50 /// `kInvalidArgument` (gRPC code `INVALID_ARGUMENT`) indicates the caller
51 /// specified an invalid argument, such as a malformed filename.
52 ///
53 /// Note that use of such errors should be narrowly limited to indicate the
54 /// invalid nature of the arguments themselves. Errors with validly formed
55 /// arguments that may cause errors with the state of the receiving system
56 /// should be denoted with `kFailedPrecondition` instead.
58
59 /// `kDeadlineExceeded` (gRPC code `DEADLINE_EXCEEDED`) indicates a deadline
60 /// expired before the operation could complete.
61 ///
62 /// For operations that may change state within a system, this error may be
63 /// returned even if the operation has completed successfully. For example, a
64 /// successful response from a server could have been delayed long enough for
65 /// the deadline to expire.
67
68 /// `kNotFound` (gRPC code `NOT_FOUND`) indicates some requested entity (such
69 /// as a file or directory) was not found.
70 ///
71 /// `kNotFound` is useful if a request should be denied for an entire class of
72 /// users, such as during a gradual feature rollout or undocumented allow
73 /// list.
74 /// If a request should be denied for specific sets of users, such as through
75 /// user-based access control, use `kPermissionDenied` instead.
76 kNotFound = 5,
77
78 /// `kAlreadyExists (gRPC code `ALREADY_EXISTS`) indicates that the entity a
79 /// caller attempted to create (such as a file or directory) is already
80 /// present.
82
83 /// `kPermissionDenied` (gRPC code `PERMISSION_DENIED`) indicates that the
84 /// caller does not have permission to execute the specified operation.
85 ///
86 /// Note that this error is different than an error due to an
87 /// *un*authenticated caller. This error code does not imply the request is
88 /// valid or the requested entity exists or satisfies any other
89 /// pre-conditions.
90 ///
91 /// `kPermissionDenied` must not be used for rejections caused by exhausting
92 /// some resource. Instead, use `kResourceExhausted` for those errors.
93 /// `kPermissionDenied` must not be used if the caller cannot be identified.
94 /// Instead, use `kUnauthenticated` for those errors.
96
97 /// `kResourceExhausted` (gRPC code `RESOURCE_EXHAUSTED`) indicates some
98 /// resource has been exhausted.
99 ///
100 /// Examples include a per-user quota, or the entire file system being out of
101 /// space.
103
104 /// `kFailedPrecondition` (gRPC code `FAILED_PRECONDITION`) indicates that the
105 /// operation was rejected because the system is not in a state required for
106 /// the operation's execution.
107 ///
108 /// For example, a directory to be deleted may be non-empty, a "rmdir"
109 /// operation is applied to a non-directory, etc.
110 ///
111 /// Some guidelines that may help a service implementer in deciding between
112 /// `kFailedPrecondition`, `kAborted`, and `kUnavailable`:
113 ///
114 /// 1. Use `kUnavailable` if the client can retry just the failing call.
115 /// 2. Use `kAborted` if the client should retry at a higher transaction
116 /// level (such as when a client-specified test-and-set fails, indicating
117 /// the client should restart a read-modify-write sequence).
118 /// 3. Use `kFailedPrecondition` if the client should not retry until the
119 /// system state has been explicitly fixed. For example, if a "rmdir" fails
120 /// because the directory is non-empty, `kFailedPrecondition` should be
121 /// returned since the client should not retry unless the files are deleted
122 /// from the directory.
124
125 /// `kAborted` (gRPC code `ABORTED`) indicates the operation was aborted.
126 ///
127 /// This is typically due to a concurrency issue such as a sequencer check
128 /// failure or a failed transaction.
129 ///
130 /// See the guidelines above for deciding between `kFailedPrecondition`,
131 /// `kAborted`, and `kUnavailable`.
132 kAborted = 10,
133
134 /// `kOutOfRange` (gRPC code `OUT_OF_RANGE`) indicates the operation was
135 /// attempted past the valid range, such as seeking or reading past an
136 /// end-of-file.
137 ///
138 /// Unlike `kInvalidArgument`, this error indicates a problem that may
139 /// be fixed if the system state changes. For example, a 32-bit file
140 /// system will generate `kInvalidArgument` if asked to read at an
141 /// offset that is not in the range [0,2^32-1], but it will generate
142 /// `kOutOfRange` if asked to read from an offset past the current
143 /// file size.
144 ///
145 /// There is a fair bit of overlap between `kFailedPrecondition` and
146 /// `kOutOfRange`. We recommend using `kOutOfRange` (the more specific
147 /// error) when it applies so that callers who are iterating through
148 /// a space can easily look for an `kOutOfRange` error to detect when
149 /// they are done.
150 kOutOfRange = 11,
151
152 /// `kUnimplemented` (gRPC code `UNIMPLEMENTED`) indicates the operation is
153 /// not implemented or supported in this service.
154 ///
155 /// In this case, the operation should not be re-attempted.
156 kUnimplemented = 12,
157
158 /// `kInternal` (gRPC code `INTERNAL`) indicates an internal error has
159 /// occurred and some invariants expected by the underlying system have not
160 /// been satisfied.
161 ///
162 /// While this error code is reserved for serious errors, some services return
163 /// this error under overload conditions.
164 kInternal = 13,
165
166 /// `kUnavailable` (gRPC code `UNAVAILABLE`) indicates the service is
167 /// currently unavailable and that this is most likely a transient condition.
168 ///
169 /// An error such as this can be corrected by retrying with a backoff scheme.
170 /// Note that it is not always safe to retry non-idempotent operations.
171 ///
172 /// See the guidelines above for deciding between `kFailedPrecondition`,
173 /// `kAborted`, and `kUnavailable`.
174 kUnavailable = 14,
175
176 /// `kDataLoss` (gRPC code `DATA_LOSS`) indicates that unrecoverable data loss
177 /// or corruption has occurred.
178 ///
179 /// As this error is serious, proper alerting should be attached to errors
180 /// such as this.
181 kDataLoss = 15,
182
183 /// `kUnauthenticated` (gRPC code `UNAUTHENTICATED`) indicates that the
184 /// request does not have valid authentication credentials for the operation.
185 ///
186 /// Correct the authentication and try again.
187 kUnauthenticated = 16,
188};
189
190/// Convert @p code to a human readable string.
191std::string StatusCodeToString(StatusCode code);
192
193/// Integration with `std::iostreams`.
194std::ostream& operator<<(std::ostream& os, StatusCode code);
195
196class Status;
197namespace internal {
198void SetPayload(Status&, std::string key, std::string payload);
199absl::optional<std::string> GetPayload(Status const&, std::string const& key);
200} // namespace internal
201
202/**
203 * Describes the cause of the error with structured details.
204 *
205 * @see https://cloud.google.com/apis/design/errors#error_info
206 */
207class ErrorInfo {
208 public:
209 /**
210 * Default constructor.
211 *
212 * Post-condition: the `reason()`, `domain()`, and `metadata()` fields are
213 * empty.
214 */
215 ErrorInfo() = default;
216
217 /**
218 * Constructor.
219 *
220 * @param reason initializes the `reason()` value.
221 * @param domain initializes the `domain()` value.
222 * @param metadata initializes the `metadata()` value.
223 */
224 explicit ErrorInfo(std::string reason, std::string domain,
225 std::unordered_map<std::string, std::string> metadata)
226 : reason_(std::move(reason)),
227 domain_(std::move(domain)),
228 metadata_(std::move(metadata)) {}
229
230 /**
231 * The reason of the error.
232 *
233 * This is a constant value that identifies the proximate cause of the error.
234 * Error reasons are unique within a particular domain of errors. This should
235 * be at most 63 characters and match a regular expression of
236 * `[A-Z][A-Z0-9_]+[A-Z0-9]`, which represents UPPER_SNAKE_CASE.
237 */
238 std::string const& reason() const { return reason_; }
239
240 /**
241 * The logical grouping to which the "reason" belongs.
242 *
243 * The error domain is typically the registered service name of the tool or
244 * product that generates the error. Example: "pubsub.googleapis.com". If the
245 * error is generated by some common infrastructure, the error domain must be
246 * a globally unique value that identifies the infrastructure. For Google API
247 * infrastructure, the error domain is "googleapis.com".
248 *
249 * For errors generated by the C++ client libraries the domain is
250 * `gcloud-cpp`.
251 */
252 std::string const& domain() const { return domain_; }
253
254 /**
255 * Additional structured details about this error.
256 *
257 * Keys should match the regular expression `[a-zA-Z0-9-_]` and be limited
258 * to 64 characters in length.
259 *
260 * When identifying the current value of an exceeded limit, the units should
261 * be contained in the key, not the value. For example, if the client exceeds
262 * the number of instances that can be created in a single (batch) request
263 * return `{"instanceLimitPerRequest": "100"}` rather than
264 * `{"instanceLimit": "100/request"}`.
265 */
266 std::unordered_map<std::string, std::string> const& metadata() const {
267 return metadata_;
268 }
269
270 friend bool operator==(ErrorInfo const&, ErrorInfo const&);
271 friend bool operator!=(ErrorInfo const&, ErrorInfo const&);
272
273 private:
274 std::string reason_;
275 std::string domain_;
276 std::unordered_map<std::string, std::string> metadata_;
277};
278
279/**
280 * Represents success or an error with info about the error.
281 *
282 * This class is typically used to indicate whether or not a function or other
283 * operation completed successfully. Success is indicated by an "OK" status. OK
284 * statuses will have `.code() == StatusCode::kOk` and `.ok() == true`, with
285 * all other properties having empty values. All OK statuses are equal. Any
286 * non-OK `Status` is considered an error. Users can inspect the error using
287 * the member functions, or they can simply stream the `Status` object, and it
288 * will print itself in some human readable way (the streamed format may change
289 * over time and you should *not* depend on the specific format of a streamed
290 * `Status` object remaining unchanged).
291 *
292 * This is a regular value type that can be copied, moved, compared for
293 * equality, and streamed.
294 */
295class Status {
296 public:
297 /// Default constructor, initializes to `StatusCode::kOk`.
298 Status();
299 /// Destructor.
300 ~Status();
301 ///@{
302 /**
303 * @name Copy construction and assignment.
304 */
305 Status(Status const&);
306 Status& operator=(Status const&);
307 ///@}
308 ///@{
309 /**
310 * @name Move construction and assignment.
311 */
312 Status(Status&&) noexcept;
313 Status& operator=(Status&&) noexcept;
314 ///@}
315
316 /**
317 * Construct from a status code, message and (optional) error info.
318 *
319 * @param code the status code for the new `Status`.
320 * @param message the message for the new `Status`, ignored if @p code is
321 * `StatusCode::kOk`.
322 * @param info the `ErrorInfo` for the new `Status`, ignored if @p code is
323 * `SStatusCode::kOk`.
324 */
325 explicit Status(StatusCode code, std::string message, ErrorInfo info = {});
326
327 /// Returns true if the status code is `StatusCode::kOk`.
328 bool ok() const { return !impl_; }
329
330 /// Returns the status code.
331 StatusCode code() const;
332
333 /**
334 * Returns the message associated with the status.
335 *
336 * This is always empty if `code()` is `StatusCode::kOk`.
337 */
338 std::string const& message() const;
339
340 /**
341 * Returns the additional error info associated with the status.
342 *
343 * This is always a default-constructed error info if `code()` is
344 * `StatusCode::kOk`.
345 */
346 ErrorInfo const& error_info() const;
347
348 friend inline bool operator==(Status const& a, Status const& b) {
349 return (a.ok() && b.ok()) || Equals(a, b);
350 }
351 friend inline bool operator!=(Status const& a, Status const& b) {
352 return !(a == b);
353 }
354
355 private:
356 static bool Equals(Status const& a, Status const& b);
357 friend void internal::SetPayload(Status&, std::string, std::string);
358 friend absl::optional<std::string> internal::GetPayload(Status const&,
359 std::string const&);
360
361 class Impl;
362 // A null `impl_` is an OK status. Only non-OK Statuses allocate an Impl.
363 std::unique_ptr<Impl> impl_;
364};
365
366/**
367 * Stream @p s to @p os.
368 *
369 * This in intended for logging and troubleshooting. Applications should not
370 * depend on the format of this output.
371 */
372std::ostream& operator<<(std::ostream& os, Status const& s);
373
374/**
375 * A runtime error that wraps a `google::cloud::Status`.
376 */
377class RuntimeStatusError : public std::runtime_error {
378 public:
379 /// Constructor from a `Status`.
380 explicit RuntimeStatusError(Status status);
381
382 /// Returns the original status.
383 Status const& status() const { return status_; }
384
385 private:
386 Status status_;
387};
388
390} // namespace cloud
391} // namespace google
392
393#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STATUS_H
Describes the cause of the error with structured details.
Definition: status.h:207
friend bool operator!=(ErrorInfo const &, ErrorInfo const &)
ErrorInfo(std::string reason, std::string domain, std::unordered_map< std::string, std::string > metadata)
Constructor.
Definition: status.h:224
friend bool operator==(ErrorInfo const &, ErrorInfo const &)
ErrorInfo()=default
Default constructor.
std::unordered_map< std::string, std::string > const & metadata() const
Additional structured details about this error.
Definition: status.h:266
std::string const & domain() const
The logical grouping to which the "reason" belongs.
Definition: status.h:252
std::string const & reason() const
The reason of the error.
Definition: status.h:238
A runtime error that wraps a google::cloud::Status.
Definition: status.h:377
RuntimeStatusError(Status status)
Constructor from a Status.
Status const & status() const
Returns the original status.
Definition: status.h:383
Represents success or an error with info about the error.
Definition: status.h:295
ErrorInfo const & error_info() const
Returns the additional error info associated with the status.
bool ok() const
Returns true if the status code is StatusCode::kOk.
Definition: status.h:328
Status & operator=(Status &&) noexcept
friend bool operator!=(Status const &a, Status const &b)
Definition: status.h:351
Status & operator=(Status const &)
~Status()
Destructor.
friend bool operator==(Status const &a, Status const &b)
Definition: status.h:348
Status(Status const &)
std::string const & message() const
Returns the message associated with the status.
StatusCode code() const
Returns the status code.
Status()
Default constructor, initializes to StatusCode::kOk.
Status(StatusCode code, std::string message, ErrorInfo info={})
Construct from a status code, message and (optional) error info.
Status(Status &&) noexcept
Contains all the Google Cloud C++ Library APIs.
Definition: async_operation.h:23
StatusCode
Well-known status codes with grpc::StatusCode-compatible values.
Definition: status.h:35
@ kFailedPrecondition
kFailedPrecondition (gRPC code FAILED_PRECONDITION) indicates that the operation was rejected because...
@ kUnknown
kUnknown (gRPC code UNKNOWN) indicates an unknown error occurred.
@ kDataLoss
kDataLoss (gRPC code DATA_LOSS) indicates that unrecoverable data loss or corruption has occurred.
@ kDeadlineExceeded
kDeadlineExceeded (gRPC code DEADLINE_EXCEEDED) indicates a deadline expired before the operation cou...
@ kResourceExhausted
kResourceExhausted (gRPC code RESOURCE_EXHAUSTED) indicates some resource has been exhausted.
@ kInvalidArgument
kInvalidArgument (gRPC code INVALID_ARGUMENT) indicates the caller specified an invalid argument,...
@ kUnavailable
kUnavailable (gRPC code UNAVAILABLE) indicates the service is currently unavailable and that this is ...
@ kUnimplemented
kUnimplemented (gRPC code UNIMPLEMENTED) indicates the operation is not implemented or supported in t...
@ kInternal
kInternal (gRPC code INTERNAL) indicates an internal error has occurred and some invariants expected ...
@ kCancelled
kCancelled (gRPC code CANCELLED) indicates the operation was cancelled, typically by the caller.
@ kAlreadyExists
kAlreadyExists (gRPC codeALREADY_EXISTS`) indicates that the entity a caller attempted to create (suc...
@ kNotFound
kNotFound (gRPC code NOT_FOUND) indicates some requested entity (such as a file or directory) was not...
@ kAborted
kAborted (gRPC code ABORTED) indicates the operation was aborted.
@ kUnauthenticated
kUnauthenticated (gRPC code UNAUTHENTICATED) indicates that the request does not have valid authentic...
@ kPermissionDenied
kPermissionDenied (gRPC code PERMISSION_DENIED) indicates that the caller does not have permission to...
@ kOk
Not an error; returned on success.
@ kOutOfRange
kOutOfRange (gRPC code OUT_OF_RANGE) indicates the operation was attempted past the valid range,...
std::string StatusCodeToString(StatusCode code)
Convert code to a human readable string.
Definition: async_operation.h:22
#define GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
Definition: version.h:45
#define GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
Definition: version.h:43