gapic-common 0.20.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +77 -0
- data/README.md +5 -5
- data/lib/gapic/call_options/error_codes.rb +2 -60
- data/lib/gapic/call_options/retry_policy.rb +10 -109
- data/lib/gapic/call_options.rb +1 -1
- data/lib/gapic/common/error_codes.rb +74 -0
- data/lib/gapic/common/polling_harness.rb +82 -0
- data/lib/gapic/common/retry_policy.rb +255 -0
- data/lib/gapic/common/version.rb +1 -1
- data/lib/gapic/common.rb +1 -0
- data/lib/gapic/config.rb +2 -2
- data/lib/gapic/grpc/service_stub/channel.rb +4 -4
- data/lib/gapic/grpc/service_stub/channel_pool.rb +9 -2
- data/lib/gapic/grpc/service_stub/rpc_call.rb +120 -12
- data/lib/gapic/grpc/service_stub.rb +39 -12
- data/lib/gapic/headers.rb +5 -1
- data/lib/gapic/logging_concerns.rb +214 -0
- data/lib/gapic/operation/retry_policy.rb +25 -65
- data/lib/gapic/paged_enumerable.rb +1 -1
- data/lib/gapic/rest/client_stub.rb +115 -25
- data/lib/gapic/rest/http_binding_override_configuration.rb +48 -0
- data/lib/gapic/rest.rb +1 -0
- data/lib/gapic/universe_domain_concerns.rb +84 -0
- metadata +35 -171
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
require "google/cloud/env"
|
|
16
|
+
require "google/logging/message"
|
|
17
|
+
require "google/logging/structured_formatter"
|
|
18
|
+
|
|
19
|
+
module Gapic
|
|
20
|
+
##
|
|
21
|
+
# A mixin module that handles logging setup for a stub.
|
|
22
|
+
#
|
|
23
|
+
module LoggingConcerns
|
|
24
|
+
##
|
|
25
|
+
# The logger for this object.
|
|
26
|
+
#
|
|
27
|
+
# @return [Logger]
|
|
28
|
+
#
|
|
29
|
+
attr_reader :logger
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# @private
|
|
33
|
+
# A convenience object used by stub-based logging.
|
|
34
|
+
#
|
|
35
|
+
class StubLogger
|
|
36
|
+
OMIT_FILES = [
|
|
37
|
+
/^#{Regexp.escape __dir__}/
|
|
38
|
+
].freeze
|
|
39
|
+
|
|
40
|
+
def initialize logger: nil, **kwargs
|
|
41
|
+
@logger = logger
|
|
42
|
+
@kwargs = kwargs
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def enabled?
|
|
46
|
+
!!@logger
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def log severity
|
|
50
|
+
return unless @logger
|
|
51
|
+
locations = caller_locations
|
|
52
|
+
@logger.add severity do
|
|
53
|
+
builder = LogEntryBuilder.new(**@kwargs)
|
|
54
|
+
builder.set_source_location_from locations
|
|
55
|
+
yield builder
|
|
56
|
+
builder.build
|
|
57
|
+
rescue StandardError
|
|
58
|
+
# Do nothing
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def info(&)
|
|
63
|
+
log(Logger::INFO, &)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def debug(&)
|
|
67
|
+
log(Logger::DEBUG, &)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
##
|
|
71
|
+
# @private
|
|
72
|
+
# Builder for a log entry, passed to {StubLogger#log}.
|
|
73
|
+
#
|
|
74
|
+
class LogEntryBuilder
|
|
75
|
+
def initialize system_name: nil,
|
|
76
|
+
service: nil,
|
|
77
|
+
endpoint: nil,
|
|
78
|
+
client_id: nil
|
|
79
|
+
@system_name = system_name
|
|
80
|
+
@service = service
|
|
81
|
+
@endpoint = endpoint
|
|
82
|
+
@client_id = client_id
|
|
83
|
+
@message = nil
|
|
84
|
+
@caller_locations = caller_locations
|
|
85
|
+
@fields = { "clientId" => @client_id }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
attr_reader :system_name
|
|
89
|
+
|
|
90
|
+
attr_reader :service
|
|
91
|
+
|
|
92
|
+
attr_reader :endpoint
|
|
93
|
+
|
|
94
|
+
attr_accessor :message
|
|
95
|
+
|
|
96
|
+
attr_writer :source_location
|
|
97
|
+
|
|
98
|
+
attr_reader :fields
|
|
99
|
+
|
|
100
|
+
def set name, value
|
|
101
|
+
fields[name] = value
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def set_system_name
|
|
105
|
+
set "system", system_name
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def set_service
|
|
109
|
+
set "serviceName", service
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def set_credentials_fields creds
|
|
113
|
+
creds = creds.client if creds.respond_to? :client
|
|
114
|
+
set "credentialsId", creds.object_id
|
|
115
|
+
set "credentialsType", creds.class.name
|
|
116
|
+
set "credentialsScope", creds.scope if creds.respond_to? :scope
|
|
117
|
+
set "useSelfSignedJWT", creds.enable_self_signed_jwt? if creds.respond_to? :enable_self_signed_jwt?
|
|
118
|
+
set "universeDomain", creds.universe_domain if creds.respond_to? :universe_domain
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def source_location
|
|
122
|
+
@source_location ||= Google::Logging::SourceLocation.for_caller omit_files: OMIT_FILES,
|
|
123
|
+
locations: @caller_locations
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def set_source_location_from locations
|
|
127
|
+
@caller_locations = locations
|
|
128
|
+
@source_location = nil
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def build
|
|
132
|
+
Google::Logging::Message.from message: message, source_location: source_location, fields: fields
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
##
|
|
138
|
+
# @private
|
|
139
|
+
# Initialize logging concerns.
|
|
140
|
+
#
|
|
141
|
+
def setup_logging logger: :default,
|
|
142
|
+
stream: nil,
|
|
143
|
+
formatter: nil,
|
|
144
|
+
level: nil,
|
|
145
|
+
system_name: nil,
|
|
146
|
+
service: nil,
|
|
147
|
+
endpoint: nil,
|
|
148
|
+
client_id: nil
|
|
149
|
+
service = LoggingConcerns.normalize_service service
|
|
150
|
+
system_name = LoggingConcerns.normalize_system_name system_name
|
|
151
|
+
logging_env = ENV["GOOGLE_SDK_RUBY_LOGGING_GEMS"].to_s.downcase
|
|
152
|
+
logger = nil if ["false", "none"].include? logging_env
|
|
153
|
+
if logger == :default
|
|
154
|
+
logger = nil
|
|
155
|
+
if ["true", "all"].include?(logging_env) || logging_env.split(",").include?(system_name)
|
|
156
|
+
stream ||= $stderr
|
|
157
|
+
level ||= "DEBUG"
|
|
158
|
+
formatter ||= Google::Logging::StructuredFormatter.new if Google::Cloud::Env.get.logging_agent_expected?
|
|
159
|
+
logger = Logger.new stream, progname: system_name, level: level, formatter: formatter
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
@logger = logger
|
|
163
|
+
@stub_logger = StubLogger.new logger: logger,
|
|
164
|
+
system_name: system_name,
|
|
165
|
+
service: service,
|
|
166
|
+
endpoint: endpoint,
|
|
167
|
+
client_id: client_id
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# @private
|
|
171
|
+
attr_reader :stub_logger
|
|
172
|
+
|
|
173
|
+
class << self
|
|
174
|
+
# @private
|
|
175
|
+
def random_uuid4
|
|
176
|
+
ary = Random.bytes 16
|
|
177
|
+
ary.setbyte 6, ((ary.getbyte(6) & 0x0f) | 0x40)
|
|
178
|
+
ary.setbyte 8, ((ary.getbyte(8) & 0x3f) | 0x80)
|
|
179
|
+
ary.unpack("H8H4H4H4H12").join "-"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# @private
|
|
183
|
+
def normalize_system_name input
|
|
184
|
+
case input
|
|
185
|
+
when String
|
|
186
|
+
input
|
|
187
|
+
when Class
|
|
188
|
+
input.name.split("::")[..-3]
|
|
189
|
+
.map { |elem| elem.scan(/[A-Z][A-Z]*(?=[A-Z][a-z0-9]|$)|[A-Z][a-z0-9]+/).map(&:downcase).join("_") }
|
|
190
|
+
.join("-")
|
|
191
|
+
else
|
|
192
|
+
"googleapis"
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# @private
|
|
197
|
+
def normalize_service input
|
|
198
|
+
case input
|
|
199
|
+
when String
|
|
200
|
+
input
|
|
201
|
+
when Class
|
|
202
|
+
mod = input.name.split("::")[..-2].inject(Object) { |m, n| m.const_get n }
|
|
203
|
+
if mod.const_defined? "Service"
|
|
204
|
+
mod.const_get("Service").service_name
|
|
205
|
+
else
|
|
206
|
+
name_segments = input.name.split("::")[..-3]
|
|
207
|
+
mod = name_segments.inject(Object) { |m, n| m.const_get n }
|
|
208
|
+
name_segments.join "." if mod.const_defined? "Rest"
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
@@ -12,80 +12,40 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
require "gapic/common/retry_policy"
|
|
16
|
+
|
|
15
17
|
module Gapic
|
|
16
18
|
class Operation
|
|
17
19
|
##
|
|
18
|
-
# The policy for retrying operation reloads using an incremental backoff.
|
|
19
|
-
#
|
|
20
|
+
# The policy for retrying operation reloads using an incremental backoff.
|
|
21
|
+
#
|
|
22
|
+
# A new object instance should be used for every Operation invocation.
|
|
20
23
|
#
|
|
21
|
-
class RetryPolicy
|
|
24
|
+
class RetryPolicy < Gapic::Common::RetryPolicy
|
|
25
|
+
# @return [Numeric] Default initial delay in seconds.
|
|
26
|
+
DEFAULT_INITIAL_DELAY = 10
|
|
27
|
+
# @return [Numeric] Default maximum delay in seconds.
|
|
28
|
+
DEFAULT_MAX_DELAY = 300 # Five minutes
|
|
29
|
+
# @return [Numeric] Default delay scaling factor for subsequent retry attempts.
|
|
30
|
+
DEFAULT_MULTIPLIER = 1.3
|
|
31
|
+
# @return [Numeric] Default timeout threshold value in seconds.
|
|
32
|
+
DEFAULT_TIMEOUT = 3600 # One hour
|
|
33
|
+
|
|
22
34
|
##
|
|
23
35
|
# Create new Operation RetryPolicy.
|
|
24
36
|
#
|
|
25
|
-
# @param initial_delay [Numeric]
|
|
26
|
-
# @param multiplier [Numeric]
|
|
27
|
-
# @param max_delay [Numeric]
|
|
28
|
-
# @param timeout [Numeric]
|
|
37
|
+
# @param initial_delay [Numeric] Initial delay in seconds.
|
|
38
|
+
# @param multiplier [Numeric] The delay scaling factor for each subsequent retry attempt.
|
|
39
|
+
# @param max_delay [Numeric] Maximum delay in seconds.
|
|
40
|
+
# @param timeout [Numeric] Timeout threshold value in seconds.
|
|
29
41
|
#
|
|
30
42
|
def initialize initial_delay: nil, multiplier: nil, max_delay: nil, timeout: nil
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def initial_delay
|
|
39
|
-
@initial_delay || 10
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def multiplier
|
|
43
|
-
@multiplier || 1.3
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def max_delay
|
|
47
|
-
@max_delay || 300 # Five minutes
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def timeout
|
|
51
|
-
@timeout || 3600 # One hour
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def call
|
|
55
|
-
return unless retry?
|
|
56
|
-
|
|
57
|
-
delay!
|
|
58
|
-
increment_delay!
|
|
59
|
-
|
|
60
|
-
true
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
private
|
|
64
|
-
|
|
65
|
-
def deadline
|
|
66
|
-
# memoize the deadline
|
|
67
|
-
@deadline ||= Time.now + timeout
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def retry?
|
|
71
|
-
deadline > Time.now
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
##
|
|
75
|
-
# The current delay value.
|
|
76
|
-
def delay
|
|
77
|
-
@delay || initial_delay
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def delay!
|
|
81
|
-
# Call Kernel.sleep so we can stub it.
|
|
82
|
-
Kernel.sleep delay
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
##
|
|
86
|
-
# Calculate and set the next delay value.
|
|
87
|
-
def increment_delay!
|
|
88
|
-
@delay = [delay * multiplier, max_delay].min
|
|
43
|
+
super(
|
|
44
|
+
initial_delay: initial_delay || DEFAULT_INITIAL_DELAY,
|
|
45
|
+
max_delay: max_delay || DEFAULT_MAX_DELAY,
|
|
46
|
+
multiplier: multiplier || DEFAULT_MULTIPLIER,
|
|
47
|
+
timeout: timeout || DEFAULT_TIMEOUT
|
|
48
|
+
)
|
|
89
49
|
end
|
|
90
50
|
end
|
|
91
51
|
end
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
require "googleauth"
|
|
16
|
+
require "gapic/logging_concerns"
|
|
16
17
|
require "gapic/rest/faraday_middleware"
|
|
18
|
+
require "gapic/universe_domain_concerns"
|
|
17
19
|
require "faraday/retry"
|
|
18
20
|
|
|
19
21
|
module Gapic
|
|
@@ -26,35 +28,64 @@ module Gapic
|
|
|
26
28
|
# - store credentials and add auth information to the request
|
|
27
29
|
#
|
|
28
30
|
class ClientStub
|
|
31
|
+
include UniverseDomainConcerns
|
|
32
|
+
include LoggingConcerns
|
|
33
|
+
|
|
29
34
|
##
|
|
30
35
|
# Initializes with an endpoint and credentials
|
|
31
|
-
#
|
|
36
|
+
#
|
|
37
|
+
# @param endpoint [String] The endpoint of the API. Overrides any endpoint_template.
|
|
38
|
+
# @param endpoint_template [String] The endpoint of the API, where the
|
|
39
|
+
# universe domain component of the hostname is marked by the string in
|
|
40
|
+
# the constant {UniverseDomainConcerns::ENDPOINT_SUBSTITUTION}.
|
|
41
|
+
# @param universe_domain [String] The universe domain in which calls
|
|
42
|
+
# should be made. Defaults to `googleapis.com`.
|
|
32
43
|
# @param credentials [Google::Auth::Credentials]
|
|
33
44
|
# Credentials to send with calls in form of a googleauth credentials object.
|
|
34
45
|
# (see the [googleauth docs](https://googleapis.dev/ruby/googleauth/latest/index.html))
|
|
35
46
|
# @param numeric_enums [Boolean] Whether to signal the server to JSON-encode enums as ints
|
|
36
|
-
#
|
|
37
47
|
# @param raise_faraday_errors [Boolean]
|
|
38
48
|
# Whether to raise Faraday errors instead of wrapping them in `Gapic::Rest::Error`
|
|
39
49
|
# Added for backwards compatibility.
|
|
40
50
|
# Default is `true`. All REST clients (except for old versions of `google-cloud-compute-v1`)
|
|
41
51
|
# should explicitly set this parameter to `false`.
|
|
52
|
+
# @param logger [Logger,:default,nil] An explicit logger to use, or one
|
|
53
|
+
# of the values `:default` (the default) to construct a default logger,
|
|
54
|
+
# or `nil` to disable logging explicitly.
|
|
42
55
|
#
|
|
43
56
|
# @yield [Faraday::Connection]
|
|
44
57
|
#
|
|
45
|
-
def initialize
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
58
|
+
def initialize credentials:,
|
|
59
|
+
endpoint: nil,
|
|
60
|
+
endpoint_template: nil,
|
|
61
|
+
universe_domain: nil,
|
|
62
|
+
numeric_enums: false,
|
|
63
|
+
raise_faraday_errors: true,
|
|
64
|
+
logging_system: nil,
|
|
65
|
+
service_name: nil,
|
|
66
|
+
logger: :default
|
|
67
|
+
setup_universe_domain universe_domain: universe_domain,
|
|
68
|
+
endpoint: endpoint,
|
|
69
|
+
endpoint_template: endpoint_template,
|
|
70
|
+
credentials: credentials
|
|
71
|
+
|
|
72
|
+
endpoint_url = self.endpoint
|
|
73
|
+
endpoint_url = "https://#{endpoint_url}" unless /^https?:/.match? endpoint_url
|
|
74
|
+
endpoint_url = endpoint_url.sub %r{/$}, ""
|
|
75
|
+
|
|
76
|
+
setup_logging logger: logger,
|
|
77
|
+
system_name: logging_system,
|
|
78
|
+
service: service_name,
|
|
79
|
+
endpoint: endpoint_url,
|
|
80
|
+
client_id: object_id
|
|
49
81
|
|
|
50
|
-
@credentials = credentials
|
|
51
82
|
@numeric_enums = numeric_enums
|
|
52
83
|
|
|
53
84
|
@raise_faraday_errors = raise_faraday_errors
|
|
54
85
|
|
|
55
|
-
@connection = Faraday.new url:
|
|
86
|
+
@connection = Faraday.new url: endpoint_url do |conn|
|
|
56
87
|
conn.headers = { "Content-Type" => "application/json" }
|
|
57
|
-
conn.request :google_authorization,
|
|
88
|
+
conn.request :google_authorization, self.credentials unless self.credentials.is_a? ::Symbol
|
|
58
89
|
conn.request :retry
|
|
59
90
|
conn.response :raise_error
|
|
60
91
|
conn.adapter :net_http
|
|
@@ -71,8 +102,8 @@ module Gapic
|
|
|
71
102
|
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
|
72
103
|
# to the REST call. Currently only timeout and headers are supported.
|
|
73
104
|
# @return [Faraday::Response]
|
|
74
|
-
def make_get_request uri:, params: {}, options: {}
|
|
75
|
-
make_http_request :get, uri: uri, body: nil, params: params, options: options
|
|
105
|
+
def make_get_request uri:, params: {}, options: {}, method_name: nil
|
|
106
|
+
make_http_request :get, uri: uri, body: nil, params: params, options: options, method_name: method_name
|
|
76
107
|
end
|
|
77
108
|
|
|
78
109
|
##
|
|
@@ -83,8 +114,8 @@ module Gapic
|
|
|
83
114
|
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
|
84
115
|
# to the REST call. Currently only timeout and headers are supported.
|
|
85
116
|
# @return [Faraday::Response]
|
|
86
|
-
def make_delete_request uri:, params: {}, options: {}
|
|
87
|
-
make_http_request :delete, uri: uri, body: nil, params: params, options: options
|
|
117
|
+
def make_delete_request uri:, params: {}, options: {}, method_name: nil
|
|
118
|
+
make_http_request :delete, uri: uri, body: nil, params: params, options: options, method_name: method_name
|
|
88
119
|
end
|
|
89
120
|
|
|
90
121
|
##
|
|
@@ -96,8 +127,8 @@ module Gapic
|
|
|
96
127
|
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
|
97
128
|
# to the REST call. Currently only timeout and headers are supported.
|
|
98
129
|
# @return [Faraday::Response]
|
|
99
|
-
def make_patch_request uri:, body:, params: {}, options: {}
|
|
100
|
-
make_http_request :patch, uri: uri, body: body, params: params, options: options
|
|
130
|
+
def make_patch_request uri:, body:, params: {}, options: {}, method_name: nil
|
|
131
|
+
make_http_request :patch, uri: uri, body: body, params: params, options: options, method_name: method_name
|
|
101
132
|
end
|
|
102
133
|
|
|
103
134
|
##
|
|
@@ -109,8 +140,8 @@ module Gapic
|
|
|
109
140
|
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
|
110
141
|
# to the REST call. Currently only timeout and headers are supported.
|
|
111
142
|
# @return [Faraday::Response]
|
|
112
|
-
def make_post_request uri:, body: nil, params: {}, options: {}
|
|
113
|
-
make_http_request :post, uri: uri, body: body, params: params, options: options
|
|
143
|
+
def make_post_request uri:, body: nil, params: {}, options: {}, method_name: nil
|
|
144
|
+
make_http_request :post, uri: uri, body: body, params: params, options: options, method_name: method_name
|
|
114
145
|
end
|
|
115
146
|
|
|
116
147
|
##
|
|
@@ -122,8 +153,8 @@ module Gapic
|
|
|
122
153
|
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
|
123
154
|
# to the REST call. Currently only timeout and headers are supported.
|
|
124
155
|
# @return [Faraday::Response]
|
|
125
|
-
def make_put_request uri:, body: nil, params: {}, options: {}
|
|
126
|
-
make_http_request :put, uri: uri, body: body, params: params, options: options
|
|
156
|
+
def make_put_request uri:, body: nil, params: {}, options: {}, method_name: nil
|
|
157
|
+
make_http_request :put, uri: uri, body: body, params: params, options: options, method_name: method_name
|
|
127
158
|
end
|
|
128
159
|
|
|
129
160
|
##
|
|
@@ -137,27 +168,38 @@ module Gapic
|
|
|
137
168
|
# @param is_server_streaming [Boolean] flag if method is streaming
|
|
138
169
|
# @yieldparam chunk [String] The chunk of data received during server streaming.
|
|
139
170
|
# @return [Faraday::Response]
|
|
140
|
-
def make_http_request verb,
|
|
171
|
+
def make_http_request verb,
|
|
172
|
+
uri:, body:, params:, options:,
|
|
173
|
+
is_server_streaming: false, method_name: nil,
|
|
174
|
+
&block
|
|
141
175
|
# Converts hash and nil to an options object
|
|
142
176
|
options = ::Gapic::CallOptions.new(**options.to_h) unless options.is_a? ::Gapic::CallOptions
|
|
143
177
|
deadline = calculate_deadline options
|
|
144
178
|
retried_exception = nil
|
|
145
179
|
next_timeout = get_timeout deadline
|
|
180
|
+
request_id = LoggingConcerns.random_uuid4
|
|
181
|
+
try_number = 1
|
|
146
182
|
|
|
147
183
|
begin
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
184
|
+
log_request method_name, request_id, try_number, body, options.metadata
|
|
185
|
+
response = base_make_http_request verb: verb, uri: uri, body: body,
|
|
186
|
+
params: params, metadata: options.metadata,
|
|
187
|
+
timeout: next_timeout,
|
|
188
|
+
is_server_streaming: is_server_streaming,
|
|
189
|
+
&block
|
|
190
|
+
log_response method_name, request_id, try_number, response, is_server_streaming
|
|
191
|
+
response
|
|
153
192
|
rescue ::Faraday::TimeoutError => e
|
|
193
|
+
log_response method_name, request_id, try_number, e, is_server_streaming
|
|
154
194
|
raise if @raise_faraday_errors
|
|
155
195
|
raise Gapic::Rest::DeadlineExceededError.wrap_faraday_error e, root_cause: retried_exception
|
|
156
196
|
rescue ::Faraday::Error => e
|
|
197
|
+
log_response method_name, request_id, try_number, e, is_server_streaming
|
|
157
198
|
next_timeout = get_timeout deadline
|
|
158
199
|
|
|
159
200
|
if check_retry?(next_timeout) && options.retry_policy.call(e)
|
|
160
201
|
retried_exception = e
|
|
202
|
+
try_number += 1
|
|
161
203
|
retry
|
|
162
204
|
end
|
|
163
205
|
|
|
@@ -234,6 +276,54 @@ module Gapic
|
|
|
234
276
|
|
|
235
277
|
timeout.positive?
|
|
236
278
|
end
|
|
279
|
+
|
|
280
|
+
def log_request method_name, request_id, try_number, body, metadata
|
|
281
|
+
return unless stub_logger&.enabled?
|
|
282
|
+
stub_logger.info do |entry|
|
|
283
|
+
entry.set_system_name
|
|
284
|
+
entry.set_service
|
|
285
|
+
entry.set "rpcName", method_name
|
|
286
|
+
entry.set "retryAttempt", try_number
|
|
287
|
+
entry.set "requestId", request_id
|
|
288
|
+
entry.message = "Sending request to #{entry.service}.#{method_name} (try #{try_number})"
|
|
289
|
+
end
|
|
290
|
+
body = body.to_s
|
|
291
|
+
metadata = metadata.to_h rescue {}
|
|
292
|
+
return if body.empty? && metadata.empty?
|
|
293
|
+
stub_logger.debug do |entry|
|
|
294
|
+
entry.set "requestId", request_id
|
|
295
|
+
entry.set "request", body
|
|
296
|
+
entry.set "headers", metadata
|
|
297
|
+
entry.message = "(request payload as JSON)"
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def log_response method_name, request_id, try_number, response, is_server_streaming
|
|
302
|
+
return unless stub_logger&.enabled?
|
|
303
|
+
stub_logger.info do |entry|
|
|
304
|
+
entry.set_system_name
|
|
305
|
+
entry.set_service
|
|
306
|
+
entry.set "rpcName", method_name
|
|
307
|
+
entry.set "retryAttempt", try_number
|
|
308
|
+
entry.set "requestId", request_id
|
|
309
|
+
if response.is_a? StandardError
|
|
310
|
+
entry.set "exception", response.to_s
|
|
311
|
+
entry.message = "Received error for #{entry.service}.#{method_name} (try #{try_number}): #{response}"
|
|
312
|
+
elsif is_server_streaming
|
|
313
|
+
entry.message = "Receiving stream for #{entry.service}.#{method_name} (try #{try_number})"
|
|
314
|
+
else
|
|
315
|
+
entry.message = "Received response for #{entry.service}.#{method_name} (try #{try_number})"
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
return if is_server_streaming || !response.respond_to?(:body)
|
|
319
|
+
body = response.body.to_s
|
|
320
|
+
return if body.empty?
|
|
321
|
+
stub_logger.debug do |entry|
|
|
322
|
+
entry.set "requestId", request_id
|
|
323
|
+
entry.set "response", body
|
|
324
|
+
entry.message = "(response payload as JSON)"
|
|
325
|
+
end
|
|
326
|
+
end
|
|
237
327
|
end
|
|
238
328
|
end
|
|
239
329
|
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copyright 2025 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
|
+
require "gapic/config"
|
|
16
|
+
|
|
17
|
+
module Gapic
|
|
18
|
+
module Rest
|
|
19
|
+
##
|
|
20
|
+
# @private
|
|
21
|
+
# A specialized Configuration class to use when generating
|
|
22
|
+
# package-level binding override configuration.
|
|
23
|
+
#
|
|
24
|
+
# This configuration is for internal use of the client library classes,
|
|
25
|
+
# and it is not intended that the end-users will read or change it.
|
|
26
|
+
#
|
|
27
|
+
# @attribute [rw] bindings_override
|
|
28
|
+
# Overrides for http bindings for the RPC of the mixins for the given package.
|
|
29
|
+
# return [::Hash{::Symbol=>::Array<::Gapic::Rest::GrpcTranscoder::HttpBinding>}]
|
|
30
|
+
#
|
|
31
|
+
class HttpBindingOverrideConfiguration
|
|
32
|
+
extend ::Gapic::Config
|
|
33
|
+
|
|
34
|
+
# @private
|
|
35
|
+
# Overrides for http bindings for the RPC of the mixins for the given package.
|
|
36
|
+
# Services in the package should use these when creating clients for the mixin services.
|
|
37
|
+
# @return [::Hash{::Symbol=>::Array<::Gapic::Rest::GrpcTranscoder::HttpBinding>}]
|
|
38
|
+
config_attr :bindings_override, {}, ::Hash, nil
|
|
39
|
+
|
|
40
|
+
# @private
|
|
41
|
+
def initialize parent_config = nil
|
|
42
|
+
@parent_config = parent_config unless parent_config.nil?
|
|
43
|
+
|
|
44
|
+
yield self if block_given?
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/gapic/rest.rb
CHANGED
|
@@ -25,6 +25,7 @@ require "gapic/rest/client_stub"
|
|
|
25
25
|
require "gapic/rest/error"
|
|
26
26
|
require "gapic/rest/faraday_middleware"
|
|
27
27
|
require "gapic/rest/grpc_transcoder"
|
|
28
|
+
require "gapic/rest/http_binding_override_configuration"
|
|
28
29
|
require "gapic/rest/operation"
|
|
29
30
|
require "gapic/rest/paged_enumerable"
|
|
30
31
|
require "gapic/rest/server_stream"
|