Skip to content

Commit 9ac928d

Browse files
Update error_details.proto to expose latest upstream fields (#81)
## Motivation The upstream Google proto file `error_details.proto` has been updated (see: https://github.com/googleapis/googleapis/blob/2e1c38ddaa402303b9c1381f5f9ba5a9ced4a51c/google/rpc/error_details.proto): - `QuotaFailure` message: - Added fields: `api_service`, `quota_metric`, `quota_id`, `quota_dimensions`, `quota_value` and `future_quota_value` - `BadRequest.FieldViolation` message: - Added fields: `reason` and `localized_message` ## Modifications Update the google proto files and generates the stubs using the provided scripts `dev/protos/fetch.sh` and `dev/protos/generate.sh`. ## Result Library users can now access the newly added fields in `error_details.proto`.
1 parent df9af05 commit 9ac928d

File tree

9 files changed

+423
-20
lines changed

9 files changed

+423
-20
lines changed

Sources/GRPCProtobuf/Errors/ErrorDetails+CustomStringConvertible.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ extension ErrorDetails.DebugInfo: CustomStringConvertible {
6464
@available(gRPCSwiftProtobuf 2.0, *)
6565
extension ErrorDetails.QuotaFailure.Violation: CustomStringConvertible {
6666
public var description: String {
67-
"\(Self.self)(subject: \"\(self.subject)\", violationDescription: \"\(self.violationDescription)\")"
67+
"\(Self.self)(subject: \"\(self.subject)\", violationDescription: \"\(self.violationDescription)\", apiService: \"\(self.apiService)\", quotaMetric: \"\(self.quotaMetric)\", quotaID: \"\(self.quotaID)\", quotaDimensions: [\(self.quotaDimensions.map({ "\"\($0)\": \"\($1)\"" }).joined(separator: ", "))], quotaValue: \(self.quotaValue), futureQuotaValue: \(self.futureQuotaValue.map({ String(describing: $0) }) ?? "nil"))"
6868
}
6969
}
7070

