gruf 2.7.0 → 2.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -3
- data/README.md +7 -502
- data/gruf.gemspec +26 -8
- data/lib/gruf/cli/executor.rb +18 -6
- data/lib/gruf/client.rb +27 -2
- data/lib/gruf/client/error.rb +2 -0
- data/lib/gruf/configuration.rb +3 -2
- data/lib/gruf/controllers/base.rb +2 -0
- data/lib/gruf/controllers/request.rb +8 -6
- data/lib/gruf/controllers/service_binder.rb +1 -1
- data/lib/gruf/error.rb +1 -1
- data/lib/gruf/hooks/executor.rb +1 -1
- data/lib/gruf/interceptors/client_interceptor.rb +8 -16
- data/lib/gruf/interceptors/context.rb +4 -4
- data/lib/gruf/interceptors/instrumentation/output_metadata_timer.rb +2 -4
- data/lib/gruf/interceptors/instrumentation/request_logging/formatters/base.rb +3 -1
- data/lib/gruf/interceptors/instrumentation/request_logging/formatters/logstash.rb +3 -1
- data/lib/gruf/interceptors/instrumentation/request_logging/formatters/plain.rb +3 -1
- data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +13 -15
- data/lib/gruf/interceptors/instrumentation/statsd.rb +2 -4
- data/lib/gruf/interceptors/timer.rb +5 -2
- data/lib/gruf/outbound/request_context.rb +1 -1
- data/lib/gruf/server.rb +2 -2
- data/lib/gruf/timer.rb +5 -4
- data/lib/gruf/version.rb +1 -1
- metadata +226 -27
data/gruf.gemspec
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
16
16
|
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
17
17
|
#
|
18
|
-
|
18
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
19
19
|
require 'gruf/version'
|
20
20
|
|
21
21
|
Gem::Specification.new do |spec|
|
@@ -30,19 +30,37 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.homepage = 'https://github.com/bigcommerce/gruf'
|
31
31
|
|
32
32
|
spec.files = Dir['README.md', 'CHANGELOG.md', 'CODE_OF_CONDUCT.md', 'lib/**/*', 'gruf.gemspec']
|
33
|
-
spec.executables
|
33
|
+
spec.executables << 'gruf'
|
34
34
|
spec.require_paths = ['lib']
|
35
35
|
|
36
|
-
spec.required_ruby_version = '
|
36
|
+
spec.required_ruby_version = '>= 2.6', '< 3.1'
|
37
37
|
|
38
38
|
spec.add_development_dependency 'bundler', '~> 1.11'
|
39
|
-
spec.add_development_dependency '
|
40
|
-
|
39
|
+
spec.add_development_dependency 'bundler-audit', '>= 0.6'
|
40
|
+
# rubocop:disable Gemspec/RubyVersionGlobalsUsage
|
41
|
+
spec.add_development_dependency(
|
42
|
+
'factory_bot',
|
43
|
+
(Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5') ? '>= 6.1' : '~> 5.2')
|
44
|
+
)
|
45
|
+
# rubocop:enable Gemspec/RubyVersionGlobalsUsage
|
46
|
+
spec.add_development_dependency 'ffaker', '>= 2.15'
|
47
|
+
spec.add_development_dependency 'pry', '~> 0.12'
|
48
|
+
spec.add_development_dependency 'pry-byebug', '>= 3.9'
|
49
|
+
spec.add_development_dependency 'rake', '>= 10.0'
|
50
|
+
spec.add_development_dependency 'rspec', '>= 3.8'
|
51
|
+
spec.add_development_dependency 'rspec_junit_formatter', '>= 0.4'
|
52
|
+
spec.add_development_dependency 'rubocop', '>= 1.0'
|
53
|
+
spec.add_development_dependency 'rubocop-performance', '>= 0.0.1'
|
54
|
+
spec.add_development_dependency 'rubocop-rspec', '>= 2.0'
|
55
|
+
spec.add_development_dependency 'rubocop-thread_safety', '>= 0.3'
|
56
|
+
spec.add_development_dependency 'simplecov', '>= 0.16'
|
41
57
|
|
42
|
-
spec.add_runtime_dependency 'grpc', '~> 1.10'
|
43
|
-
spec.add_runtime_dependency 'grpc-tools', '~> 1.10'
|
44
58
|
spec.add_runtime_dependency 'activesupport', '> 4'
|
45
|
-
|
46
59
|
spec.add_runtime_dependency 'concurrent-ruby', '> 1'
|
60
|
+
spec.add_runtime_dependency 'e2mmap', '~> 0.1'
|
61
|
+
spec.add_runtime_dependency 'grpc', '~> 1.10'
|
62
|
+
spec.add_runtime_dependency 'grpc-tools', '~> 1.10'
|
63
|
+
spec.add_runtime_dependency 'json', '>= 2.3'
|
47
64
|
spec.add_runtime_dependency 'slop', '~> 4.6'
|
65
|
+
spec.add_runtime_dependency 'thwait', '~> 0.1'
|
48
66
|
end
|
data/lib/gruf/cli/executor.rb
CHANGED
@@ -38,7 +38,7 @@ module Gruf
|
|
38
38
|
@services = services || Gruf.services
|
39
39
|
@hook_executor = hook_executor || Gruf::Hooks::Executor.new(hooks: Gruf.hooks&.prepare)
|
40
40
|
@server = server || Gruf::Server.new(Gruf.server_options)
|
41
|
-
@logger = logger || Gruf.logger || ::Logger.new(
|
41
|
+
@logger = logger || Gruf.logger || ::Logger.new($stderr)
|
42
42
|
end
|
43
43
|
|
44
44
|
##
|
@@ -67,7 +67,23 @@ module Gruf
|
|
67
67
|
# Setup options for CLI execution and configure Gruf based on inputs
|
68
68
|
#
|
69
69
|
def setup!
|
70
|
-
opts =
|
70
|
+
opts = parse_options
|
71
|
+
|
72
|
+
Gruf.server_binding_url = opts[:host] if opts[:host]
|
73
|
+
if opts.suppress_default_interceptors?
|
74
|
+
Gruf.interceptors.remove(Gruf::Interceptors::ActiveRecord::ConnectionReset)
|
75
|
+
Gruf.interceptors.remove(Gruf::Interceptors::Instrumentation::OutputMetadataTimer)
|
76
|
+
end
|
77
|
+
Gruf.backtrace_on_error = true if opts.backtrace_on_error?
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Parse all CLI arguments into an options result
|
82
|
+
#
|
83
|
+
# @return [Slop::Result]
|
84
|
+
#
|
85
|
+
def parse_options
|
86
|
+
::Slop.parse(@args) do |o|
|
71
87
|
o.null '-h', '--help', 'Display help message' do
|
72
88
|
puts o
|
73
89
|
exit(0)
|
@@ -80,10 +96,6 @@ module Gruf
|
|
80
96
|
exit(0)
|
81
97
|
end
|
82
98
|
end
|
83
|
-
|
84
|
-
Gruf.server_binding_url = opts[:host] if opts[:host]
|
85
|
-
Gruf.use_default_interceptors = false if opts.suppress_default_interceptors?
|
86
|
-
Gruf.backtrace_on_error = true if opts.backtrace_on_error?
|
87
99
|
end
|
88
100
|
end
|
89
101
|
end
|
data/lib/gruf/client.rb
CHANGED
@@ -60,9 +60,10 @@ module Gruf
|
|
60
60
|
@opts = options || {}
|
61
61
|
@opts[:password] = @opts.fetch(:password, '').to_s
|
62
62
|
@opts[:hostname] = @opts.fetch(:hostname, Gruf.default_client_host)
|
63
|
+
@opts[:channel_credentials] = @opts.fetch(:channel_credentials, Gruf.default_channel_credentials)
|
63
64
|
@error_factory = Gruf::Client::ErrorFactory.new
|
64
|
-
client_options[:timeout] = client_options[:timeout]
|
65
|
-
client = "#{service}::Stub".constantize.new(@opts[:hostname], build_ssl_credentials, client_options)
|
65
|
+
client_options[:timeout] = parse_timeout(client_options[:timeout]) if client_options.key?(:timeout)
|
66
|
+
client = "#{service}::Stub".constantize.new(@opts[:hostname], build_ssl_credentials, **client_options)
|
66
67
|
super(client)
|
67
68
|
end
|
68
69
|
|
@@ -190,6 +191,8 @@ module Gruf
|
|
190
191
|
#
|
191
192
|
# :nocov:
|
192
193
|
def build_ssl_credentials
|
194
|
+
return opts[:channel_credentials] if opts[:channel_credentials]
|
195
|
+
|
193
196
|
cert = nil
|
194
197
|
if opts[:ssl_certificate_file]
|
195
198
|
cert = File.read(opts[:ssl_certificate_file]).to_s.strip
|
@@ -213,5 +216,27 @@ module Gruf
|
|
213
216
|
Gruf::Serializers::Errors::Json
|
214
217
|
end
|
215
218
|
end
|
219
|
+
|
220
|
+
##
|
221
|
+
# Handle various timeout values and prevent improper value setting
|
222
|
+
#
|
223
|
+
# @see GRPC::Core::TimeConsts#from_relative_time
|
224
|
+
# @param [mixed] timeout
|
225
|
+
# @return [Float]
|
226
|
+
# @return [GRPC::Core::TimeSpec]
|
227
|
+
#
|
228
|
+
def parse_timeout(timeout)
|
229
|
+
if timeout.nil?
|
230
|
+
GRPC::Core::TimeConsts::ZERO
|
231
|
+
elsif timeout.is_a?(GRPC::Core::TimeSpec)
|
232
|
+
timeout
|
233
|
+
elsif timeout.is_a?(Numeric)
|
234
|
+
timeout
|
235
|
+
elsif timeout.respond_to?(:to_f)
|
236
|
+
timeout.to_f
|
237
|
+
else
|
238
|
+
raise ArgumentError, 'timeout is not a valid value: does not respond to to_f'
|
239
|
+
end
|
240
|
+
end
|
216
241
|
end
|
217
242
|
end
|
data/lib/gruf/client/error.rb
CHANGED
@@ -33,6 +33,7 @@ module Gruf
|
|
33
33
|
#
|
34
34
|
def initialize(error)
|
35
35
|
@error = error
|
36
|
+
super
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
@@ -57,6 +58,7 @@ module Gruf
|
|
57
58
|
class FailedPrecondition < Error; end
|
58
59
|
class Internal < Error; end
|
59
60
|
class PermissionDenied < Error; end
|
61
|
+
class ResourceExhausted < Error; end
|
60
62
|
class Unauthenticated < Error; end
|
61
63
|
class Unavailable < Error; end
|
62
64
|
class Unimplemented < Error; end
|
data/lib/gruf/configuration.rb
CHANGED
@@ -26,6 +26,7 @@ module Gruf
|
|
26
26
|
server_options: {},
|
27
27
|
interceptors: nil,
|
28
28
|
hooks: nil,
|
29
|
+
default_channel_credentials: nil,
|
29
30
|
default_client_host: '',
|
30
31
|
use_ssl: false,
|
31
32
|
ssl_crt_file: '',
|
@@ -97,7 +98,7 @@ module Gruf
|
|
97
98
|
#
|
98
99
|
def reset
|
99
100
|
VALID_CONFIG_KEYS.each do |k, v|
|
100
|
-
send(
|
101
|
+
send("#{k}=", v)
|
101
102
|
end
|
102
103
|
self.interceptors = Gruf::Interceptors::Registry.new
|
103
104
|
self.hooks = Gruf::Hooks::Registry.new
|
@@ -106,7 +107,7 @@ module Gruf
|
|
106
107
|
self.logger = Rails.logger
|
107
108
|
else
|
108
109
|
require 'logger'
|
109
|
-
self.logger = ::Logger.new(
|
110
|
+
self.logger = ::Logger.new($stdout)
|
110
111
|
end
|
111
112
|
self.grpc_logger = logger if grpc_logger.nil?
|
112
113
|
self.ssl_crt_file = "#{root_path}config/ssl/#{environment}.crt"
|
@@ -65,7 +65,9 @@ module Gruf
|
|
65
65
|
def self.bind(service)
|
66
66
|
service_class = service.name.constantize
|
67
67
|
Gruf.services << service_class
|
68
|
+
# rubocop:disable ThreadSafety/InstanceVariableInClassMethod
|
68
69
|
@bound_service = service_class
|
70
|
+
# rubocop:enable ThreadSafety/InstanceVariableInClassMethod
|
69
71
|
ServiceBinder.new(service_class).bind!(self)
|
70
72
|
end
|
71
73
|
|
@@ -58,7 +58,7 @@ module Gruf
|
|
58
58
|
# @param [Class] service The class of the service being executed against
|
59
59
|
# @param [GRPC::RpcDesc] rpc_desc The RPC descriptor of the call
|
60
60
|
# @param [GRPC::ActiveCall] active_call The restricted view of the call
|
61
|
-
# @param [Object] message The protobuf message (or messages) of the request
|
61
|
+
# @param [Object|Google::Protobuf::MessageExts] message The protobuf message (or messages) of the request
|
62
62
|
#
|
63
63
|
def initialize(method_key:, service:, rpc_desc:, active_call:, message:)
|
64
64
|
@method_key = method_key
|
@@ -99,21 +99,23 @@ module Gruf
|
|
99
99
|
# @return [String] The parsed service method name
|
100
100
|
#
|
101
101
|
def method_name
|
102
|
-
"#{service_key}.#{method_key}"
|
102
|
+
"#{service_key}.#{@method_key}"
|
103
103
|
end
|
104
104
|
|
105
105
|
##
|
106
106
|
# Return all messages for this request, properly handling different request types
|
107
107
|
#
|
108
|
-
# @return Enumerable<Object> All messages for this request
|
108
|
+
# @return [Enumerable<Object>] All messages for this request
|
109
109
|
#
|
110
110
|
def messages
|
111
111
|
if client_streamer?
|
112
|
-
|
112
|
+
# rubocop:disable Style/ExplicitBlockArgument
|
113
|
+
@message.call { |msg| yield msg }
|
114
|
+
# rubocop:enable Style/ExplicitBlockArgument
|
113
115
|
elsif bidi_streamer?
|
114
|
-
message
|
116
|
+
@message
|
115
117
|
else
|
116
|
-
[message]
|
118
|
+
[@message]
|
117
119
|
end
|
118
120
|
end
|
119
121
|
end
|
@@ -38,7 +38,7 @@ module Gruf
|
|
38
38
|
##
|
39
39
|
# Bind all methods on the service to the passed controller
|
40
40
|
#
|
41
|
-
# @param [Gruf::Controllers::Base] controller
|
41
|
+
# @param [Class<Gruf::Controllers::Base>] controller
|
42
42
|
#
|
43
43
|
def bind!(controller)
|
44
44
|
rpc_methods.each { |name, desc| bind_method(controller, name, desc) }
|
data/lib/gruf/error.rb
CHANGED
data/lib/gruf/hooks/executor.rb
CHANGED
@@ -43,7 +43,7 @@ module Gruf
|
|
43
43
|
# @param [Hash] metadata A hash of outgoing metadata
|
44
44
|
# @return [Object] The response message
|
45
45
|
#
|
46
|
-
def request_response(request: nil, call: nil, method: nil, metadata: nil)
|
46
|
+
def request_response(request: nil, call: nil, method: nil, metadata: nil, &block)
|
47
47
|
rc = Gruf::Outbound::RequestContext.new(
|
48
48
|
type: :request_response,
|
49
49
|
requests: [request],
|
@@ -51,9 +51,7 @@ module Gruf
|
|
51
51
|
method: method,
|
52
52
|
metadata: metadata
|
53
53
|
)
|
54
|
-
call(request_context: rc)
|
55
|
-
yield
|
56
|
-
end
|
54
|
+
call(request_context: rc, &block)
|
57
55
|
end
|
58
56
|
|
59
57
|
##
|
@@ -65,7 +63,7 @@ module Gruf
|
|
65
63
|
# @param [Hash] metadata A hash of outgoing metadata
|
66
64
|
# @return [Object] The response message
|
67
65
|
#
|
68
|
-
def client_streamer(requests: nil, call: nil, method: nil, metadata: nil)
|
66
|
+
def client_streamer(requests: nil, call: nil, method: nil, metadata: nil, &block)
|
69
67
|
rc = Gruf::Outbound::RequestContext.new(
|
70
68
|
type: :client_streamer,
|
71
69
|
requests: requests,
|
@@ -73,9 +71,7 @@ module Gruf
|
|
73
71
|
method: method,
|
74
72
|
metadata: metadata
|
75
73
|
)
|
76
|
-
call(request_context: rc)
|
77
|
-
yield
|
78
|
-
end
|
74
|
+
call(request_context: rc, &block)
|
79
75
|
end
|
80
76
|
|
81
77
|
##
|
@@ -87,7 +83,7 @@ module Gruf
|
|
87
83
|
# @param [Hash] metadata A hash of outgoing metadata
|
88
84
|
# @return [Object] The response message
|
89
85
|
#
|
90
|
-
def server_streamer(request: nil, call: nil, method: nil, metadata: nil)
|
86
|
+
def server_streamer(request: nil, call: nil, method: nil, metadata: nil, &block)
|
91
87
|
rc = Gruf::Outbound::RequestContext.new(
|
92
88
|
type: :server_streamer,
|
93
89
|
requests: [request],
|
@@ -95,9 +91,7 @@ module Gruf
|
|
95
91
|
method: method,
|
96
92
|
metadata: metadata
|
97
93
|
)
|
98
|
-
call(request_context: rc)
|
99
|
-
yield
|
100
|
-
end
|
94
|
+
call(request_context: rc, &block)
|
101
95
|
end
|
102
96
|
|
103
97
|
##
|
@@ -108,7 +102,7 @@ module Gruf
|
|
108
102
|
# @param [Method] method The method being called
|
109
103
|
# @param [Hash] metadata A hash of outgoing metadata
|
110
104
|
#
|
111
|
-
def bidi_streamer(requests: nil, call: nil, method: nil, metadata: nil)
|
105
|
+
def bidi_streamer(requests: nil, call: nil, method: nil, metadata: nil, &block)
|
112
106
|
rc = Gruf::Outbound::RequestContext.new(
|
113
107
|
type: :bidi_streamer,
|
114
108
|
requests: requests,
|
@@ -116,9 +110,7 @@ module Gruf
|
|
116
110
|
method: method,
|
117
111
|
metadata: metadata
|
118
112
|
)
|
119
|
-
call(request_context: rc)
|
120
|
-
yield
|
121
|
-
end
|
113
|
+
call(request_context: rc, &block)
|
122
114
|
end
|
123
115
|
end
|
124
116
|
end
|
@@ -28,14 +28,14 @@ module Gruf
|
|
28
28
|
#
|
29
29
|
# @param [Array<Gruf::Interceptors::ServerInterceptor>] interceptors
|
30
30
|
#
|
31
|
-
def initialize(interceptors =
|
32
|
-
@interceptors = interceptors
|
31
|
+
def initialize(interceptors = nil)
|
32
|
+
@interceptors = interceptors || []
|
33
33
|
end
|
34
34
|
|
35
35
|
##
|
36
36
|
# Intercept the given request and run interceptors in a FIFO execution order
|
37
37
|
#
|
38
|
-
def intercept!
|
38
|
+
def intercept!(&block)
|
39
39
|
return yield if @interceptors.none?
|
40
40
|
|
41
41
|
i = @interceptors.pop
|
@@ -45,7 +45,7 @@ module Gruf
|
|
45
45
|
|
46
46
|
i.call do
|
47
47
|
if @interceptors.any?
|
48
|
-
intercept!
|
48
|
+
intercept!(&block)
|
49
49
|
else
|
50
50
|
yield
|
51
51
|
end
|
@@ -27,12 +27,10 @@ module Gruf
|
|
27
27
|
##
|
28
28
|
# Handle the instrumented response. Note: this will only instrument timings of _successful_ responses.
|
29
29
|
#
|
30
|
-
def call
|
30
|
+
def call(&block)
|
31
31
|
return unless active_call.respond_to?(:output_metadata)
|
32
32
|
|
33
|
-
result = Gruf::Interceptors::Timer.time
|
34
|
-
yield
|
35
|
-
end
|
33
|
+
result = Gruf::Interceptors::Timer.time(&block)
|
36
34
|
output_metadata.update(metadata_key => result.elapsed.to_s)
|
37
35
|
|
38
36
|
raise result.message unless result.successful?
|
@@ -28,9 +28,11 @@ module Gruf
|
|
28
28
|
# Format the parameters into a loggable string. Must be implemented in every derivative class
|
29
29
|
#
|
30
30
|
# @param [Hash] _payload The incoming request payload
|
31
|
+
# @param [Gruf::Controllers::Request] request The current controller request
|
32
|
+
# @param [Gruf::Interceptors::Timer::Result] result The timed result of the response
|
31
33
|
# @return [String] The formatted string
|
32
34
|
#
|
33
|
-
def format(_payload)
|
35
|
+
def format(_payload, request:, result:)
|
34
36
|
raise NotImplementedError
|
35
37
|
end
|
36
38
|
end
|
@@ -30,9 +30,11 @@ module Gruf
|
|
30
30
|
# Format the request into a JSON-friendly payload
|
31
31
|
#
|
32
32
|
# @param [Hash] payload The incoming request payload
|
33
|
+
# @param [Gruf::Controllers::Request] request The current controller request
|
34
|
+
# @param [Gruf::Interceptors::Timer::Result] result The timed result of the response
|
33
35
|
# @return [String] The JSON representation of the payload
|
34
36
|
#
|
35
|
-
def format(payload)
|
37
|
+
def format(payload, request:, result:)
|
36
38
|
payload.merge(format: 'json').to_json
|
37
39
|
end
|
38
40
|
end
|
@@ -28,9 +28,11 @@ module Gruf
|
|
28
28
|
# Format the request by only outputting the message body and params (if set to log params)
|
29
29
|
#
|
30
30
|
# @param [Hash] payload The incoming request payload
|
31
|
+
# @param [Gruf::Controllers::Request] request The current controller request
|
32
|
+
# @param [Gruf::Interceptors::Timer::Result] result The timed result of the response
|
31
33
|
# @return [String] The formatted string
|
32
34
|
#
|
33
|
-
def format(payload)
|
35
|
+
def format(payload, request:, result:)
|
34
36
|
time = payload.fetch(:duration, 0)
|
35
37
|
grpc_status = payload.fetch(:grpc_status, 'GRPC::Ok')
|
36
38
|
route_key = payload.fetch(:method, 'unknown')
|
@@ -61,12 +61,10 @@ module Gruf
|
|
61
61
|
#
|
62
62
|
# @return [String]
|
63
63
|
#
|
64
|
-
def call
|
65
|
-
return yield if options.fetch(:ignore_methods, [])
|
64
|
+
def call(&block)
|
65
|
+
return yield if options.fetch(:ignore_methods, [])&.include?(request.method_name)
|
66
66
|
|
67
|
-
result = Gruf::Interceptors::Timer.time
|
68
|
-
yield
|
69
|
-
end
|
67
|
+
result = Gruf::Interceptors::Timer.time(&block)
|
70
68
|
|
71
69
|
# Fetch log level options and merge with default...
|
72
70
|
log_level_map = LOG_LEVEL_MAP.merge(options.fetch(:log_levels, {}))
|
@@ -100,7 +98,7 @@ module Gruf
|
|
100
98
|
payload[:time] = Time.now.to_s
|
101
99
|
payload[:host] = Socket.gethostname
|
102
100
|
|
103
|
-
logger.send(type, formatter.format(payload))
|
101
|
+
logger.send(type, formatter.format(payload, request: request, result: result))
|
104
102
|
|
105
103
|
raise result.message unless result.successful?
|
106
104
|
|
@@ -113,7 +111,7 @@ module Gruf
|
|
113
111
|
# @return [::Gruf::Logger]
|
114
112
|
#
|
115
113
|
def logger
|
116
|
-
@logger ||= options.fetch(:logger,
|
114
|
+
@logger ||= (options.fetch(:logger, nil) || Gruf.logger)
|
117
115
|
end
|
118
116
|
|
119
117
|
##
|
@@ -164,26 +162,26 @@ module Gruf
|
|
164
162
|
end
|
165
163
|
|
166
164
|
##
|
167
|
-
# Redact any
|
165
|
+
# Redact any blocklisted params and return an updated hash
|
168
166
|
#
|
169
167
|
# @param [Hash] params The hash of parameters to sanitize
|
170
168
|
# @return [Hash] The sanitized params in hash form
|
171
169
|
#
|
172
170
|
def sanitize(params = {})
|
173
|
-
|
174
|
-
redacted_string = options.fetch(:redacted_string, 'REDACTED'
|
175
|
-
|
176
|
-
parts =
|
171
|
+
blocklists = (options.fetch(:blocklist, []) || []).map(&:to_s)
|
172
|
+
redacted_string = options.fetch(:redacted_string, nil) || 'REDACTED'
|
173
|
+
blocklists.each do |blocklist|
|
174
|
+
parts = blocklist.split('.').map(&:to_sym)
|
177
175
|
redact!(parts, 0, params, redacted_string)
|
178
176
|
end
|
179
177
|
params
|
180
178
|
end
|
181
179
|
|
182
180
|
##
|
183
|
-
# Helper method to recursively redact based on the
|
181
|
+
# Helper method to recursively redact based on the blocklist
|
184
182
|
#
|
185
|
-
# @param [Array] parts The
|
186
|
-
# @param [Integer] idx The current index of the
|
183
|
+
# @param [Array] parts The blocklist. ex. 'data.schema' -> [:data, :schema]
|
184
|
+
# @param [Integer] idx The current index of the blocklist
|
187
185
|
# @param [Hash] params The hash of parameters to sanitize
|
188
186
|
# @param [String] redacted_string The custom redact string
|
189
187
|
#
|