gruf 2.4.1 → 2.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1289ff979cec29b1c475fc7fb9292d3eab752229e5147b59f18c107fb34531d
4
- data.tar.gz: 55acd4dee980cd8274edbbc7308edc63e09b6a4b19e4a87a6d1d1e72b11dd46f
3
+ metadata.gz: bef9466a137b8d52bc76a4d24c65fef26b0701cff21eefb2ae9811e020dd619c
4
+ data.tar.gz: f3209bfefd0e3a7fe7ee03b6bcc7a417974593b924966521346d095d87de6d5d
5
5
  SHA512:
6
- metadata.gz: 99959b15a10222393883ac16b80c8550ba35190aa9a9858764687e4349d04db9f696d37fe9ed7fd7bf4db0df8e1841791760eb49de7633392720fe9f8175d733
7
- data.tar.gz: 22f6f6f2b9db9bea6768b1f3089c6502d02323e012efdad113becd430a94af4136d8d6f216d4e73079e66d59490ee379c6ba962d1c3f9f9649243fa0b382b57d
6
+ metadata.gz: 906fa455028407ea0ac54dceeb89c54b032ddf9e1090e85d14dabf8496aad91b22d19056fdf8e84d9836399518198ed7afffa50c1cc69ac9d8a4e5a43e53f40b
7
+ data.tar.gz: c3ec65443321ff6ac00b839bf3b6a9fed748e5f7ab2ec73ffd4476d1b4b7590ccd2d865ac4f5c6703a59c5ae89746b2964f58ee43e56c62a3df62e8bddae9271
@@ -2,6 +2,20 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
2
2
 
3
3
  ### Pending release
4
4
 
