gruf 2.2.2 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +107 -12
  3. data/CODE_OF_CONDUCT.md +38 -41
  4. data/README.md +8 -360
  5. data/bin/gruf +2 -12
  6. data/gruf.gemspec +31 -7
  7. data/lib/gruf/cli/executor.rb +102 -0
  8. data/lib/gruf/client/error.rb +68 -0
  9. data/lib/gruf/client/error_factory.rb +105 -0
  10. data/lib/gruf/client.rb +52 -38
  11. data/lib/gruf/configuration.rb +25 -5
  12. data/lib/gruf/controllers/base.rb +35 -12
  13. data/lib/gruf/controllers/request.rb +21 -10
  14. data/lib/gruf/controllers/service_binder.rb +38 -6
  15. data/lib/gruf/error.rb +34 -9
  16. data/lib/gruf/errors/debug_info.rb +9 -2
  17. data/lib/gruf/errors/field.rb +2 -0
  18. data/lib/gruf/errors/helpers.rb +5 -0
  19. data/lib/gruf/hooks/base.rb +34 -0
  20. data/lib/gruf/hooks/executor.rb +47 -0
  21. data/lib/gruf/hooks/registry.rb +159 -0
  22. data/lib/gruf/instrumentable_grpc_server.rb +64 -0
  23. data/lib/gruf/integrations/rails/railtie.rb +10 -0
  24. data/lib/gruf/interceptors/active_record/connection_reset.rb +4 -3
  25. data/lib/gruf/interceptors/authentication/basic.rb +10 -2
  26. data/lib/gruf/interceptors/base.rb +3 -0
  27. data/lib/gruf/interceptors/client_interceptor.rb +117 -0
  28. data/lib/gruf/interceptors/context.rb +6 -4
  29. data/lib/gruf/interceptors/instrumentation/output_metadata_timer.rb +5 -4
  30. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/base.rb +5 -1
  31. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/logstash.rb +5 -1
  32. data/lib/gruf/interceptors/instrumentation/request_logging/formatters/plain.rb +5 -1
  33. data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +60 -29
  34. data/lib/gruf/interceptors/instrumentation/statsd.rb +5 -4
  35. data/lib/gruf/interceptors/registry.rb +6 -1
  36. data/lib/gruf/interceptors/server_interceptor.rb +2 -0
  37. data/lib/gruf/interceptors/timer.rb +12 -2
  38. data/lib/gruf/loggable.rb +2 -0
  39. data/lib/gruf/logging.rb +2 -0
  40. data/lib/gruf/outbound/request_context.rb +71 -0
  41. data/lib/gruf/response.rb +5 -2
  42. data/lib/gruf/serializers/errors/base.rb +2 -0
  43. data/lib/gruf/serializers/errors/json.rb +2 -0
  44. data/lib/gruf/server.rb +57 -23
  45. data/lib/gruf/synchronized_client.rb +97 -0
  46. data/lib/gruf/timer.rb +9 -6
  47. data/lib/gruf/version.rb +3 -1
  48. data/lib/gruf.rb +10 -0
  49. metadata +254 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b0e7891457a5fc0c9540a5347060adb81d943c2f
4
- data.tar.gz: b6f8e81ec7ad9fda50874fd0dfc34493dd2fabce
2
+ SHA256:
3
+ metadata.gz: bffd546b0bd27dcd8cd54146065623e73e0396211ae263985a197255bb8ec48a
4
+ data.tar.gz: 9b0364643ab5c1008a330ed61c8fba4458f9b075c34eea81acb10de4ee70f53d
5
5
  SHA512:
6
- metadata.gz: 7881d0383409066521a069f99d1a978c67c281a6142eef378e7204dcb394fd7d3e53d0a82453bc36097e611fada3daded6bc6c91a7697a7e924bcbbbef2f6a2f
7
- data.tar.gz: 6748606577097d0b5bf6cec7c4afe6254b71f3abd39b40a3a3ca1dde6ac43f43cb592fe14c83e51158e1929f25cb4e442cf2b2afe00f759332fe404558fee6e5
6
+ metadata.gz: 3ef4637ca552b572f77b270ccdc491c660b62d7c1d8ff85fe67151cf22f09e92f18a9b88b63d31e956411cb46380ba695e0eccc74d47a2095c8fc7d6ebfaf838
7
+ data.tar.gz: 0f38cc6c69487f1cab2ebc5e07b5a06de20f5e35d0000ad4c80a021288557aaaef2acf58fe254be6dc292ddd2e764976acfdd65578a7a0233c663dea83018eb3
data/CHANGELOG.md CHANGED
@@ -2,13 +2,108 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
2
2
 
