ErrorDetails.swift 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * Copyright 2024, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. public import SwiftProtobuf
  17. /// Common details which can be used to supplement ``GoogleRPCStatus``.
  18. ///
  19. /// This represents the set of common error types suggested by [Google AIP-193](https://google.aip.dev/193).
  20. /// These types are derived from and will serialize to the those represented in
  21. /// [google/rpc/error_details.proto](https://github.com/googleapis/googleapis/blob/3597f7db2191c00b100400991ef96e52d62f5841/google/rpc/error_details.proto).
  22. ///
  23. /// This type also allows you to provide wrap your own error details up as an "Any"
  24. /// protobuf (`Google_Protobuf_Any`).
  25. public struct ErrorDetails: Sendable, Hashable {
  26. enum Wrapped: Sendable, Hashable {
  27. case errorInfo(ErrorInfo)
  28. case retryInfo(RetryInfo)
  29. case debugInfo(DebugInfo)
  30. case quotaFailure(QuotaFailure)
  31. case preconditionFailure(PreconditionFailure)
  32. case badRequest(BadRequest)
  33. case requestInfo(RequestInfo)
  34. case resourceInfo(ResourceInfo)
  35. case help(Help)
  36. case localizedMessage(LocalizedMessage)
  37. case any(Google_Protobuf_Any)
  38. }
  39. private(set) var wrapped: Wrapped
  40. private init(_ wrapped: Wrapped) {
  41. self.wrapped = wrapped
  42. }
  43. /// Create a new detail wrapping a `Google_Protobuf_Any`.
  44. public static func any(_ any: Google_Protobuf_Any) -> Self {
  45. Self(.any(any))
  46. }
  47. /// Create a new detail wrapping an ``ErrorInfo-swift.struct``.
  48. public static func errorInfo(_ info: ErrorInfo) -> Self {
  49. Self(.errorInfo(info))
  50. }
  51. /// Create a ``ErrorInfo-swift.struct`` detail.
  52. ///
  53. /// - Parameters:
  54. /// - reason: The reason of the error.
  55. /// - domain: The logical grouping to which the "reason" belongs.
  56. /// - metadata: Additional structured details about this error.
  57. public static func errorInfo(
  58. reason: String,
  59. domain: String,
  60. metadata: [String: String] = [:]
  61. ) -> Self {
  62. Self.errorInfo(ErrorInfo(reason: reason, domain: domain, metadata: metadata))
  63. }
  64. /// Create a new detail wrapping a ``RetryInfo-swift.struct``.
  65. public static func retryInfo(_ info: RetryInfo) -> Self {
  66. Self(.retryInfo(info))
  67. }
  68. /// Create a ``RetryInfo-swift.struct`` detail.
  69. ///
  70. /// - Parameter delay: Amount of time clients should wait before retrying this request.
  71. public static func retryInfo(delay: Duration) -> Self {
  72. Self.retryInfo(RetryInfo(delay: delay))
  73. }
  74. /// Create a new detail wrapping a ``DebugInfo-swift.struct``.
  75. public static func debugInfo(_ info: DebugInfo) -> Self {
  76. Self(.debugInfo(info))
  77. }
  78. /// Create a ``DebugInfo-swift.struct`` detail.
  79. ///
  80. /// - Parameters:
  81. /// - stack: The stack trace entries indicating where the error occurred.
  82. /// - detail: Additional debugging information provided by the server.
  83. public static func debugInfo(stack: [String], detail: String) -> Self {
  84. Self.debugInfo(DebugInfo(stack: stack, detail: detail))
  85. }
  86. /// Create a new detail wrapping a ``QuotaFailure-swift.struct``.
  87. public static func quotaFailure(_ info: QuotaFailure) -> Self {
  88. Self(.quotaFailure(info))
  89. }
  90. /// Create a ``QuotaFailure-swift.struct`` detail.
  91. ///
  92. /// - Parameter violations: Describes all quota violations.
  93. public static func quotaFailure(violations: [QuotaFailure.Violation]) -> Self {
  94. Self.quotaFailure(QuotaFailure(violations: violations))
  95. }
  96. /// Create a new detail wrapping a ``PreconditionFailure-swift.struct``.
  97. public static func preconditionFailure(_ info: PreconditionFailure) -> Self {
  98. Self(.preconditionFailure(info))
  99. }
  100. /// Create a ``PreconditionFailure-swift.struct`` detail.
  101. ///
  102. /// - Parameter violations: Describes all precondition violations.
  103. public static func preconditionFailure(violations: [PreconditionFailure.Violation]) -> Self {
  104. Self.preconditionFailure(PreconditionFailure(violations: violations))
  105. }
  106. /// Create a new detail wrapping a ``BadRequest-swift.struct``.
  107. public static func badRequest(_ info: BadRequest) -> Self {
  108. Self(.badRequest(info))
  109. }
  110. /// Create a ``BadRequest-swift.struct`` detail.
  111. ///
  112. /// - Parameter violations: Describes all request violations.
  113. public static func badRequest(violations: [BadRequest.FieldViolation]) -> Self {
  114. Self.badRequest(BadRequest(violations: violations))
  115. }
  116. /// Create a new detail wrapping a ``RequestInfo-swift.struct``.
  117. public static func requestInfo(_ info: RequestInfo) -> Self {
  118. Self(.requestInfo(info))
  119. }
  120. /// Create a ``RequestInfo-swift.struct`` detail.
  121. ///
  122. /// - Parameters:
  123. /// - requestID: An opaque string that should only be interpreted by the service generating
  124. /// it. For example, it can be used to identify requests in the service's logs.
  125. /// - servingData: Any data that was used to serve this request. For example, an encrypted
  126. /// stack trace that can be sent back to the service provider for debugging.
  127. public static func requestInfo(requestID: String, servingData: String) -> Self {
  128. Self.requestInfo(RequestInfo(requestID: requestID, servingData: servingData))
  129. }
  130. /// Create a new detail wrapping a ``ResourceInfo-swift.struct``.
  131. public static func resourceInfo(_ info: ResourceInfo) -> Self {
  132. Self(.resourceInfo(info))
  133. }
  134. /// Create a ``ResourceInfo-swift.struct`` detail.
  135. ///
  136. /// - Parameters:
  137. /// - type: The type of resource being accessed, e,.g. "sql table", "file" or type URL of the
  138. /// resource.
  139. /// - name: The name of the resource being accessed.
  140. /// - errorDescription: Describes the error encountered when accessing this resource.
  141. /// - owner: The owner of the resource.
  142. public static func resourceInfo(
  143. type: String,
  144. name: String,
  145. errorDescription: String,
  146. owner: String = ""
  147. ) -> Self {
  148. Self.resourceInfo(
  149. ResourceInfo(type: type, name: name, errorDescription: errorDescription, owner: owner)
  150. )
  151. }
  152. /// Create a ``Help-swift.struct`` detail.
  153. public static func help(_ info: Help) -> Self {
  154. Self(.help(info))
  155. }
  156. /// Create a ``Help-swift.struct`` detail.
  157. ///
  158. /// - Parameter links: URL(s) pointing to additional information on handling the current error.
  159. public static func help(links: [Help.Link]) -> Self {
  160. Self.help(Help(links: links))
  161. }
  162. /// Create a ``LocalizedMessage-swift.struct`` detail.
  163. public static func localizedMessage(_ info: LocalizedMessage) -> Self {
  164. Self(.localizedMessage(info))
  165. }
  166. /// Create a ``Help-swift.struct`` detail.
  167. ///
  168. /// - Parameters:
  169. /// - locale: The locale used.
  170. /// - message: Localized error message.
  171. public static func localizedMessage(locale: String, message: String) -> Self {
  172. Self.localizedMessage(LocalizedMessage(locale: locale, message: message))
  173. }
  174. }
  175. extension ErrorDetails {
  176. /// Returns error info if set.
  177. public var errorInfo: ErrorInfo? {
  178. switch self.wrapped {
  179. case .errorInfo(let info):
  180. return info
  181. default:
  182. return nil
  183. }
  184. }
  185. /// Returns retry info if set.
  186. public var retryInfo: RetryInfo? {
  187. switch self.wrapped {
  188. case .retryInfo(let info):
  189. return info
  190. default:
  191. return nil
  192. }
  193. }
  194. /// Returns debug info if set.
  195. public var debugInfo: DebugInfo? {
  196. switch self.wrapped {
  197. case .debugInfo(let info):
  198. return info
  199. default:
  200. return nil
  201. }
  202. }
  203. /// Returns a quota failure if set.
  204. public var quotaFailure: QuotaFailure? {
  205. switch self.wrapped {
  206. case .quotaFailure(let info):
  207. return info
  208. default:
  209. return nil
  210. }
  211. }
  212. /// Returns a precondition failure if set.
  213. public var preconditionFailure: PreconditionFailure? {
  214. switch self.wrapped {
  215. case .preconditionFailure(let info):
  216. return info
  217. default:
  218. return nil
  219. }
  220. }
  221. /// Returns bad request details if set.
  222. public var badRequest: BadRequest? {
  223. switch self.wrapped {
  224. case .badRequest(let info):
  225. return info
  226. default:
  227. return nil
  228. }
  229. }
  230. /// Returns request info if set.
  231. public var requestInfo: RequestInfo? {
  232. switch self.wrapped {
  233. case .requestInfo(let info):
  234. return info
  235. default:
  236. return nil
  237. }
  238. }
  239. /// Returns resource info if set.
  240. public var resourceInfo: ResourceInfo? {
  241. switch self.wrapped {
  242. case .resourceInfo(let info):
  243. return info
  244. default:
  245. return nil
  246. }
  247. }
  248. /// Returns help if set.
  249. public var help: Help? {
  250. switch self.wrapped {
  251. case .help(let info):
  252. return info
  253. default:
  254. return nil
  255. }
  256. }
  257. /// Returns a localized message if set.
  258. public var localizedMessage: LocalizedMessage? {
  259. switch self.wrapped {
  260. case .localizedMessage(let info):
  261. return info
  262. default:
  263. return nil
  264. }
  265. }
  266. /// Returns `Google_Protobuf_Any` if applicable.
  267. ///
  268. /// - Important: Calling this **doesn't** encode a detail of another type into a `Google_Protobuf_Any`.
  269. public var any: Google_Protobuf_Any? {
  270. switch self.wrapped {
  271. case .any(let any):
  272. return any
  273. default:
  274. return nil
  275. }
  276. }
  277. }