5
+ ### 2.4.2
6
+
7
+ - Added error handling for GRPC::Core::CallError, a low-level error in the grpc library that does not inherit
8
+ from StandardError. [#59]
9
+ - Removed `Thread.abort\_on\_exception = true`. Exceptions should be handled by gruf or the application,
10
+ and should not cause the server process to crash. [#59]
11
+ - Added guard for size of trailing metadata attached to grpc call. The default max for http2 trailing metadata
12
+ in the gRPC C library is 8kb. If we go over that limit (either through custom metadata attached to the
13
+ error by the application, or via the error payload encoded by the error serializer), the gRPC library
14
+ will throw RESOURCE\_EXHAUSTED. Gruf now detects this case, and attempts to prevent it by logging the
15
+ original error and substituting it with an internal error indicating that the metadata was too large. [#60]
16
+ - Truncate stack trace in error payload to help avoid overflowing the trailing metadata. Added backtrace\_limit
17
+ configuration parameter, which defaults to 10.[#60]
18
+
5
19
  ### 2.4.1
6
20
 
7
21
  - Safer configuration of GRPC::RpcServer. From now on, use `Gruf.rpc_server_options` for the params
@@ -12,8 +26,8 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
12
26
 
13
27
  ### 2.4.0
14
28
 
15
- - Added a hash of error log levels to RequestLogging interceptor, mapping error code to level of logging to use. To
16
- override the level of logging per error response, provide a map of codes to log level in options, key :log_levels.
29
+ - Added a hash of error log levels to RequestLogging interceptor, mapping error code to level of logging to use. To
30
+ override the level of logging per error response, provide a map of codes to log level in options, key :log_levels.
17
31
  The default is :error log level.
18
32
 
19
33
  ### 2.3.0
@@ -28,7 +42,7 @@ The default is :error log level.
28
42
 
29
43
  ### 2.2.1
30
44
 
31
- - Now changes proc title once server is ready to process incoming requests [#44]
45
+ - Now changes proc title once server is ready to process incoming requests [#44]
32
46
  - Gruf now requires gRPC 1.10.x+ due to various fixes and improvements in the gRPC core libraries
33
47
 
34
48
  ### 2.2.0
@@ -37,13 +51,13 @@ The default is :error log level.
37
51
 
38
52
  ### 2.1.1
39
53
 
40
- - Add ability to pass in client stub options into Gruf::Client
54
+ - Add ability to pass in client stub options into Gruf::Client
41
55
 
42
56
  ### 2.1.0
43
57
 
44
58
  - Add ability to list, clear, insert before, insert after, and remove to a server's interceptor
45
59
  registry
46
- - Ensure interceptors and services cannot be adjusted on the server after it starts to
60
+ - Ensure interceptors and services cannot be adjusted on the server after it starts to
47
61
  prevent threading issues
48
62
  - [#36], [#37] Adds `response_class`, `request_class`, and `service` accessors to controller request
49
63
 
@@ -106,22 +120,22 @@ Gruf 2.0 is a major shift from Gruf 1.0. See [UPGRADING.md](UPGRADING.md) for de
106
120
  - Instrumentation hooks now execute similarly to outer_around hooks; they can
107
121
  now instrument failures
108
122
  - Instrumentation hooks now pass a `RequestContext` object that contains information
109
- about the incoming request, instead of relying on instance variables
123
+ about the incoming request, instead of relying on instance variables
110
124
  - StatsD hook now sends success/failure metrics for endpoints
111
125
  - Add ability to turn off sending exception message on uncaught exception.
112
126
  - Add configuration to set the error message when an uncaught exception is
113
127
  handled by gruf.
114
- - Add a request logging hook for Rails-style request logging, with optional
115
- parameter logging, blacklists, and formatter support
128
+ - Add a request logging hook for Rails-style request logging, with optional
129
+ parameter logging, blacklists, and formatter support
116
130
  - Optimizations around Symbol casting within service calls
117
131
 
118
132
  ### 1.1.0
119
133
 
120
- - Add the ability for call options to the client, which enables deadline setting
134
+ - Add the ability for call options to the client, which enables deadline setting
121
135
 
122
136
  ### 1.0.0
123
137
 
124
- - Bump gRPC to 1.4
138
+ - Bump gRPC to 1.4
125
139
 
126
140
  ### 0.14.2
127
141
 
@@ -150,7 +164,7 @@ Gruf 2.0 is a major shift from Gruf 1.0. See [UPGRADING.md](UPGRADING.md) for de
150
164
  ### 0.12.0
151
165
 
152
166
  - Add ability to run multiple around hooks
153
- - Fix bug with error handling that caused error messages to repeat across streams
167
+ - Fix bug with error handling that caused error messages to repeat across streams
154
168
 
155
169
  ### 0.11.5
156
170
 
data/README.md CHANGED
@@ -87,9 +87,9 @@ end
87
87
 
88
88
  ::Gruf::Client.new(
89
89
  service: ::Demo::ThingService,
90
- client_options: [
90
+ client_options: {
91
91
  interceptors: [MyInterceptor.new]
92
- ])
92
+ })
93
93
  ```
94
94
 
95
95
  The `interceptors` option in `client_options` can accept either a `GRPC::ClientInterceptor` class or a
@@ -239,9 +239,11 @@ For the client, you'll need to point to the public certificate:
239
239
  ```ruby
240
240
  ::Gruf::Client.new(
241
241
  service: Demo::ThingService,
242
- ssl_certificate: 'x509 public certificate here',
243
- # OR
244
- ssl_certificate_file: '/path/to/my.crt'
242
+ options: {
243
+ ssl_certificate: 'x509 public certificate here',
244
+ # OR
245
+ ssl_certificate_file: '/path/to/my.crt'
246
+ }
245
247
  )
246
248
  ```
247
249
 
@@ -485,6 +487,8 @@ gruf that you can use today:
485
487
 
486
488
  * [gruf-zipkin](https://github.com/bigcommerce/gruf-zipkin) - Provides a [Zipkin](https://zipkin.io)
487
489
  integration
490
+ * [gruf-lightstep](https://github.com/bigcommerce/gruf-lightstep) - Provides a seamless
491
+ [LightStep](https://lightstep.com) integration
488
492
  * [gruf-circuit-breaker](https://github.com/bigcommerce/gruf-circuit-breaker) - Circuit breaker
489
493
  support for services
490
494
  * [gruf-profiler](https://github.com/bigcommerce/gruf-profiler) - Profiles and provides memory usage
@@ -36,6 +36,7 @@ module Gruf
36
36
  append_server_errors_to_trailing_metadata: true,
37
37
  use_default_interceptors: true,
38
38
  backtrace_on_error: false,
39
+ backtrace_limit: 10,
39
40
  use_exception_message: true,
40
41
  internal_error_message: 'Internal Server Error',
41
42
  event_listener_proc: nil,
@@ -71,8 +71,8 @@ module Gruf
71
71
  send(method_key, &block)
72
72
  end
73
73
  rescue GRPC::BadStatus
74
- raise # passthrough
75
- rescue StandardError => e
74
+ raise # passthrough, to be caught by Gruf::Interceptors::Timer
75
+ rescue GRPC::Core::CallError, StandardError => e # CallError is not a StandardError
76
76
  set_debug_info(e.message, e.backtrace) if Gruf.backtrace_on_error
77
77
  error_message = Gruf.use_exception_message ? e.message : Gruf.internal_error_message
78
78
  fail!(:internal, :unknown, error_message)
@@ -50,6 +50,13 @@ module Gruf
50
50
  data_loss: GRPC::DataLoss
51
51
  }.freeze
52
52
 
53
+ # Default limit on trailing metadata is 8KB. We need to be careful
54
+ # not to overflow this limit, or the response message will never
55
+ # be sent. Instead, resource_exhausted will be thrown.
56
+ MAX_METADATA_SIZE = 7.5 * 1_024
57
+ METADATA_SIZE_EXCEEDED_CODE = 'metadata_size_exceeded'.freeze
58
+ METADATA_SIZE_EXCEEDED_MSG = 'Metadata too long, risks exceeding http2 trailing metadata limit.'.freeze
59
+
53
60
  # @return [Symbol] The given internal gRPC code for the error
54
61
  attr_accessor :code
55
62
  # @return [Symbol] An arbitrary application code that can be used for logical processing of the error by the client
@@ -58,8 +65,8 @@ module Gruf
58
65
  attr_accessor :message
59
66
  # @return [Array] An array of field errors that can be returned by the server
60
67
  attr_accessor :field_errors
61
- # @return [Object] A hash of debugging information, such as a stack trace and exception name, that can be used to
62
- # debug an given error response. This is sent by the server over the trailing metadata.
68
+ # @return [Errors::DebugInfo] A object containing debugging information, such as a stack trace and exception name,
69
+ # that can be used to debug an given error response. This is sent by the server over the trailing metadata.
63
70
  attr_accessor :debug_info
64
71
  # @return [GRPC::BadStatus] The gRPC BadStatus error object that was generated
65
72
  attr_writer :grpc_error
@@ -72,10 +79,11 @@ module Gruf
72
79
  # @param [Hash] args (Optional) An optional hash of arguments that will set fields on the error object
73
80
  #
74
81
  def initialize(args = {})
82
+ @field_errors = []
83
+ @metadata = {}
75
84
  args.each do |k, v|
76
85
  send("#{k}=", v) if respond_to?(k)
77
86
  end
78
- @field_errors = []
79
87
  end
80
88
 
81
89
  ##
@@ -130,16 +138,30 @@ module Gruf
130
138
  end
131
139
 
132
140
  ##
133
- # Append any appropriate errors to the gRPC call and properly update the output metadata
141
+ # Update the trailing metadata on the given gRPC call, including the error payload if configured
142
+ # to do so.
134
143
  #
135
144
  # @param [GRPC::ActiveCall] active_call The marshalled gRPC call
136
- # @return [Error] Return the error itself with the GRPC::ActiveCall attached and error metadata appended
145
+ # @return [Error] Return the error itself after updating metadata on the given gRPC call.
146
+ # In the case of a metadata overflow error, we replace the current error with
147
+ # a new one that won't cause a low-level http2 error.
137
148
  #
138
149
  def attach_to_call(active_call)
139
150
  metadata[Gruf.error_metadata_key.to_sym] = serialize if Gruf.append_server_errors_to_trailing_metadata
140
- if !metadata.empty? && active_call && active_call.respond_to?(:output_metadata)
141
- active_call.output_metadata.update(metadata)
151
+ return self if metadata.empty? || !active_call || !active_call.respond_to?(:output_metadata)
152
+
153
+ # Check if we've overflown the maximum size of output metadata. If so,
154
+ # log a warning and replace the metadata with something smaller to avoid
155
+ # resource exhausted errors.
156
+ if metadata.inspect.size > MAX_METADATA_SIZE
157
+ code = METADATA_SIZE_EXCEEDED_CODE
158
+ msg = METADATA_SIZE_EXCEEDED_MSG
159
+ logger.warn "#{code}: #{msg} Original error: #{to_h.inspect}"
160
+ err = Gruf::Error.new(code: :internal, app_code: code, message: msg)
161
+ return err.attach_to_call(active_call)
142
162
  end
163
+
164
+ active_call.output_metadata.update(metadata)
143
165
  self
144
166
  end
145
167
 
@@ -30,7 +30,12 @@ module Gruf
30
30
  #
31
31
  def initialize(detail, stack_trace = [])
32
32
  @detail = detail
33
- @stack_trace = stack_trace.is_a?(String) ? stack_trace.split("\n") : stack_trace
33
+ @stack_trace = (stack_trace.is_a?(String) ? stack_trace.split("\n") : stack_trace)
34
+
35
+ # Limit the size of the stack trace to reduce risk of overflowing metadata
36
+ stack_trace_limit = Gruf.backtrace_limit.to_i
37
+ stack_trace_limit = 10 if stack_trace_limit < 0
38
+ @stack_trace = @stack_trace[0..stack_trace_limit] if stack_trace_limit > 0
34
39
  end
35
40
 
36
41
  ##
@@ -203,8 +203,6 @@ module Gruf
203
203
  #
204
204
  # :nocov:
205
205
  def setup_signal_handlers
206
- Thread.abort_on_exception = true
207
-
208
206
  Signal.trap('INT') do
209
207
  @stop_server = true
210
208
  @stop_server_cv.broadcast
@@ -14,5 +14,5 @@
14
14
  # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15
15
  #
16
16
  module Gruf
17
- VERSION = '2.4.1'.freeze
17
+ VERSION = '2.4.2'.freeze
18
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gruf
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.1
4
+ version: 2.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shaun McCormick
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-07 00:00:00.000000000 Z
11
+ date: 2018-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler