grpcx 0.1.1 → 0.2.0

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: 7e6bcd16e9fceffd33f50eb1f4329ce55b9c983ff434f8688cbc2cf2432012d0
4
- data.tar.gz: 79fb5b99a06087b37e0a8af8c36c13eebaf07b81a797459144b144adcecc3e07
3
+ metadata.gz: a99773353852adc153af1cda72a8c17e980687c69127bb9a7830d983fd4a052d
4
+ data.tar.gz: 415a8d6f395db5283f57c9756ed47483560b8b1365ff224090a88f6a5dba02b1
5
5
  SHA512:
6
- metadata.gz: e19042030a742d1f985dde51ef366402bbd062c3fe4f2d17d987c6dbc40db0cf069ad61f746648291987d0011b38d28f757e3dd8b9b5bdcdff738ba34029b228
7
- data.tar.gz: a79ba2d070d331afa74b95f439f0cfa0fa243d2e5c6b11186d3175374f3a435b304082ad67ec2ba34230415dda06add606101b0762ed8823b36b4c4c19448443
6
+ metadata.gz: 8a92a53f2e0fe302482ca483f4434a35f274045d97ebc77c63e11a425f3c591d31bbcbdec2ed013a0c296fefbaf9ad514ecdc45ad8dbfc9143acde905d767933
7
+ data.tar.gz: 775e2e820a35bc874ab36090e3328c72954545653d5dec0a02ee3608aa4b836d88742b17b49a0845dc8e5897db6871464e9978b87f704a03819f23c4bd21971b
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  .rubocop-*
2
+ .rake_tasks~
2
3
  pkg/
@@ -1,96 +1,70 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grpcx (0.1.1)
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.0)
12
- activesupport (= 5.2.0)
13
- activerecord (5.2.0)
14
- activemodel (= 5.2.0)
15
- activesupport (= 5.2.0)
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.0)
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
- faraday (0.15.0)
29
- multipart-post (>= 1.2, < 3)
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
- googleauth (0.6.2)
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
- googleauth (>= 0.5.1, < 0.7)
45
- i18n (1.0.1)
32
+ i18n (1.1.0)
46
33
  concurrent-ruby (~> 1.0)
47
- jwt (2.1.0)
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.0)
37
+ parser (2.5.1.2)
59
38
  ast (~> 2.4.0)
60
- powerpack (0.1.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.7.0)
65
- rspec-core (~> 3.7.0)
66
- rspec-expectations (~> 3.7.0)
67
- rspec-mocks (~> 3.7.0)
68
- rspec-core (3.7.1)
69
- rspec-support (~> 3.7.0)
70
- rspec-expectations (3.7.0)
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.7.0)
73
- rspec-mocks (3.7.0)
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.7.0)
76
- rspec-support (3.7.1)
77
- rubocop (0.55.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.9.0)
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.3.2)
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.1
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: METHOD_NAME` data)
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 GRPC < Base
56
+ class MyGRPC < Base
56
57
 
57
58
  def initialize(opts={})
58
59
  super
59
- Datadog::Notifications.subscribe 'process_action.grpc' do |reporter, event|
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
- action = event.payload[:action]
68
- status = event.payload[:exception] ? 'error' : 'ok'
69
- tags = self.tags + ["rpc:#{action}", "status:#{status}"]
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::GRPC
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('process_action.grpc') do |_name, _start, _finish, _id, payload|
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|
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'grpcx'
3
- s.version = '0.1.1'
3
+ s.version = '0.2.0'
4
4
  s.authors = ['Black Square Media Ltd']
5
5
  s.email = ['info@blacksquaremedia.com']
6
6
  s.summary = %(gRPC extensions/helpers)
@@ -1 +1,2 @@
1
1
  require 'grpcx/server'
2
+ require 'grpcx/entity'
@@ -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(action: opts[:method], &block)
10
+ instrument(opts[:method], &block)
11
11
  end
12
12
 
13
13
  def client_streamer(opts={}, &block)
14
- instrument(action: opts[:method], &block)
14
+ instrument(opts[:method], &block)
15
15
  end
16
16
 
17
17
  def server_streamer(opts={}, &block)
18
- instrument(action: opts[:method], &block)
18
+ instrument(opts[:method], &block)
19
19
  end
20
20
 
21
21
  def bidi_streamer(opts={}, &block)
22
- instrument(action: opts[:method], &block)
22
+ instrument(opts[:method], &block)
23
23
  end
24
24
 
25
25
  private
26
26
 
27
- def instrument(opts={}, &block)
28
- ActiveSupport::Notifications.instrument(METRIC_NAME, opts, &block)
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
@@ -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
- add_enum "grpcx.spec.Enum" do
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
- Enum = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpcx.spec.Enum").enummodule
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.1.1
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-05-10 00:00:00.000000000 Z
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.3
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