grpcx 0.1.1 → 0.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/.gitignore +1 -0
- data/Gemfile.lock +31 -57
- data/README.md +14 -9
- data/grpcx.gemspec +1 -1
- data/lib/grpcx.rb +1 -0
- data/lib/grpcx/entity.rb +58 -0
- data/lib/grpcx/server/interceptors/instrumentation.rb +8 -6
- data/spec/lib/entity_spec.rb +26 -0
- data/spec/spec_helper.rb +10 -2
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a99773353852adc153af1cda72a8c17e980687c69127bb9a7830d983fd4a052d
|
|
4
|
+
data.tar.gz: 415a8d6f395db5283f57c9756ed47483560b8b1365ff224090a88f6a5dba02b1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8a92a53f2e0fe302482ca483f4434a35f274045d97ebc77c63e11a425f3c591d31bbcbdec2ed013a0c296fefbaf9ad514ecdc45ad8dbfc9143acde905d767933
|
|
7
|
+
data.tar.gz: 775e2e820a35bc874ab36090e3328c72954545653d5dec0a02ee3608aa4b836d88742b17b49a0845dc8e5897db6871464e9978b87f704a03819f23c4bd21971b
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,96 +1,70 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
grpcx (0.
|
|
4
|
+
grpcx (0.2.0)
|
|
5
5
|
activesupport (>= 5.0)
|
|
6
6
|
grpc (>= 1.8.0)
|
|
7
7
|
|
|
8
8
|
GEM
|
|
9
9
|
remote: https://rubygems.org/
|
|
10
10
|
specs:
|
|
11
|
-
activemodel (5.2.
|
|
12
|
-
activesupport (= 5.2.
|
|
13
|
-
activerecord (5.2.
|
|
14
|
-
activemodel (= 5.2.
|
|
15
|
-
activesupport (= 5.2.
|
|
11
|
+
activemodel (5.2.1)
|
|
12
|
+
activesupport (= 5.2.1)
|
|
13
|
+
activerecord (5.2.1)
|
|
14
|
+
activemodel (= 5.2.1)
|
|
15
|
+
activesupport (= 5.2.1)
|
|
16
16
|
arel (>= 9.0)
|
|
17
|
-
activesupport (5.2.
|
|
17
|
+
activesupport (5.2.1)
|
|
18
18
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
19
19
|
i18n (>= 0.7, < 2)
|
|
20
20
|
minitest (~> 5.1)
|
|
21
21
|
tzinfo (~> 1.1)
|
|
22
|
-
addressable (2.5.2)
|
|
23
|
-
public_suffix (>= 2.0.2, < 4.0)
|
|
24
22
|
arel (9.0.0)
|
|
25
23
|
ast (2.4.0)
|
|
26
24
|
concurrent-ruby (1.0.5)
|
|
27
25
|
diff-lcs (1.3)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
google-protobuf (3.5.1.2-x86_64-linux)
|
|
31
|
-
googleapis-common-protos-types (1.0.1)
|
|
26
|
+
google-protobuf (3.6.1)
|
|
27
|
+
googleapis-common-protos-types (1.0.2)
|
|
32
28
|
google-protobuf (~> 3.0)
|
|
33
|
-
|
|
34
|
-
faraday (~> 0.12)
|
|
35
|
-
jwt (>= 1.4, < 3.0)
|
|
36
|
-
logging (~> 2.0)
|
|
37
|
-
memoist (~> 0.12)
|
|
38
|
-
multi_json (~> 1.11)
|
|
39
|
-
os (~> 0.9)
|
|
40
|
-
signet (~> 0.7)
|
|
41
|
-
grpc (1.11.0-x86_64-linux)
|
|
29
|
+
grpc (1.14.2)
|
|
42
30
|
google-protobuf (~> 3.1)
|
|
43
31
|
googleapis-common-protos-types (~> 1.0.0)
|
|
44
|
-
|
|
45
|
-
i18n (1.0.1)
|
|
32
|
+
i18n (1.1.0)
|
|
46
33
|
concurrent-ruby (~> 1.0)
|
|
47
|
-
|
|
48
|
-
little-plugger (1.1.4)
|
|
49
|
-
logging (2.2.2)
|
|
50
|
-
little-plugger (~> 1.1)
|
|
51
|
-
multi_json (~> 1.10)
|
|
52
|
-
memoist (0.16.0)
|
|
34
|
+
jaro_winkler (1.5.1)
|
|
53
35
|
minitest (5.11.3)
|
|
54
|
-
multi_json (1.13.1)
|
|
55
|
-
multipart-post (2.0.0)
|
|
56
|
-
os (0.9.6)
|
|
57
36
|
parallel (1.12.1)
|
|
58
|
-
parser (2.5.1.
|
|
37
|
+
parser (2.5.1.2)
|
|
59
38
|
ast (~> 2.4.0)
|
|
60
|
-
powerpack (0.1.
|
|
61
|
-
public_suffix (3.0.2)
|
|
39
|
+
powerpack (0.1.2)
|
|
62
40
|
rainbow (3.0.0)
|
|
63
41
|
rake (12.3.1)
|
|
64
|
-
rspec (3.
|
|
65
|
-
rspec-core (~> 3.
|
|
66
|
-
rspec-expectations (~> 3.
|
|
67
|
-
rspec-mocks (~> 3.
|
|
68
|
-
rspec-core (3.
|
|
69
|
-
rspec-support (~> 3.
|
|
70
|
-
rspec-expectations (3.
|
|
42
|
+
rspec (3.8.0)
|
|
43
|
+
rspec-core (~> 3.8.0)
|
|
44
|
+
rspec-expectations (~> 3.8.0)
|
|
45
|
+
rspec-mocks (~> 3.8.0)
|
|
46
|
+
rspec-core (3.8.0)
|
|
47
|
+
rspec-support (~> 3.8.0)
|
|
48
|
+
rspec-expectations (3.8.1)
|
|
71
49
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
72
|
-
rspec-support (~> 3.
|
|
73
|
-
rspec-mocks (3.
|
|
50
|
+
rspec-support (~> 3.8.0)
|
|
51
|
+
rspec-mocks (3.8.0)
|
|
74
52
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
75
|
-
rspec-support (~> 3.
|
|
76
|
-
rspec-support (3.
|
|
77
|
-
rubocop (0.
|
|
53
|
+
rspec-support (~> 3.8.0)
|
|
54
|
+
rspec-support (3.8.0)
|
|
55
|
+
rubocop (0.59.0)
|
|
56
|
+
jaro_winkler (~> 1.5.1)
|
|
78
57
|
parallel (~> 1.10)
|
|
79
|
-
parser (>= 2.5)
|
|
58
|
+
parser (>= 2.5, != 2.5.1.1)
|
|
80
59
|
powerpack (~> 0.1)
|
|
81
60
|
rainbow (>= 2.2.2, < 4.0)
|
|
82
61
|
ruby-progressbar (~> 1.7)
|
|
83
62
|
unicode-display_width (~> 1.0, >= 1.0.1)
|
|
84
|
-
ruby-progressbar (1.
|
|
85
|
-
signet (0.8.1)
|
|
86
|
-
addressable (~> 2.3)
|
|
87
|
-
faraday (~> 0.9)
|
|
88
|
-
jwt (>= 1.5, < 3.0)
|
|
89
|
-
multi_json (~> 1.10)
|
|
63
|
+
ruby-progressbar (1.10.0)
|
|
90
64
|
thread_safe (0.3.6)
|
|
91
65
|
tzinfo (1.2.5)
|
|
92
66
|
thread_safe (~> 0.1)
|
|
93
|
-
unicode-display_width (1.
|
|
67
|
+
unicode-display_width (1.4.0)
|
|
94
68
|
|
|
95
69
|
PLATFORMS
|
|
96
70
|
ruby
|
|
@@ -104,4 +78,4 @@ DEPENDENCIES
|
|
|
104
78
|
rubocop
|
|
105
79
|
|
|
106
80
|
BUNDLED WITH
|
|
107
|
-
1.16.
|
|
81
|
+
1.16.4
|
data/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Mixin for `GRPC::RpcServer`:
|
|
|
9
9
|
|
|
10
10
|
- handles [GRPC health checks](https://github.com/grpc/grpc/blob/master/doc/health-checking.md) requests
|
|
11
11
|
- handles `ActiveRecord` connection (auto-connect + pooling)
|
|
12
|
-
- instruments each request with `ActiveSupport::Notifications` (available as `process_action.grpc`, includes `action:
|
|
12
|
+
- instruments each request with `ActiveSupport::Notifications` (available as `process_action.grpc`, includes `service: 'package.name.ServiceName', action: 'underscored_action_name'` data)
|
|
13
13
|
- includes `ActiveSupport::Rescuable` and transforms most common `ActiveRecord::ActiveRecordError`-s into `GRPC::BadStatus` ones
|
|
14
14
|
|
|
15
15
|
|
|
@@ -51,12 +51,13 @@ end
|
|
|
51
51
|
## Using with [Datadog::Notifications](https://github.com/bsm/datadog-notifications)
|
|
52
52
|
|
|
53
53
|
```ruby
|
|
54
|
+
# TODO: update this in datadog-notifications gem itself (to handle new service/action payloads)
|
|
54
55
|
module Datadog::Notifications::Plugins
|
|
55
|
-
class
|
|
56
|
+
class MyGRPC < Base
|
|
56
57
|
|
|
57
58
|
def initialize(opts={})
|
|
58
59
|
super
|
|
59
|
-
Datadog::Notifications.subscribe
|
|
60
|
+
Datadog::Notifications.subscribe(Grpcx::Server::Interceptors::Instrumentation::METRIC_NAME) do |reporter, event|
|
|
60
61
|
record(reporter, event)
|
|
61
62
|
end
|
|
62
63
|
end
|
|
@@ -64,9 +65,10 @@ module Datadog::Notifications::Plugins
|
|
|
64
65
|
private
|
|
65
66
|
|
|
66
67
|
def record(reporter, event)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
service = event.payload[:service]
|
|
69
|
+
action = event.payload[:action]
|
|
70
|
+
status = event.payload[:exception] ? 'error' : 'ok'
|
|
71
|
+
tags = self.tags + %W[service:#{service} action:#{action} status:#{status}]
|
|
70
72
|
|
|
71
73
|
reporter.batch do
|
|
72
74
|
reporter.increment 'grpc.request', tags: tags
|
|
@@ -78,7 +80,7 @@ module Datadog::Notifications::Plugins
|
|
|
78
80
|
end
|
|
79
81
|
|
|
80
82
|
Datadog::Notifications.configure do |c|
|
|
81
|
-
c.use Datadog::Notifications::Plugins::
|
|
83
|
+
c.use Datadog::Notifications::Plugins::MyGRPC
|
|
82
84
|
end if RUNNING_IN_PROD?
|
|
83
85
|
```
|
|
84
86
|
|
|
@@ -86,11 +88,14 @@ end if RUNNING_IN_PROD?
|
|
|
86
88
|
## Using with [Sentry](https://sentry.io/)/[Raven](https://github.com/getsentry/raven-ruby)
|
|
87
89
|
|
|
88
90
|
```ruby
|
|
89
|
-
ActiveSupport::Notifications.subscribe(
|
|
91
|
+
ActiveSupport::Notifications.subscribe(Grpcx::Server::Interceptors::Instrumentation::METRIC_NAME) do |_name, _start, _finish, _id, payload|
|
|
90
92
|
e = payload[:exception_object]
|
|
91
93
|
next unless e
|
|
92
94
|
|
|
93
|
-
Raven.capture_exception(e
|
|
95
|
+
Raven.capture_exception(e, extra: {
|
|
96
|
+
'service' => payload[:service],
|
|
97
|
+
'action' => payload[:action],
|
|
98
|
+
})
|
|
94
99
|
end
|
|
95
100
|
|
|
96
101
|
Raven.configure do |config|
|
data/grpcx.gemspec
CHANGED
data/lib/grpcx.rb
CHANGED
data/lib/grpcx/entity.rb
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
|
2
|
+
require 'set'
|
|
3
|
+
|
|
4
|
+
module Grpcx
|
|
5
|
+
# Entity releated helpers
|
|
6
|
+
module Entity
|
|
7
|
+
def self._convert(field, value, &block)
|
|
8
|
+
field.label == :repeated ? value.map(&block) : yield(value) if value # rubocop:disable Style/IfUnlessModifierOfIfUnless
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
TRUE_VALUES = [true, 1, "1", "t", "T", "true", "TRUE", "on", "ON"].to_set.freeze
|
|
14
|
+
|
|
15
|
+
# @param [Class] msgclass messagepack message class
|
|
16
|
+
# @param [Hash] attrs attributes to assign
|
|
17
|
+
def build(msgclass, attrs={}) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
18
|
+
attrs = ActiveSupport::HashWithIndifferentAccess.new(attrs)
|
|
19
|
+
fields = {}
|
|
20
|
+
msgclass.descriptor.each do |field| # rubocop:disable Metrics/BlockLength
|
|
21
|
+
next unless attrs.key?(field.name)
|
|
22
|
+
|
|
23
|
+
source = attrs[field.name]
|
|
24
|
+
target = nil
|
|
25
|
+
|
|
26
|
+
case field.type
|
|
27
|
+
when :int64, :int32
|
|
28
|
+
target = Entity._convert(field, source, &:to_i)
|
|
29
|
+
when :float, :double
|
|
30
|
+
target = Entity._convert(field, source, &:to_f)
|
|
31
|
+
when :string
|
|
32
|
+
target = Entity._convert(field, source, &:to_s)
|
|
33
|
+
when :bool
|
|
34
|
+
target = Entity._convert(field, source) do |vv|
|
|
35
|
+
TRUE_VALUES.include?(vv)
|
|
36
|
+
end
|
|
37
|
+
when :enum
|
|
38
|
+
target = Entity._convert(field, source) do |vv|
|
|
39
|
+
case vv
|
|
40
|
+
when Integer
|
|
41
|
+
vv
|
|
42
|
+
when String, Symbol
|
|
43
|
+
field.subtype.lookup_name(vv.to_s.upcase.to_sym)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
when :message
|
|
47
|
+
target = Entity._convert(field, source) do |vv|
|
|
48
|
+
build(field.subtype.msgclass, vv)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
fields[field.name] = target if target
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
msgclass.new(fields)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -7,25 +7,27 @@ module Grpcx
|
|
|
7
7
|
METRIC_NAME = 'process_action.grpc'.freeze
|
|
8
8
|
|
|
9
9
|
def request_response(opts={}, &block)
|
|
10
|
-
instrument(
|
|
10
|
+
instrument(opts[:method], &block)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def client_streamer(opts={}, &block)
|
|
14
|
-
instrument(
|
|
14
|
+
instrument(opts[:method], &block)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def server_streamer(opts={}, &block)
|
|
18
|
-
instrument(
|
|
18
|
+
instrument(opts[:method], &block)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def bidi_streamer(opts={}, &block)
|
|
22
|
-
instrument(
|
|
22
|
+
instrument(opts[:method], &block)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
private
|
|
26
26
|
|
|
27
|
-
def instrument(
|
|
28
|
-
|
|
27
|
+
def instrument(method, &block)
|
|
28
|
+
service = method.owner.service_name # method is just a standard ruby Method class, so `owner` is a service impl
|
|
29
|
+
action = method.name # does not match real proto service name; it's a GRPC::GenericService.underscore-d version
|
|
30
|
+
ActiveSupport::Notifications.instrument(METRIC_NAME, service: service, action: action, &block)
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Grpcx::Entity do
|
|
4
|
+
|
|
5
|
+
it 'should build messages' do
|
|
6
|
+
msg = described_class.build Grpcx::Spec::Message,
|
|
7
|
+
name: 'Name',
|
|
8
|
+
version: 1,
|
|
9
|
+
types: {
|
|
10
|
+
num: 8,
|
|
11
|
+
truth: [1, 0, true, 'true'],
|
|
12
|
+
decimal: '1.2',
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
expect(msg.to_h).to eq(
|
|
16
|
+
name: "Name",
|
|
17
|
+
version: :V1,
|
|
18
|
+
types: {
|
|
19
|
+
num: 8,
|
|
20
|
+
truth: [true, false, true, true],
|
|
21
|
+
decimal: 1.2,
|
|
22
|
+
},
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -6,8 +6,15 @@ require 'google/protobuf'
|
|
|
6
6
|
Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
7
7
|
add_message "grpcx.spec.Message" do
|
|
8
8
|
optional :name, :string, 1
|
|
9
|
+
optional :version, :enum, 2, "grpcx.spec.Version"
|
|
10
|
+
optional :types, :message, 3, "grpcx.spec.Types"
|
|
9
11
|
end
|
|
10
|
-
|
|
12
|
+
add_message "grpcx.spec.Types" do
|
|
13
|
+
optional :num, :int64, 1
|
|
14
|
+
repeated :truth, :bool, 2
|
|
15
|
+
optional :decimal, :double, 3
|
|
16
|
+
end
|
|
17
|
+
add_enum "grpcx.spec.Version" do
|
|
11
18
|
value :V0, 0
|
|
12
19
|
value :V1, 1
|
|
13
20
|
value :V2, 2
|
|
@@ -18,7 +25,8 @@ end
|
|
|
18
25
|
|
|
19
26
|
module Grpcx::Spec
|
|
20
27
|
Message = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpcx.spec.Message").msgclass
|
|
21
|
-
|
|
28
|
+
Version = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpcx.spec.Version").enummodule
|
|
29
|
+
Types = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpcx.spec.Types").msgclass
|
|
22
30
|
GetMessageRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpcx.spec.GetMessageRequest").msgclass
|
|
23
31
|
|
|
24
32
|
module Service
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: grpcx
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Black Square Media Ltd
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-
|
|
11
|
+
date: 2018-09-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -124,11 +124,13 @@ files:
|
|
|
124
124
|
- Rakefile
|
|
125
125
|
- grpcx.gemspec
|
|
126
126
|
- lib/grpcx.rb
|
|
127
|
+
- lib/grpcx/entity.rb
|
|
127
128
|
- lib/grpcx/server.rb
|
|
128
129
|
- lib/grpcx/server/interceptors.rb
|
|
129
130
|
- lib/grpcx/server/interceptors/active_record.rb
|
|
130
131
|
- lib/grpcx/server/interceptors/instrumentation.rb
|
|
131
132
|
- lib/grpcx/server/interceptors/rescue.rb
|
|
133
|
+
- spec/lib/entity_spec.rb
|
|
132
134
|
- spec/lib/server_spec.rb
|
|
133
135
|
- spec/spec_helper.rb
|
|
134
136
|
homepage: https://github.com/bsm/grpcx
|
|
@@ -151,10 +153,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
151
153
|
version: '0'
|
|
152
154
|
requirements: []
|
|
153
155
|
rubyforge_project:
|
|
154
|
-
rubygems_version: 2.7.
|
|
156
|
+
rubygems_version: 2.7.6
|
|
155
157
|
signing_key:
|
|
156
158
|
specification_version: 4
|
|
157
159
|
summary: gRPC extensions/helpers
|
|
158
160
|
test_files:
|
|
161
|
+
- spec/lib/entity_spec.rb
|
|
159
162
|
- spec/lib/server_spec.rb
|
|
160
163
|
- spec/spec_helper.rb
|