gruf 2.8.1 → 2.11.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 +38 -3
- data/README.md +2 -2
- data/gruf.gemspec +28 -9
- data/lib/gruf/cli/executor.rb +1 -1
- data/lib/gruf/client/error.rb +4 -1
- data/lib/gruf/client.rb +30 -5
- data/lib/gruf/configuration.rb +99 -17
- data/lib/gruf/controllers/base.rb +8 -3
- data/lib/gruf/controllers/request.rb +20 -12
- data/lib/gruf/controllers/service_binder.rb +1 -1
- data/lib/gruf/error.rb +17 -9
- data/lib/gruf/errors/debug_info.rb +4 -2
- data/lib/gruf/errors/field.rb +6 -3
- data/lib/gruf/hooks/executor.rb +1 -1
- data/lib/gruf/interceptors/base.rb +6 -3
- 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/interceptor.rb +12 -14
- data/lib/gruf/interceptors/instrumentation/statsd.rb +2 -4
- data/lib/gruf/interceptors/timer.rb +8 -1
- data/lib/gruf/outbound/request_context.rb +12 -7
- data/lib/gruf/response.rb +12 -6
- data/lib/gruf/serializers/errors/base.rb +2 -1
- data/lib/gruf/server.rb +6 -4
- data/lib/gruf/synchronized_client.rb +2 -0
- data/lib/gruf/timer.rb +7 -2
- data/lib/gruf/version.rb +1 -1
- data/lib/gruf.rb +1 -1
- metadata +229 -31
@@ -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?
|
@@ -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, {}))
|
@@ -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
|
#
|
@@ -25,7 +25,7 @@ module Gruf
|
|
25
25
|
##
|
26
26
|
# Push data to StatsD, only doing so if a client is set
|
27
27
|
#
|
28
|
-
def call
|
28
|
+
def call(&block)
|
29
29
|
unless client
|
30
30
|
Gruf.logger.error 'Statsd module loaded, but no client configured!'
|
31
31
|
return yield
|
@@ -33,9 +33,7 @@ module Gruf
|
|
33
33
|
|
34
34
|
client.increment(route_key)
|
35
35
|
|
36
|
-
result = Gruf::Interceptors::Timer.time
|
37
|
-
yield
|
38
|
-
end
|
36
|
+
result = Gruf::Interceptors::Timer.time(&block)
|
39
37
|
|
40
38
|
client.increment("#{route_key}.#{postfix(result.successful?)}")
|
41
39
|
client.timing(route_key, result.elapsed)
|
@@ -24,8 +24,15 @@ module Gruf
|
|
24
24
|
##
|
25
25
|
# Represents a timed result for an interceptor
|
26
26
|
#
|
27
|
+
# @property [Object] message The protobuf message
|
28
|
+
# @property [Float] elapsed The elapsed time of the request
|
29
|
+
#
|
27
30
|
class Result
|
31
|
+
# @!attribute [r] message
|
32
|
+
# @return [Object] The returned protobuf message
|
28
33
|
attr_reader :message
|
34
|
+
# @return [r] elapsed
|
35
|
+
# @return [Float] The time elapsed for this interceptor to execute
|
29
36
|
attr_reader :elapsed
|
30
37
|
|
31
38
|
##
|
@@ -50,7 +57,7 @@ module Gruf
|
|
50
57
|
# @return [String] The name of the message class
|
51
58
|
#
|
52
59
|
def message_class_name
|
53
|
-
@message.class.name
|
60
|
+
@message.class.name.to_s
|
54
61
|
end
|
55
62
|
|
56
63
|
##
|
@@ -21,15 +21,20 @@ module Gruf
|
|
21
21
|
# Encapsulates the context of an outbound client request
|
22
22
|
#
|
23
23
|
class RequestContext
|
24
|
-
#
|
24
|
+
# @!attribute [r] type
|
25
|
+
# @return [Symbol]
|
25
26
|
attr_reader :type
|
26
|
-
#
|
27
|
+
# @!attribute [r] requests
|
28
|
+
# @return [Enumerable] requests
|
27
29
|
attr_reader :requests
|
28
|
-
#
|
30
|
+
# @!attribute [r] call
|
31
|
+
# @return [GRPC::ActiveCall]
|
29
32
|
attr_reader :call
|
30
|
-
#
|
33
|
+
# @!attribute [r] method
|
34
|
+
# @return [Method] method
|
31
35
|
attr_reader :method
|
32
|
-
#
|
36
|
+
# @!attribute [r] metadata
|
37
|
+
# @return [Hash] metadata
|
33
38
|
attr_reader :metadata
|
34
39
|
|
35
40
|
##
|
@@ -55,7 +60,7 @@ module Gruf
|
|
55
60
|
# @return [String]
|
56
61
|
#
|
57
62
|
def method_name
|
58
|
-
@method.to_s.split('/').last
|
63
|
+
@method.to_s.split('/').last.to_s
|
59
64
|
end
|
60
65
|
|
61
66
|
##
|
@@ -64,7 +69,7 @@ module Gruf
|
|
64
69
|
# @return [String]
|
65
70
|
#
|
66
71
|
def route_key
|
67
|
-
@method[1
|
72
|
+
@method[1..].to_s.underscore.tr('/', '.')
|
68
73
|
end
|
69
74
|
end
|
70
75
|
end
|
data/lib/gruf/response.rb
CHANGED
@@ -20,17 +20,23 @@ module Gruf
|
|
20
20
|
# Wraps the active call operation to provide metadata and timing around the request
|
21
21
|
#
|
22
22
|
class Response
|
23
|
-
#
|
23
|
+
# @!attribute [r] operation
|
24
|
+
# @return [GRPC::ActiveCall::Operation] The operation that was executed for the given request
|
24
25
|
attr_reader :operation
|
25
|
-
#
|
26
|
+
# @!attribute [r] metadata
|
27
|
+
# @return [Hash] The metadata that was attached to the operation
|
26
28
|
attr_reader :metadata
|
27
|
-
#
|
29
|
+
# @!attribute [r] trailing_metadata
|
30
|
+
# @return [Hash] The trailing metadata that the service returned
|
28
31
|
attr_reader :trailing_metadata
|
29
|
-
#
|
32
|
+
# @!attribute [r] deadline
|
33
|
+
# @return [Time] The set deadline on the call
|
30
34
|
attr_reader :deadline
|
31
|
-
#
|
35
|
+
# @!attribute [r] cancelled
|
36
|
+
# @return [Boolean] Whether or not the operation was cancelled
|
32
37
|
attr_reader :cancelled
|
33
|
-
#
|
38
|
+
# @!attribute [r] execution_time
|
39
|
+
# @return [Float] The time that the request took to execute
|
34
40
|
attr_reader :execution_time
|
35
41
|
|
36
42
|
##
|
@@ -22,7 +22,8 @@ module Gruf
|
|
22
22
|
# Base class for serialization of errors for transport across the grpc protocol
|
23
23
|
#
|
24
24
|
class Base
|
25
|
-
#
|
25
|
+
# @!attribute [r] error
|
26
|
+
# @return [Gruf::Error|String] The error being serialized
|
26
27
|
attr_reader :error
|
27
28
|
|
28
29
|
##
|
data/lib/gruf/server.rb
CHANGED
@@ -25,9 +25,11 @@ module Gruf
|
|
25
25
|
|
26
26
|
include Gruf::Loggable
|
27
27
|
|
28
|
-
#
|
28
|
+
# @!attribute [r] port
|
29
|
+
# @return [Integer] The port the server is bound to
|
29
30
|
attr_reader :port
|
30
|
-
#
|
31
|
+
# @!attribute [r] options
|
32
|
+
# @return [Hash] Hash of options passed into the server
|
31
33
|
attr_reader :options
|
32
34
|
|
33
35
|
##
|
@@ -69,9 +71,9 @@ module Gruf
|
|
69
71
|
|
70
72
|
server = if @event_listener_proc
|
71
73
|
server_options[:event_listener_proc] = @event_listener_proc
|
72
|
-
Gruf::InstrumentableGrpcServer.new(server_options)
|
74
|
+
Gruf::InstrumentableGrpcServer.new(**server_options)
|
73
75
|
else
|
74
|
-
GRPC::RpcServer.new(server_options)
|
76
|
+
GRPC::RpcServer.new(**server_options)
|
75
77
|
end
|
76
78
|
|
77
79
|
@port = server.add_http2_port(@hostname, ssl_credentials)
|
data/lib/gruf/timer.rb
CHANGED
@@ -29,10 +29,15 @@ module Gruf
|
|
29
29
|
# result.time # => 1.10123
|
30
30
|
# result.result # => 'my_thing_is_done'
|
31
31
|
#
|
32
|
+
# @property [Object] result The result of the block that was called
|
33
|
+
# @property [Float] time The time, in ms, of the block execution
|
34
|
+
#
|
32
35
|
class Result
|
33
|
-
#
|
36
|
+
# @!attribute [r] result
|
37
|
+
# @return [mixed]
|
34
38
|
attr_reader :result
|
35
|
-
#
|
39
|
+
# @!attribute [r] time
|
40
|
+
# @return [Float]
|
36
41
|
attr_reader :time
|
37
42
|
|
38
43
|
##
|
data/lib/gruf/version.rb
CHANGED
data/lib/gruf.rb
CHANGED
@@ -40,7 +40,7 @@ require_relative 'gruf/client'
|
|
40
40
|
require_relative 'gruf/synchronized_client'
|
41
41
|
require_relative 'gruf/instrumentable_grpc_server'
|
42
42
|
require_relative 'gruf/server'
|
43
|
-
require_relative 'gruf/integrations/rails/railtie' if defined?(Rails)
|
43
|
+
require_relative 'gruf/integrations/rails/railtie' if defined?(::Rails)
|
44
44
|
|
45
45
|
##
|
46
46
|
# Initializes configuration of gruf core module
|