@@ -78,7 +78,7 @@ extension ErrorDetails.PreconditionFailure.Violation: CustomStringConvertible {
7878
@available(gRPCSwiftProtobuf 2.0, *)
7979
extension ErrorDetails.BadRequest.FieldViolation: CustomStringConvertible {
8080
public var description: String {
81-
"\(Self.self)(field: \"\(self.field)\", violationDescription: \"\(self.violationDescription)\")"
81+
"\(Self.self)(field: \"\(self.field)\", violationDescription: \"\(self.violationDescription)\", reason: \"\(self.reason)\", localizedMessage: \(self.localizedMessage.map({ String(describing: $0) }) ?? "nil"))"
8282
}
8383
}
8484

Sources/GRPCProtobuf/Errors/ErrorDetails+Types.swift

Lines changed: 161 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,14 +205,123 @@ extension ErrorDetails {
205205
/// exceeded".
206206
public var violationDescription: String
207207

208-
public init(subject: String, description: String) {
208+
/// The API Service from which the `QuotaFailure.Violation` orginates. In
209+
/// some cases, Quota issues originate from an API Service other than the one
210+
/// that was called. In other words, a dependency of the called API Service
211+
/// could be the cause of the `QuotaFailure`, and this field would have the
212+
/// dependency API service name.
213+
///
214+
/// For example, if the called API is Kubernetes Engine API
215+
/// (container.googleapis.com), and a quota violation occurs in the
216+
/// Kubernetes Engine API itself, this field would be
217+
/// "container.googleapis.com". On the other hand, if the quota violation
218+
/// occurs when the Kubernetes Engine API creates VMs in the Compute Engine
219+
/// API (compute.googleapis.com), this field would be
220+
/// "compute.googleapis.com".
221+
@available(gRPCSwiftProtobuf 2.1, *)
222+
public var apiService: String
223+
224+
/// The metric of the violated quota. A quota metric is a named counter to
225+
/// measure usage, such as API requests or CPUs. When an activity occurs in a
226+
/// service, such as Virtual Machine allocation, one or more quota metrics
227+
/// may be affected.
228+
///
229+
/// For example, "compute.googleapis.com/cpus_per_vm_family",
230+
/// "storage.googleapis.com/internet_egress_bandwidth".
231+
@available(gRPCSwiftProtobuf 2.1, *)
232+
public var quotaMetric: String
233+
234+
/// The id of the violated quota. Also know as "limit name", this is the
235+
/// unique identifier of a quota in the context of an API service.
236+
///
237+
/// For example, "CPUS-PER-VM-FAMILY-per-project-region".
238+
@available(gRPCSwiftProtobuf 2.1, *)
239+
public var quotaID: String
240+
241+
/// The dimensions of the violated quota. Every non-global quota is enforced
242+
/// on a set of dimensions. While quota metric defines what to count, the
243+
/// dimensions specify for what aspects the counter should be increased.
244+
///
245+
/// For example, the quota "CPUs per region per VM family" enforces a limit
246+
/// on the metric "compute.googleapis.com/cpus_per_vm_family" on dimensions
247+
/// "region" and "vm_family". And if the violation occurred in region
248+
/// "us-central1" and for VM family "n1", the quota_dimensions would be,
249+
///
250+
/// {
251+
/// "region": "us-central1",
252+
/// "vm_family": "n1",
253+
/// }
254+
///
255+
/// When a quota is enforced globally, the quota_dimensions would always be
256+
/// empty.
257+
@available(gRPCSwiftProtobuf 2.1, *)
258+
public var quotaDimensions: [String: String]
259+
260+
/// The enforced quota value at the time of the `QuotaFailure`.
261+
///
262+
/// For example, if the enforced quota value at the time of the
263+
/// `QuotaFailure` on the number of CPUs is "10", then the value of this
264+
/// field would reflect this quantity.
265+
@available(gRPCSwiftProtobuf 2.1, *)
266+
public var quotaValue: Int
267+
268+
/// The new quota value being rolled out at the time of the violation. At the
269+
/// completion of the rollout, this value will be enforced in place of
270+
/// quota_value. If no rollout is in progress at the time of the violation,
271+
/// this field is not set.
272+
///
273+
/// For example, if at the time of the violation a rollout is in progress
274+
/// changing the number of CPUs quota from 10 to 20, 20 would be the value of
275+
/// this field.
276+
@available(gRPCSwiftProtobuf 2.1, *)
277+
public var futureQuotaValue: Int?
278+
279+
public init(
280+
subject: String,
281+
description: String
282+
) {
209283
self.subject = subject
210284
self.violationDescription = description
285+
self.apiService = ""
286+
self.quotaMetric = ""
287+
self.quotaID = ""
288+
self.quotaDimensions = [:]
289+
self.quotaValue = 0
290+
self.futureQuotaValue = nil
291+
}
292+
293+
@available(gRPCSwiftProtobuf 2.1, *)
294+
public init(
295+
subject: String,
296+
description: String,
297+
apiService: String,
298+
quotaMetric: String,
299+
quotaID: String,
300+
quotaDimensions: [String: String],
301+
quotaValue: Int,
302+
futureQuotaValue: Int?
303+
) {
304+
self.subject = subject
305+
self.violationDescription = description
306+
self.apiService = apiService
307+
self.quotaMetric = quotaMetric
308+
self.quotaID = quotaID
309+
self.quotaDimensions = quotaDimensions
310+
self.quotaValue = quotaValue
311+
self.futureQuotaValue = futureQuotaValue
211312
}
212313

213314
init(_ storage: Google_Rpc_QuotaFailure.Violation) {
214315
self.subject = storage.subject
215316
self.violationDescription = storage.description_p
317+
self.apiService = storage.apiService
318+
self.quotaMetric = storage.quotaMetric
319+
self.quotaID = storage.quotaID
320+
self.quotaDimensions = storage.quotaDimensions
321+
self.quotaValue = Int(storage.quotaValue)
322+
if storage.hasFutureQuotaValue {
323+
self.futureQuotaValue = Int(storage.futureQuotaValue)
324+
}
216325
}
217326
}
218327

@@ -225,6 +334,14 @@ extension ErrorDetails {
225334
.with {
226335
$0.subject = violation.subject
227336
$0.description_p = violation.violationDescription
337+
$0.apiService = violation.apiService
338+
$0.quotaMetric = violation.quotaMetric
339+
$0.quotaID = violation.quotaID
340+
$0.quotaDimensions = violation.quotaDimensions
341+
$0.quotaValue = Int64(violation.quotaValue)
342+
if let futureQuotaValue = violation.futureQuotaValue {
343+
$0.futureQuotaValue = Int64(futureQuotaValue)
344+
}
228345
}
229346
}
230347
}
@@ -368,14 +485,52 @@ extension ErrorDetails {
368485
/// A description of why the request element is bad.
369486
public var violationDescription: String
370487

371-
public init(field: String, description: String) {
488+
/// The reason of the field-level error. This is a constant value that
489+
/// identifies the proximate cause of the field-level error. It should
490+
/// uniquely identify the type of the FieldViolation within the scope of the
491+
/// google.rpc.ErrorInfo.domain. This should be at most 63
492+
/// characters and match a regular expression of `[A-Z][A-Z0-9_]+[A-Z0-9]`,
493+
/// which represents UPPER_SNAKE_CASE.
494+
@available(gRPCSwiftProtobuf 2.1, *)
495+
public var reason: String
496+
497+
/// Provides a localized error message for field-level errors that is safe to
498+
/// return to the API consumer.
499+
@available(gRPCSwiftProtobuf 2.1, *)
500+
public var localizedMessage: LocalizedMessage?
501+
502+
public init(
503+
field: String,
504+
description: String
505+
) {
372506
self.field = field
373507
self.violationDescription = description
508+
self.reason = ""
509+
self.localizedMessage = nil
510+
}
511+
512+
@available(gRPCSwiftProtobuf 2.1, *)
513+
public init(
514+
field: String,
515+
description: String,
516+
reason: String,
517+
localizedMessage: LocalizedMessage?
518+
) {
519+
self.field = field
520+
self.violationDescription = description
521+
self.reason = reason
522+
self.localizedMessage = localizedMessage
374523
}
375524

376525
init(_ storage: Google_Rpc_BadRequest.FieldViolation) {
377526
self.field = storage.field
378527
self.violationDescription = storage.description_p
528+
self.reason = storage.reason
529+
if storage.hasLocalizedMessage {
530+
self.localizedMessage = LocalizedMessage(storage: storage.localizedMessage)
531+
} else {
532+
self.localizedMessage = nil
533+
}
379534
}
380535
}
381536

@@ -388,6 +543,10 @@ extension ErrorDetails {
388543
.with {
389544
$0.field = violation.field
390545
$0.description_p = violation.violationDescription
546+
$0.reason = violation.reason
547+
if let localizedMessage = violation.localizedMessage {
548+
$0.localizedMessage = localizedMessage.storage
549+
}
391550
}
392551
}
393552
}

Sources/GRPCProtobuf/Errors/Generated/code.pb.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// For information on using the generated types, please see the documentation:
99
// https://github.com/apple/swift-protobuf/
1010

11-
// Copyright 2024 Google LLC
11+
// Copyright 2025 Google LLC
1212
//
1313
// Licensed under the Apache License, Version 2.0 (the "License");
1414
// you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)