3
3
  ### Pending release
4
4
 
5
+ ### 2.9.1
6
+
7
+ - Drop support for Ruby 2.4/2.5 to align with Ruby EOL schedule, supporting 2.6+ only
8
+ - Allow for float/TimeSpec timeout values on clients
9
+
10
+ ### 2.9.0
11
+
12
+ - Change to racially neutral terminology across library
13
+ - blacklist->blocklist
14
+ - master->main branch
15
+ - Explicitly declare development dependencies in gemspec
16
+ - Add script/e2e test for full e2e test in regression suite
17
+ - Explicitly declare [json gem](https://rubygems.org/gems/json) dependency
18
+ - Update to Rubocop 1.4, add in rubocop-rspec for spec tests
19
+ - Add Ruby 2.7, 3.0 support
20
+
21
+ ### 2.8.1
22
+
23
+ - Fix issue with --suppress-default-interceptors not working [#95]
24
+ - Loosen rake development dependency to >= 10.0 [#97]
25
+
26
+ ### 2.8.0
27
+
28
+ - Pass the controller request object into the request logging formatters [#92]
29
+
30
+ ### 2.7.1
31
+
32
+ - Add `channel_credentials` option to `Gruf::Client` and `default_channel_credentials` option to `Gruf::Configuration` [#85] [#87]
33
+
34
+ ### 2.7.0
35
+
36
+ - Add hook support for executing code paths before a server is started, and after a server stops
37
+
38
+ ### 2.6.1
39
+
40
+ - Add frozen_string_literal: true to files, update rubocop to 0.68
41
+
42
+ ### 2.6.0
43
+
44
+ - Drop Ruby 2.2 support
45
+ - Abstract gruf controller's send to make it usable in filters
46
+ - Adjusts configuration reset into a Railtie for Rails systems to ensure proper OOE
47
+ - Bump rubocop to 0.64, address violations, update activesupport/concurrent-ruby dependencies to have a min version
48
+
49
+ ### 2.5.2
50
+
51
+ - Log ok/validation responses at DEBUG levels to prevent log stampeding in high-volume environments
52
+
53
+ ### 2.5.1
54
+
55
+ - Ensure `timeout` is an int when passed as a client option to a gRPC client
56
+ - Add `bound_service` reader to `Gruf::Controllers::Base` for finding the service bound to the given controller
57
+
58
+ ### 2.5.0
59
+
60
+ - Client exceptions raised now contain mapped subclasses, such as `Gruf::Client::Errors::InvalidArgument`
61
+ - Client exceptions will also now catch StandardError and GRPC::Core errors, and handle them as Internal errors
62
+ - Added SynchronizedClient which prevents multiple calls to the same endpoint with the same params at
63
+ a given time. This is useful for mitigating thundering herds. To skip this behavior for certain endpoints,
64
+ pass the `options[:unsynchronized_methods]` param with a list of method names (as symbols).
65
+
66
+ ### 2.4.2
67
+
68
+ - Added error handling for GRPC::Core::CallError, a low-level error in the grpc library that does not inherit
69
+ from StandardError. [#59]
70
+ - Removed `Thread.abort\_on\_exception = true`. Exceptions should be handled by gruf or the application,
71
+ and should not cause the server process to crash. [#59]
72
+ - Added guard for size of trailing metadata attached to grpc call. The default max for http2 trailing metadata
73
+ in the gRPC C library is 8kb. If we go over that limit (either through custom metadata attached to the
74
+ error by the application, or via the error payload encoded by the error serializer), the gRPC library
75
+ will throw RESOURCE\_EXHAUSTED. Gruf now detects this case, and attempts to prevent it by logging the
76
+ original error and substituting it with an internal error indicating that the metadata was too large. [#60]
77
+ - Truncate stack trace in error payload to help avoid overflowing the trailing metadata. Added backtrace\_limit
78
+ configuration parameter, which defaults to 10.[#60]
79
+
80
+ ### 2.4.1
81
+
82
+ - Safer configuration of GRPC::RpcServer. From now on, use `Gruf.rpc_server_options` for the params
83
+ to be sent to GPRC::RpcServer. Also provide sane defaults for params for GRPC::RpcServer. [#55]
84
+ - Added ability to monitor `RESOURCE_EXHAUSTED` and `UNIMPLEMENTED`. By setting `event_listener_proc` in
85
+ the Gruf configuration, you will receive a callback when these events occur. The parameter to your
86
+ callback will be a symbol (`:thread_pool_exhausted` or `:unimplemented`). Others may be added in the future.
87
+
88
+ ### 2.4.0
89
+
90
+ - Added a hash of error log levels to RequestLogging interceptor, mapping error code to level of logging to use. To
91
+ override the level of logging per error response, provide a map of codes to log level in options, key :log_levels.
92
+ The default is :error log level.
93
+
94
+ ### 2.3.0
95
+
96
+ - Add Gruf::Interceptors::ClientInterceptor for intercepting outbound client calls
97
+ - Add command-line arguments to the gruf binstub
98
+ - Add ability to specify server hostname via CLI argument
99
+
5
100
  ### 2.2.2
6
101
 
7
- - Added ignore_methods option for RequestLogging interceptor [#45]
102
+ - Add ignore_methods option for RequestLogging interceptor [#45]
8
103
 
9
104
  ### 2.2.1
10
105
 
11
- - Now changes proc title once server is ready to process incoming requests [#44]
106
+ - Now changes proc title once server is ready to process incoming requests [#44]
12
107
  - Gruf now requires gRPC 1.10.x+ due to various fixes and improvements in the gRPC core libraries
13
108
 
14
109
  ### 2.2.0
@@ -17,13 +112,13 @@ Changelog for the gruf gem. This includes internal history before the gem was ma
17
112
 
18
113
  ### 2.1.1
19
114
 
20
- - Add ability to pass in client stub options into Gruf::Client
115
+ - Add ability to pass in client stub options into Gruf::Client
21
116
 
22
117
  ### 2.1.0
23
118
 
24
119
  - Add ability to list, clear, insert before, insert after, and remove to a server's interceptor
25
120
  registry
26
- - Ensure interceptors and services cannot be adjusted on the server after it starts to
121
+ - Ensure interceptors and services cannot be adjusted on the server after it starts to
27
122
  prevent threading issues
28
123
  - [#36], [#37] Adds `response_class`, `request_class`, and `service` accessors to controller request
29
124
 
@@ -66,11 +161,11 @@ Gruf 2.0 is a major shift from Gruf 1.0. See [UPGRADING.md](UPGRADING.md) for de
66
161
  ### 1.2.4
67
162
 
68
163
  - Loosen explicit Protobuf dependency now that 3.4.0.2 is released
69
- - Guard against nil params in logger blacklist
164
+ - Guard against nil params in logger blocklist
70
165
 
71
166
  ### 1.2.3
72
167
 
73
- - Support nested blacklist parameters in path.to.key format
168
+ - Support nested blocklist parameters in path.to.key format
74
169
 
75
170
  ### 1.2.2
76
171
 
@@ -86,22 +181,22 @@ Gruf 2.0 is a major shift from Gruf 1.0. See [UPGRADING.md](UPGRADING.md) for de
86
181
  - Instrumentation hooks now execute similarly to outer_around hooks; they can
87
182
  now instrument failures
88
183
  - Instrumentation hooks now pass a `RequestContext` object that contains information
89
- about the incoming request, instead of relying on instance variables
184
+ about the incoming request, instead of relying on instance variables
90
185
  - StatsD hook now sends success/failure metrics for endpoints
91
186
  - Add ability to turn off sending exception message on uncaught exception.
92
187
  - Add configuration to set the error message when an uncaught exception is
93
188
  handled by gruf.
94
- - Add a request logging hook for Rails-style request logging, with optional
95
- parameter logging, blacklists, and formatter support
189
+ - Add a request logging hook for Rails-style request logging, with optional
190
+ parameter logging, blocklists, and formatter support
96
191
  - Optimizations around Symbol casting within service calls
97
192
 
98
193
  ### 1.1.0
99
194
 
100
- - Add the ability for call options to the client, which enables deadline setting
195
+ - Add the ability for call options to the client, which enables deadline setting
101
196
 
102
197
  ### 1.0.0
103
198
 
104
- - Bump gRPC to 1.4
199
+ - Bump gRPC to 1.4
105
200
 
106
201
  ### 0.14.2
107
202
 
@@ -130,7 +225,7 @@ Gruf 2.0 is a major shift from Gruf 1.0. See [UPGRADING.md](UPGRADING.md) for de
130
225
  ### 0.12.0
131
226
 
132
227
  - Add ability to run multiple around hooks
133
- - Fix bug with error handling that caused error messages to repeat across streams
228
+ - Fix bug with error handling that caused error messages to repeat across streams
134
229
 
135
230
  ### 0.11.5
136
231
 
data/CODE_OF_CONDUCT.md CHANGED
@@ -1,49 +1,46 @@
1
- # Contributor Code of Conduct
1
+ # Contributor Covenant Code of Conduct
2
2
 
3
- As contributors and maintainers of this project, and in the interest of
4
- fostering an open and welcoming community, we pledge to respect all people who
5
- contribute through reporting issues, posting feature requests, updating
6
- documentation, submitting pull requests or patches, and other activities.
3
+ ## Our Pledge
7
4
 
8
- We are committed to making participation in this project a harassment-free
9
- experience for everyone, regardless of level of experience, gender, gender
10
- identity and expression, sexual orientation, disability, personal appearance,
11
- body size, race, ethnicity, age, religion, or nationality.
5
+ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to creating a positive environment include:
10
+
11
+ * Using welcoming and inclusive language
12
+ * Being respectful of differing viewpoints and experiences
13
+ * Gracefully accepting constructive criticism
14
+ * Focusing on what is best for the community
15
+ * Showing empathy towards other community members
12
16
 
13
17
  Examples of unacceptable behavior by participants include:
14
18
 
15
- * The use of sexualized language or imagery
16
- * Personal attacks
17
- * Trolling or insulting/derogatory comments
19
+ * The use of sexualized language or imagery and unwelcome sexual attention or advances
20
+ * Trolling, insulting/derogatory comments, and personal or political attacks
18
21
  * Public or private harassment
19
- * Publishing other's private information, such as physical or electronic
20
- addresses, without explicit permission
21
- * Other unethical or unprofessional conduct
22
-
23
- Project maintainers have the right and responsibility to remove, edit, or
24
- reject comments, commits, code, wiki edits, issues, and other contributions
25
- that are not aligned to this Code of Conduct, or to ban temporarily or
26
- permanently any contributor for other behaviors that they deem inappropriate,
27
- threatening, offensive, or harmful.
28
-
29
- By adopting this Code of Conduct, project maintainers commit themselves to
30
- fairly and consistently applying these principles to every aspect of managing
31
- this project. Project maintainers who do not follow or enforce the Code of
32
- Conduct may be permanently removed from the project team.
33
-
34
- This code of conduct applies both within project spaces and in public spaces
35
- when an individual is representing the project or its community.
36
-
37
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
- reported by contacting a project maintainer at splittingred@gmail.com. All
39
- complaints will be reviewed and investigated and will result in a response that
40
- is deemed necessary and appropriate to the circumstances. Maintainers are
41
- obligated to maintain confidentiality with regard to the reporter of an
42
- incident.
43
-
44
- This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
- version 1.3.0, available at
46
- [http://contributor-covenant.org/version/1/3/0/][version]
22
+ * Publishing others' private information, such as a physical or electronic address, without explicit permission
23
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
24
+
25
+ ## Our Responsibilities
26
+
27
+ Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28
+
29
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ ## Scope
32
+
33
+ This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34
+
35
+ ## Enforcement
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at engineering@bigcommerce.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38
+
39
+ Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40
+
41
+ ## Attribution
42
+
43
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
47
44
 
48
45
  [homepage]: http://contributor-covenant.org
49
- [version]: http://contributor-covenant.org/version/1/3/0/
46
+ [version]: http://contributor-covenant.org/version/1/4/
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # gruf - gRPC Ruby Framework
2
2
 
3
- [![Build Status](https://travis-ci.org/bigcommerce/gruf.svg?branch=master)](https://travis-ci.org/bigcommerce/gruf) [![Gem Version](https://badge.fury.io/rb/gruf.svg)](https://badge.fury.io/rb/gruf) [![Documentation](https://inch-ci.org/github/bigcommerce/gruf.svg?branch=master)](https://inch-ci.org/github/bigcommerce/gruf?branch=master)
3
+ [![CircleCI](https://circleci.com/gh/bigcommerce/gruf/tree/main.svg?style=svg)](https://circleci.com/gh/bigcommerce/gruf/tree/main) [![Gem Version](https://badge.fury.io/rb/gruf.svg)](https://badge.fury.io/rb/gruf) [![Documentation](https://inch-ci.org/github/bigcommerce/gruf.svg?branch=main)](https://inch-ci.org/github/bigcommerce/gruf?branch=main)
4
4
 
5
- gruf is a Ruby framework that wraps the [gRPC Ruby library](https://github.com/grpc/grpc/tree/master/src/ruby) to
5
+ gruf is a Ruby framework that wraps the [gRPC Ruby library](https://github.com/grpc/grpc/tree/main/src/ruby) to
6
6
  provide a more streamlined integration into Ruby and Ruby on Rails applications.
7
7
 
8
8
  It provides an abstracted server and client for gRPC services, along with other tools to help get gRPC services in Ruby
@@ -17,372 +17,20 @@ up fast and efficiently at scale. Some of its features include:
17
17
  still preserving gRPC BadStatus codes
18
18
  * Server and client execution timings in responses
19
19
 
20
- gruf currently has active support for gRPC 1.10.x+. gruf is compatible and tested with Ruby 2.2-2.5.
21
- gruf is also not [Rails](https://github.com/rails/rails)-specific, and can be used in any Ruby framework
22
- (such as [Grape](https://github.com/ruby-grape/grape), for instance).
20
+ gruf currently has active support for gRPC 1.10.x+. gruf is compatible and tested with Ruby 2.2-2.7.
21
+ gruf is also not [Rails](https://github.com/rails/rails)-specific, and can be used in any Ruby framework
22
+ (such as [Grape](https://github.com/ruby-grape/grape) or [dry-rb](https://dry-rb.org/), for instance).
23
23
 
24
- ## Installation
24
+ ### Getting Started
25
25
 
26
- ```ruby
27
- gem 'gruf'
28
- ```
29
-
30
- Then in an initializer or before use:
31
-
32
- ```ruby
33
- require 'gruf'
34
- ```
35
-
36
- Make sure to review [UPGRADING.md](https://github.com/bigcommerce/gruf/blob/master/UPGRADING.md)
37
- if you are upgrading gruf between minor or major versions.
38
-
39
- ### Client
40
-
41
- Add an initializer:
42
-
43
- ```ruby
44
- require 'gruf'
45
-
46
- Gruf.configure do |c|
47
- c.default_client_host = 'grpc.service.com:9003'
48
- end
49
- ```
50
-
51
- If you don't explicitly set `default_client_host`, you will need to pass it into the client options, like so:
52
-
53
- ```ruby
54
- client = ::Gruf::Client.new(service: ::Demo::ThingService, options: {hostname: 'grpc.service.com:9003'})
55
- ```
56
-
57
- From there, you can instantiate a client given a stub service (say on an SslCertificates proto with a GetSslCertificate call):
58
-
59
- ```ruby
60
- require 'gruf'
61
-
62
- id = args[:id].to_i.presence || 1
63
-
64
- begin
65
- client = ::Gruf::Client.new(service: ::Demo::ThingService)
66
- response = client.call(:GetMyThing, id: id)
67
- puts response.message.inspect
68
- rescue Gruf::Client::Error => e
69
- puts e.error.inspect
70
- end
71
- ```
72
-
73
- Note this returns a response object. The response object can provide `trailing_metadata` as well as a `execution_time`.
74
-
75
- ### Server
76
-
77
- Add an initializer:
78
-
79
- ```ruby
80
- require 'gruf'
81
-
82
- Gruf.configure do |c|
83
- c.server_binding_url = 'grpc.service.com:9003'
84
- end
85
- ```
86
-
87
- Next, setup some handlers based on your proto configurations in `/app/rpc/`. For example, for the Thing service, with a
88
- GetThingReq/GetThingResp call based on this proto:
89
-
90
- ```proto
91
- syntax = "proto3";
92
-
93
- package demo;
94
-
95
- service Jobs {
96
- rpc GetJob(GetJobReq) returns (GetJobResp) { }
97
- }
98
-
99
- message GetJobReq {
100
- uint64 id = 1;
101
- }
102
-
103
- message GetJobResp {
104
- uint64 id = 1;
105
- string name = 2;
106
- }
107
- ```
108
-
109
- You'd have this handler in `/app/rpc/demo/job_controller.rb`
110
-
111
- ```ruby
112
- module Demo
113
- class JobController < ::Gruf::Controllers::Base
114
- bind ::Demo::Jobs::Service
115
-
116
- ##
117
- # @return [Demo::GetJobResp] The job response
118
- #
119
- def get_job
120
- thing = Job.find(request.message.id)
121
-
122
- Demo::GetJobResp.new(id: thing.id)
123
- rescue
124
- fail!(:not_found, :job_not_found, "Failed to find Job with ID: #{request.message.id}")
125
- end
126
- end
127
- end
128
- ```
129
-
130
- Finally, you can start the server by running:
131
-
132
- ```bash
133
- bundle exec gruf
134
- ```
135
-
136
- ### Basic Authentication
137
-
138
- Gruf comes packaged in with a Basic Authentication interceptor. It takes in an array of supported
139
- username and password pairs (or password-only credentials).
140
-
141
- In Server:
142
-
143
- ```ruby
144
- Gruf.configure do |c|
145
- c.interceptors.use(
146
- Gruf::Interceptors::Authentication::Basic,
147
- credentials: [{
148
- username: 'my-username-here',
149
- password: 'my-password-here',
150
- },{
151
- username: 'another-username',
152
- password: 'another-password',
153
- },{
154
- password: 'a-password-only'
155
- }]
156
- )
157
- end
158
- ```
159
-
160
- In Client:
161
-
162
- ```ruby
163
- require 'gruf'
164
-
165
- id = args[:id].to_i.presence || 1
166
-
167
- options = {
168
- username: ENV.fetch('DEMO_THING_SERVICE_USERNAME'),
169
- password: ENV.fetch('DEMO_THING_SERVICE_PASSWORD')
170
- }
171
-
172
- begin
173
- client = ::Gruf::Client.new(service: ::Demo::ThingService, options: options)
174
- response = client.call(:GetMyThing, id: id)
175
- puts response.message.inspect
176
- rescue Gruf::Client::Error => e
177
- puts e.error.inspect
178
- end
179
- ```
180
-
181
- Supporting an array of credentials allow for unique credentials per service, or for easy credential
182
- rotation with zero downtime.
183
-
184
- ### SSL Configuration
185
-
186
- We don't recommend using TLS for gRPC, but instead using something like [linkerd](https://linkerd.io) for TLS
187
- encryption between services. If you need it, however, this library supports TLS.
188
-
189
- For the client, you'll need to point to the public certificate:
190
-
191
- ```ruby
192
- ::Gruf::Client.new(
193
- service: Demo::ThingService,
194
- ssl_certificate: 'x509 public certificate here',
195
- # OR
196
- ssl_certificate_file: '/path/to/my.crt'
197
- )
198
- ```
199
-
200
- If you want to run a server you'll need both the CRT and the key file if you want to do credentialed auth:
201
-
202
- ```ruby
203
- Gruf.configure do |c|
204
- c.use_ssl = true
205
- c.ssl_crt_file = "#{Rails.root}/config/ssl/#{Rails.env}.crt"
206
- c.ssl_key_file = "#{Rails.root}/config/ssl/#{Rails.env}.key"
207
- end
208
- ```
209
-
210
- ## Server Interceptors
211
-
212
- gruf supports interceptors around the grpc server calls, allowing you to perform actions around your service
213
- method calls. This can be used to add tracing data, connection resets in the grpc thread pool, further
214
- instrumentation, and other things.
215
-
216
- Adding a hook is as simple as creating a class that extends `Gruf::Interceptor::ServerInterceptor`,
217
- and a `call` method that yields control to get the method result:
218
-
219
- ```ruby
220
- class MyInterceptor < ::Gruf::Interceptors::ServerInterceptor
221
- def call
222
- yield
223
- end
224
- end
225
- ```
226
-
227
- Interceptors have access to the `request` object, which is the `Gruf::Controller::Request` object
228
- described above.
229
-
230
- ### Failing in an Interceptor
231
-
232
- Interceptors can fail requests with the same method calls as a controller:
233
-
234
- ```ruby
235
- class MyFailingInterceptor < ::Gruf::Interceptors::ServerInterceptor
236
- def call
237
- result = yield # this returns the protobuf message
238
- unless result.dont_hijack
239
- # we'll assume this "dont_hijack" attribute exists on the message for this example
240
- fail!(:internal, :hijacked, 'Hijack all the things!')
241
- end
242
- result
243
- end
244
- end
245
- ```
246
-
247
- Similarly, you can raise `GRPC::BadStatus` calls to trigger similar errors without accompanying metadata.
248
-
249
- ### Configuring Interceptors
250
-
251
- From there, the interceptor can be added to the server manually (if not executing via `bundle exec gruf`):
252
-
253
- ```ruby
254
- server = Gruf::Server.new
255
- server.add_interceptor(MyInterceptor, option_foo: 'value 123')
256
- ```
257
-
258
- Or, alternatively, the more common method of passing them into the `interceptors` configuration hash:
259
-
260
- ```ruby
261
- Gruf.configure do |c|
262
- c.interceptors.use(MyInterceptor, option_foo: 'value 123')
263
- end
264
- ```
265
-
266
- Interceptors each wrap the call and are run recursively within each other. This means that if you have
267
- three interceptors - `Interceptor1`, `Interceptor2`, and `Interceptor3` - they will run in FIFO
268
- (first in, first out) order. `Interceptor1` will run, yielding to `Interceptor2`,
269
- which will then yield to `Interceptor3`, which will then yield to your service method call,
270
- ending the chain.
271
-
272
- You can utilize the `insert_before` and `insert_after` methods to maintain order:
273
-
274
- ```ruby
275
- Gruf.configure do |c|
276
- c.interceptors.use(Interceptor1)
277
- c.interceptors.use(Interceptor2)
278
- c.interceptors.insert_before(Interceptor2, Interceptor3) # 3 will now happen before 2
279
- c.interceptors.insert_after(Interceptor1, Interceptor4) # 4 will now happen after 1
280
- end
281
- ```
282
-
283
- By default, the ActiveRecord Connection Reset interceptor and Output Metadata Timing interceptor
284
- are loaded into gruf unless explicitly told not to via the `use_default_interceptors` configuration
285
- parameter.
286
-
287
- ## Instrumentation
288
-
289
- gruf comes out of the box with a couple of instrumentation interceptors packed in:
290
- output metadata timings and StatsD support.
291
-
292
- ### Output Metadata Timing
293
-
294
- Enabled by default, this will push timings for _successful responses_ through the response output
295
- metadata back to the client.
296
-
297
- ### StatsD
298
-
299
- The StatsD support is not enabled by default. To enable it, you'll want to do:
300
-
301
- ```ruby
302
- Gruf.configure do |c|
303
- c.interceptors.use(
304
- Gruf::Interceptors::Instrumentation::Statsd,
305
- client: ::Statsd.new('my.statsd.host', 8125),
306
- prefix: 'my_application_prefix.rpc'
307
- )
308
- end
309
- ```
310
-
311
- This will measure counts and timings for each endpoint.
312
-
313
- ### Request Logging
314
-
315
- Gruf 1.2+ comes built with request logging out of the box; you'll get Rails-style logs with your
316
- gRPC calls:
317
-
318
- ```
319
- # plain
320
- I, [2017-07-14T09:50:54.200506 #70571] INFO -- : [GRPC::Ok] (thing_service.get_thing) [0.348ms]
321
- # logstash
322
- I, [2017-07-14T09:51:03.299050 #70595] INFO -- : {"message":"[GRPC::Ok] (thing_service.get_thing) [0.372ms]","service":"thing_service","method":"thing_service.get_thing","grpc_status":"GRPC::Ok"}
323
- ```
324
-
325
- It supports formatters (including custom ones) that you can use to specify the formatting of the logging:
326
-
327
- ```ruby
328
- Gruf.configure do |c|
329
- c.interceptors.use(
330
- Gruf::Interceptors::Instrumentation::RequestLogging::Interceptor,
331
- formatter: :logstash
332
- )
333
- end
334
- ```
335
-
336
- It comes with a few more options as well:
337
-
338
- | Option | Description | Default |
339
- | ------ | ----------- | ------- |
340
- | formatter | The formatter to use. By default `:plain` and `:logstash` are supported. | `:logstash` |
341
- | log_parameters | If set to true, will log parameters in the response | `false` |
342
- | blacklist | An array of parameter key names to redact from logging, in path.to.key format | `[]` |
343
- | redacted_string | The string to use for redacted parameters. | `REDACTED` |
344
- | ignore_methods | An array of method names to ignore from logging. E.g. `['namespace.health.check']` | `[]` |
345
-
346
- It's important to maintain a safe blacklist should you decide to log parameters; gruf does no
347
- parameter sanitization on its own. We also recommend blacklisting parameters that may contain
348
- very large values (such as binary or json data).
349
-
350
- ## Plugins
351
-
352
- You can build your own hooks and middleware for gruf; here's a list of known open source gems for
353
- gruf that you can use today:
354
-
355
- * [gruf-zipkin](https://github.com/bigcommerce/gruf-zipkin) - Provides a [Zipkin](https://zipkin.io)
356
- integration
357
- * [gruf-circuit-breaker](https://github.com/bigcommerce/gruf-circuit-breaker) - Circuit breaker
358
- support for services
359
- * [gruf-profiler](https://github.com/bigcommerce/gruf-profiler) - Profiles and provides memory usage
360
- reports for clients and services
361
- * [gruf-commander](https://github.com/bigcommerce/gruf-commander) - Request/command-style validation and
362
- execution patterns for services
26
+ Please see the [gruf wiki](https://github.com/bigcommerce/gruf/wiki) for detailed information on getting started
27
+ using gruf.
363
28
 
364
29
  ## Demo Rails App
365
30
 
366
31
  There is a [demonstration Rails application here](https://github.com/bigcommerce/gruf-demo) you can
367
32
  view and clone that shows how to integrate Gruf into an existing Rails application.
368
33
 
369
- ## Roadmap
370
-
371
- ### Gruf 3.0
372
-
373
- * Utilize the new core Ruby interceptors in gRPC 1.7
374
- * Support client interceptors
375
- * Change configuration to an injectable object to ensure thread safety on chained server/client interactions
376
- * Move all references to `Gruf.` configuration into injectable parameters
377
- * Redo server configuration to be fully injectable
378
- * Move client calls to their native method implementation
379
-
380
- ## Companies Using Gruf
381
-
382
- Using gruf and want to show your support? Let us know and we'll add your name here.
383
-
384
- * [BigCommerce](https://www.bigcommerce.com/)
385
-
386
34
  ## License
387
35
 
388
36
  Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
data/bin/gruf CHANGED
@@ -25,15 +25,5 @@ end
25
25
  load 'config/environment.rb' if defined?(Rails)
26
26
  require 'gruf'
27
27
 
28
- begin
29
- server = Gruf::Server.new(Gruf.server_options)
30
- Gruf.services.each { |s| server.add_service(s) }
31
- server.start!
32
- rescue => e
33
- msg = "FATAL ERROR: #{e.message} #{e.backtrace.join("\n")}"
34
- if Gruf.logger
35
- Gruf.logger.fatal msg
36
- else
37
- Logger.new(STDOUT).fatal msg
38
- end
39
- end
28
+ cli = Gruf::Cli::Executor.new
29
+ cli.run