jcw 0.1.2 → 0.2.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e8fc0e3e0c34e18f281b228fc45782f30109ba9125c6730ff170982f9c683e5c
4
- data.tar.gz: 4ac948f3822db7891f59919616302077757c6ef0a71f6e2a4a09c06ced413241
3
+ metadata.gz: 110c81162cbfa9b0c7320539340e3adc8f2ecb0dc76f3ebc398ab3ef9330db31
4
+ data.tar.gz: 637bfb300fc81f4e07dce12983da6e4a342dbaa2445695241c7f3bd6fdd76f69
5
5
  SHA512:
6
- metadata.gz: 9e75ea2fb98b023b70b2cf7b84074a9ec4a6bef9f7a901d48da09ac6a9f1b63c4b9b6d9838f83658729e602c27bcf739fa869437d95022bd0b92060f92cf3239
7
- data.tar.gz: 5b5c8c1248f89e9fc28a82b3dab536da66115c34e03254cbb3822e5123076998c4b9674969343766f9b51a6ad14bcf78d99fa6620a353af549f4536968d7a3d7
6
+ metadata.gz: 1cd01757ae92d40d4e0bd2ba687fc62d612a3ce7a6b3178d1a4038c56e7c2877ff219a8415fe0f4c099b0930b341eaff81efe2345ce6361384c46dfaa16829ab
7
+ data.tar.gz: 696a1156f40a49295c53f638b2626e6269c445f30f73ad809bc725dc765673417de5c9869c39fe3cbbc58146a951ef14f4d11e7a00b6a36193358e3b73ec1c3c
@@ -41,11 +41,8 @@ jobs:
41
41
  strategy:
42
42
  fail-fast: false
43
43
  matrix:
44
- ruby: [2.7, 2.7.4, 3.0.0, 3.0.1, 3.0.2]
44
+ ruby: [2.6, 2.7, 2.7.4, 3.0.0, 3.0.1, 3.0.2]
45
45
  experimental: [false]
46
- include:
47
- - ruby: head
48
- experimental: true
49
46
 
50
47
  steps:
51
48
  - uses: actions/checkout@v2
data/.rubocop.yml CHANGED
@@ -3,7 +3,7 @@ inherit_gem:
3
3
 
4
4
  AllCops:
5
5
  DisplayCopNames: true
6
- TargetRubyVersion: 2.7
6
+ TargetRubyVersion: 2.6
7
7
 
8
8
  RSpec/EmptyLineAfterHook:
9
9
  Enabled: false
data/Gemfile.lock CHANGED
@@ -1,29 +1,29 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- jcw (0.1.2)
5
- activesupport (>= 5.0)
4
+ jcw (0.2.2)
5
+ activesupport (>= 5.0, < 7.0.0)
6
+ gruf (~> 2.10)
6
7
  httprb-opentracing (~> 0.4.0)
7
8
  jaeger-client (~> 1.1.0)
8
- rack-tracer (~> 0.9.0)
9
9
 
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- actionpack (6.1.4.1)
14
- actionview (= 6.1.4.1)
15
- activesupport (= 6.1.4.1)
13
+ actionpack (6.1.4.4)
14
+ actionview (= 6.1.4.4)
15
+ activesupport (= 6.1.4.4)
16
16
  rack (~> 2.0, >= 2.0.9)
17
17
  rack-test (>= 0.6.3)
18
18
  rails-dom-testing (~> 2.0)
19
19
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
20
- actionview (6.1.4.1)
21
- activesupport (= 6.1.4.1)
20
+ actionview (6.1.4.4)
21
+ activesupport (= 6.1.4.4)
22
22
  builder (~> 3.1)
23
23
  erubi (~> 1.4)
24
24
  rails-dom-testing (~> 2.0)
25
25
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
26
- activesupport (6.1.4.1)
26
+ activesupport (6.1.4.4)
27
27
  concurrent-ruby (~> 1.0, >= 1.0.2)
28
28
  i18n (>= 1.6, < 2)
29
29
  minitest (>= 5.1)
@@ -33,7 +33,7 @@ GEM
33
33
  public_suffix (>= 2.0.2, < 5.0)
34
34
  ast (2.4.2)
35
35
  builder (3.2.4)
36
- bundler-audit (0.8.0)
36
+ bundler-audit (0.9.0.1)
37
37
  bundler (>= 1.2.0, < 3)
38
38
  thor (~> 1.0)
39
39
  coderay (1.1.3)
@@ -43,16 +43,33 @@ GEM
43
43
  docile (1.4.0)
44
44
  domain_name (0.5.20190701)
45
45
  unf (>= 0.0.5, < 1.0.0)
46
+ e2mmap (0.1.0)
46
47
  erubi (1.10.0)
47
- ffi (1.15.3)
48
+ ffi (1.15.4)
48
49
  ffi-compiler (1.0.1)
49
50
  ffi (>= 1.0.0)
50
51
  rake
51
- http (5.0.1)
52
- addressable (~> 2.3)
52
+ google-protobuf (3.19.1)
53
+ googleapis-common-protos-types (1.3.0)
54
+ google-protobuf (~> 3.14)
55
+ grpc (1.42.0)
56
+ google-protobuf (~> 3.18)
57
+ googleapis-common-protos-types (~> 1.0)
58
+ grpc-tools (1.42.0)
59
+ gruf (2.10.0)
60
+ activesupport (> 4)
61
+ concurrent-ruby (> 1)
62
+ e2mmap (~> 0.1)
63
+ grpc (~> 1.10)
64
+ grpc-tools (~> 1.10)
65
+ json (>= 2.3)
66
+ slop (~> 4.6)
67
+ thwait (~> 0.1)
68
+ http (5.0.4)
69
+ addressable (~> 2.8)
53
70
  http-cookie (~> 1.0)
54
71
  http-form_data (~> 2.2)
55
- llhttp-ffi (~> 0.3.0)
72
+ llhttp-ffi (~> 0.4.0)
56
73
  http-cookie (1.0.4)
57
74
  domain_name (~> 0.5)
58
75
  http-form_data (2.3.0)
@@ -60,55 +77,56 @@ GEM
60
77
  ffi-compiler (>= 1.0, < 2.0)
61
78
  httprb-opentracing (0.4.0)
62
79
  opentracing (~> 0.5.0)
63
- i18n (1.8.10)
80
+ i18n (1.8.11)
64
81
  concurrent-ruby (~> 1.0)
65
82
  jaeger-client (1.1.0)
66
83
  opentracing (~> 0.3)
67
84
  thrift
68
- llhttp-ffi (0.3.1)
85
+ json (2.6.1)
86
+ llhttp-ffi (0.4.0)
69
87
  ffi-compiler (~> 1.0)
70
88
  rake (~> 13.0)
71
- loofah (2.12.0)
89
+ loofah (2.13.0)
72
90
  crass (~> 1.0.2)
73
91
  nokogiri (>= 1.5.9)
74
92
  method_source (1.0.0)
75
93
  mini_portile2 (2.6.1)
76
- minitest (5.14.4)
77
- nokogiri (1.12.3)
94
+ minitest (5.15.0)
95
+ nokogiri (1.12.5)
78
96
  mini_portile2 (~> 2.6.1)
79
97
  racc (~> 1.4)
80
- nokogiri (1.12.3-x86_64-darwin)
98
+ nokogiri (1.12.5-x86_64-darwin)
81
99
  racc (~> 1.4)
82
- nokogiri (1.12.3-x86_64-linux)
100
+ nokogiri (1.12.5-x86_64-linux)
83
101
  racc (~> 1.4)
84
102
  opentracing (0.5.0)
85
- parallel (1.20.1)
86
- parser (3.0.2.0)
103
+ opentracing_test_tracer (0.1.1)
104
+ opentracing
105
+ parallel (1.21.0)
106
+ parser (3.0.3.2)
87
107
  ast (~> 2.4.1)
88
108
  pry (0.14.1)
89
109
  coderay (~> 1.1)
90
110
  method_source (~> 1.0)
91
111
  public_suffix (4.0.6)
92
- racc (1.5.2)
112
+ racc (1.6.0)
93
113
  rack (2.2.3)
94
114
  rack-test (1.1.0)
95
115
  rack (>= 1.0, < 3)
96
- rack-tracer (0.9.0)
97
- opentracing (~> 0.4)
98
116
  rails-dom-testing (2.0.3)
99
117
  activesupport (>= 4.2.0)
100
118
  nokogiri (>= 1.6)
101
119
  rails-html-sanitizer (1.4.2)
102
120
  loofah (~> 2.3)
103
- railties (6.1.4.1)
104
- actionpack (= 6.1.4.1)
105
- activesupport (= 6.1.4.1)
121
+ railties (6.1.4.4)
122
+ actionpack (= 6.1.4.4)
123
+ activesupport (= 6.1.4.4)
106
124
  method_source
107
125
  rake (>= 0.13)
108
126
  thor (~> 1.0)
109
127
  rainbow (3.0.0)
110
128
  rake (13.0.6)
111
- regexp_parser (2.1.1)
129
+ regexp_parser (2.2.0)
112
130
  rexml (3.2.5)
113
131
  rspec (3.10.0)
114
132
  rspec-core (~> 3.10.0)
@@ -122,7 +140,7 @@ GEM
122
140
  rspec-mocks (3.10.2)
123
141
  diff-lcs (>= 1.2.0, < 2.0)
124
142
  rspec-support (~> 3.10.0)
125
- rspec-support (3.10.2)
143
+ rspec-support (3.10.3)
126
144
  rubocop (1.17.0)
127
145
  parallel (~> 1.10)
128
146
  parser (>= 3.0.0.0)
@@ -132,7 +150,7 @@ GEM
132
150
  rubocop-ast (>= 1.7.0, < 2.0)
133
151
  ruby-progressbar (~> 1.7)
134
152
  unicode-display_width (>= 1.4.0, < 3.0)
135
- rubocop-ast (1.11.0)
153
+ rubocop-ast (1.15.0)
136
154
  parser (>= 3.0.1.1)
137
155
  rubocop-config-umbrellio (1.17.0.53)
138
156
  rubocop (= 1.17.0)
@@ -163,15 +181,18 @@ GEM
163
181
  simplecov-html (0.12.3)
164
182
  simplecov-lcov (0.8.0)
165
183
  simplecov_json_formatter (0.1.3)
184
+ slop (4.9.1)
166
185
  thor (1.1.0)
167
- thrift (0.14.2)
186
+ thrift (0.15.0)
187
+ thwait (0.2.0)
188
+ e2mmap
168
189
  tzinfo (2.0.4)
169
190
  concurrent-ruby (~> 1.0)
170
191
  unf (0.1.4)
171
192
  unf_ext
172
- unf_ext (0.0.7.7)
173
- unicode-display_width (2.0.0)
174
- zeitwerk (2.4.2)
193
+ unf_ext (0.0.8)
194
+ unicode-display_width (2.1.0)
195
+ zeitwerk (2.5.1)
175
196
 
176
197
  PLATFORMS
177
198
  ruby
@@ -184,6 +205,7 @@ DEPENDENCIES
184
205
  http
185
206
  http-parser
186
207
  jcw!
208
+ opentracing_test_tracer
187
209
  pry
188
210
  railties
189
211
  rake
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # JCW &middot; [![Supporting](https://github.com/Cado-Labs/cado-labs-logos/blob/main/cado_labs_badge.png)](https://github.com/Cado-Labs/) &middot; [![Coverage Status](https://coveralls.io/repos/github/Cado-Labs/jcw/badge.svg?branch=gem-without-zeitwerk)](https://coveralls.io/github/Cado-Labs/jcw?branch=gem-without-zeitwerk) &middot; [![Gem Version](https://badge.fury.io/rb/jcw.svg)](https://badge.fury.io/rb/jcw)
1
+ # JCW &middot; <a target="_blank" href="https://github.com/Cado-Labs"><img src="https://github.com/Cado-Labs/cado-labs-logos/raw/main/cado_labs_badge.svg" alt="Supported by Cado Labs" style="max-width: 100%; height: 20px"></a> &middot; [![Coverage Status](https://coveralls.io/repos/github/Cado-Labs/jcw/badge.svg?branch=gem-without-zeitwerk)](https://coveralls.io/github/Cado-Labs/jcw?branch=gem-without-zeitwerk) &middot; [![Gem Version](https://badge.fury.io/rb/jcw.svg)](https://badge.fury.io/rb/jcw)
2
2
 
3
3
  Simple wrapper for the gem "jaeger-client" with simpler customization.
4
4
 
@@ -6,7 +6,7 @@ Simple wrapper for the gem "jaeger-client" with simpler customization.
6
6
 
7
7
  <p>
8
8
  <a href="https://github.com/Cado-Labs">
9
- <img src="https://github.com/Cado-Labs/cado-labs-logos/blob/main/cado_labs_supporting.svg" alt="Supported by Cado Labs" />
9
+ <img src="https://github.com/Cado-Labs/cado-labs-resources/blob/main/cado_labs_supporting_rounded.svg" alt="Supported by Cado Labs" />
10
10
  </a>
11
11
  </p>
12
12
 
@@ -25,7 +25,7 @@ gem install jcw
25
25
  ```
26
26
 
27
27
  ```ruby
28
- require 'jcw'
28
+ require 'jcw'
29
29
  ```
30
30
 
31
31
  ## Usage
@@ -42,10 +42,11 @@ UDP Sender(default):
42
42
  hostname: "custom-hostname",
43
43
  custom_tag: "custom-tag-value",
44
44
  }
45
+ config.rack_ignore_paths = %w[/api/test]
45
46
  end
46
47
 
47
- # Set middleware for wrapping all requests(gem RackTracer)
48
- Rails.application.middleware.use(JCW::RackTracer)
48
+ # Set middleware for wrapping all requests
49
+ Rails.application.middleware.use(JCW::Rack::Tracer)
49
50
  ```
50
51
 
51
52
  TCP Sender:
@@ -59,26 +60,67 @@ TCP Sender:
59
60
  hostname: "custom-hostname",
60
61
  custom_tag: "custom-tag-value",
61
62
  }
63
+ config.rack_ignore_paths = %w[/api/test]
62
64
  end
63
65
 
64
66
  # Set middleware for wrapping all requests
65
- Rails.application.middleware.use(JCW::RackTracer)
67
+ Rails.application.middleware.use(JCW::Rack::Tracer)
66
68
 
67
69
  # If you need send all logs with spans set on_finish_span and extend JaegerLoggerExtension
68
70
  # Not recommended for UDP sender, because default max packet size is 65,000 bytes.
69
71
  Rails.application.config.tap do |config|
70
72
  config.middleware.use(
71
- ::JCW::RackTracer,
72
- on_finish_span:
73
- -> (span) { ::JCW::JaegerLogger.current.logs.each { |log| span.log_kv(**log) } },
73
+ JCW::Rack::Tracer,
74
+ on_finish_span: lambda do |span|
75
+ JCW::Logger.current.logs.each { |log| span.log_kv(**log) }
76
+ JCW::Logger.current.clear # Do not forget to avoid memory leaks
77
+ end,
74
78
  )
75
- config.logger.extend(::JCW::JaegerLoggerExtension)
79
+
80
+ config.logger.extend(JCW::LoggerExtension)
76
81
  end
77
82
  ```
78
83
  - `config.subscribe_to` - not recommended for UDP sender, because default max packet size is 65,000 bytes.
79
84
 
85
+ #### GRPC Integration
86
+
87
+ Client side
88
+
89
+ ```ruby
90
+ # Add JCW::Interceptors::Gruf::Client Interceptor to Gruf Client Initializer
91
+ options = {}
92
+ client_options = { timeout: 10, interceptors: [JCW::Interceptors::Gruf::Client.new] }
93
+
94
+ client = Gruf::Client.new(
95
+ service: Test::Service, options: options, client_options: client_options
96
+ )
97
+
98
+ request_method = "some_method"
99
+ client.call(request_method)
100
+ ```
101
+
102
+ Server side
103
+
104
+ ```ruby
105
+ # Add Server Interceptor
106
+ Rails.configuration.to_prepare do
107
+ Gruf.configure do |config|
108
+ config.interceptors.use(JCW::Interceptors::Gruf::Server)
109
+ end
110
+ end
111
+
112
+ # Configure
113
+ ::JCW::Wrapper.configure do |config|
114
+ config.service_name = "Service Name"
115
+ config.connection = { protocol: :udp, host: "127.0.0.1", port: 6831 }
116
+ config.enabled = true
117
+ config.subscribe_to = [/.*/]
118
+ config.grpc_ignore_methods = %w[grpc.ignore.method]
119
+ end
120
+ ```
121
+
80
122
  ### Contributing
81
-
123
+
82
124
  - Fork it ( https://github.com/Cado-Labs/jcw )
83
125
  - Create your feature branch (`git checkout -b feature/my-new-feature`)
84
126
  - Commit your changes (`git commit -am '[feature_context] Add some feature'`)
@@ -92,7 +134,7 @@ Released under MIT License.
92
134
  ## Supporting
93
135
 
94
136
  <a href="https://github.com/Cado-Labs">
95
- <img src="https://github.com/Cado-Labs/cado-labs-logos/blob/main/cado_labs_logo.png" alt="Supported by Cado Labs" />
137
+ <img src="https://github.com/Cado-Labs/cado-labs-resources/blob/main/cado_labs_supporting_rounded.svg" alt="Supported by Cado Labs" />
96
138
  </a>
97
139
 
98
140
  ## Authors
data/jcw.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "Wrapper for the gem 'jaeger-client' with simpler customization."
13
13
  spec.homepage = "https://github.com/Cado-Labs/jcw"
14
14
  spec.license = "MIT"
15
- spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
16
16
 
17
17
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
18
18
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
@@ -22,15 +22,16 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ["lib"]
24
24
 
25
- spec.add_dependency "activesupport", ">= 5.0"
25
+ spec.add_dependency "activesupport", ">= 5.0", "< 7.0.0"
26
+ spec.add_dependency "gruf", "~> 2.10"
26
27
  spec.add_dependency "httprb-opentracing", "~> 0.4.0"
27
28
  spec.add_dependency "jaeger-client", "~> 1.1.0"
28
- spec.add_dependency "rack-tracer", "~> 0.9.0"
29
29
 
30
30
  spec.add_development_dependency "bundler"
31
31
  spec.add_development_dependency "bundler-audit"
32
32
  spec.add_development_dependency "http"
33
33
  spec.add_development_dependency "http-parser"
34
+ spec.add_development_dependency "opentracing_test_tracer"
34
35
  spec.add_development_dependency "pry"
35
36
  spec.add_development_dependency "railties"
36
37
  spec.add_development_dependency "rake"
@@ -38,4 +39,7 @@ Gem::Specification.new do |spec|
38
39
  spec.add_development_dependency "rubocop-config-umbrellio"
39
40
  spec.add_development_dependency "simplecov"
40
41
  spec.add_development_dependency "simplecov-lcov"
42
+ spec.metadata = {
43
+ "rubygems_mfa_required" => "true",
44
+ }
41
45
  end
data/lib/jcw/config.rb CHANGED
@@ -7,7 +7,9 @@ module JCW
7
7
  :subscribe_to,
8
8
  :connection,
9
9
  :flush_interval,
10
- :tags
10
+ :tags,
11
+ :grpc_ignore_methods,
12
+ :rack_ignore_paths
11
13
 
12
14
  def enabled
13
15
  @enabled ||= false
@@ -34,5 +36,13 @@ module JCW
34
36
  def tags
35
37
  @tags ||= {}
36
38
  end
39
+
40
+ def grpc_ignore_methods
41
+ @grpc_ignore_methods ||= []
42
+ end
43
+
44
+ def rack_ignore_paths
45
+ @rack_ignore_paths ||= []
46
+ end
37
47
  end
38
48
  end
@@ -17,6 +17,7 @@ module JCW
17
17
  host = request.uri.host if request.uri.respond_to?(:host)
18
18
  port = request.uri.port if request.uri.respond_to?(:port)
19
19
  verb = request.verb.to_s.upcase if request.respond_to?(:verb)
20
+ full_path = request.uri.to_s
20
21
 
21
22
  tags = {
22
23
  "component" => "ruby-httprb",
@@ -25,13 +26,15 @@ module JCW
25
26
  "http.url" => path,
26
27
  "peer.host" => host,
27
28
  "peer.port" => port,
29
+ "full_path" => full_path,
28
30
  }.compact
29
31
 
30
32
  tracer = ::HTTP::Tracer.tracer
31
33
 
32
- tracer.start_active_span("http.request", tags: tags) do |scope|
34
+ request_name = "http.request #{verb} #{path}"
35
+ tracer.start_active_span(request_name, tags: tags) do |scope|
33
36
  request.headers.merge!(options.headers)
34
- OpenTracing.inject(scope.span.context, OpenTracing::FORMAT_RACK,
37
+ OpenTracing.inject(scope.span.context, OpenTracing::FORMAT_TEXT_MAP,
35
38
  request.headers)
36
39
 
37
40
  res = perform_without_tracing(request, options)
data/lib/jcw/init.rb CHANGED
@@ -41,11 +41,10 @@ module JCW
41
41
  end
42
42
 
43
43
  def activate_subscribers
44
- subscribers = config.subscribe_to
45
- return if subscribers.blank?
44
+ events = config.subscribe_to
45
+ return if events.blank?
46
46
 
47
- Tracing.register_subscribers(subscribers)
48
- Tracing.subscribe_tracing_events
47
+ events.each { |event| JCW::Subscriber.subscribe_to_event!(event) }
49
48
  end
50
49
 
51
50
  def init_http_tracer
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "gruf"
4
+
5
+ module JCW
6
+ module Interceptors
7
+ module Gruf
8
+ class Client < ::Gruf::Interceptors::ClientInterceptor
9
+ def call(request_context:)
10
+ tracer = OpenTracing.global_tracer
11
+ metadata = request_context.metadata
12
+
13
+ tags = {
14
+ "component" => "gRPC",
15
+ "span.kind" => "client",
16
+ "grpc.method_type" => "request_response",
17
+ "grpc.headers" => metadata,
18
+ }
19
+
20
+ tracer.start_active_span(request_context.method.to_s, tags: tags) do |current_scope|
21
+ current_span = current_scope.span
22
+ current_span.log_kv(
23
+ event: "request",
24
+ data: request_context.requests.map { |request| request.try(:to_h) },
25
+ )
26
+ hpack_carrier = Hpack.new(metadata)
27
+ tracer.inject(current_span.context, ::OpenTracing::FORMAT_TEXT_MAP, hpack_carrier)
28
+
29
+ yield
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JCW
4
+ module Interceptors
5
+ module Gruf
6
+ class Hpack
7
+ def initialize(wrapped)
8
+ @wrapped = wrapped
9
+ end
10
+
11
+ def [](key)
12
+ @wrapped[key.downcase]
13
+ end
14
+
15
+ def []=(key, value)
16
+ return unless value
17
+
18
+ @wrapped[key.downcase] = value
19
+ end
20
+
21
+ def each(&block)
22
+ @wrapped.each(&block)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "gruf"
4
+
5
+ module JCW
6
+ module Interceptors
7
+ module Gruf
8
+ class Server < ::Gruf::Interceptors::ServerInterceptor
9
+ # rubocop:disable Metrics/MethodLength
10
+ def call
11
+ method = request.method_name
12
+ return yield if Wrapper.config.grpc_ignore_methods.include?(method)
13
+
14
+ tracer = OpenTracing.global_tracer
15
+ on_finish_span = options[:on_finish_span]
16
+ service_class = request.service
17
+ method_name = request.method_key
18
+ name = method_name.to_s.camelize
19
+ route = "/#{service_class.service_name}/#{name}"
20
+
21
+ begin
22
+ tags = {
23
+ "component" => "gRPC",
24
+ "span.kind" => "server",
25
+ "grpc.method_type" => "request_response",
26
+ }
27
+ hpack_carrier = Hpack.new(request.active_call.metadata)
28
+ parent_span_context = tracer.extract(::OpenTracing::FORMAT_TEXT_MAP, hpack_carrier)
29
+ current_scope = tracer.start_active_span(
30
+ route,
31
+ child_of: parent_span_context,
32
+ tags: tags,
33
+ )
34
+ current_span = current_scope.span
35
+ current_span.log_kv(event: "request", data: request.message.to_h)
36
+
37
+ response = yield
38
+
39
+ if response.try(:error_fields)
40
+ current_span.set_tag("error", true)
41
+ current_span.log_kv(event: "error", data: response.to_h)
42
+ end
43
+ rescue => e
44
+ if current_span
45
+ current_span.set_tag("error", true)
46
+ current_span.log_kv(event: "error", error_object: e)
47
+ end
48
+ raise
49
+ ensure
50
+ on_finish_span&.call(current_span)
51
+ current_scope.close if current_span
52
+ end
53
+
54
+ response
55
+ end
56
+ # rubocop:enable Metrics/MethodLength
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,5 +1,130 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # inspired https://github.com/opentracing-contrib/ruby-rack-tracer/blob/master/lib/rack/tracer.rb
3
4
  module JCW
4
- RackTracer = Class.new(Rack::Tracer)
5
+ module Rack
6
+ class Tracer
7
+ REQUEST_URI = "REQUEST_URI"
8
+ REQUEST_PATH = "REQUEST_PATH"
9
+ REQUEST_METHOD = "REQUEST_METHOD"
10
+
11
+ # Create a new Rack Tracer middleware.
12
+ #
13
+ # @param app The Rack application/middlewares stack.
14
+ # @param tracer [OpenTracing::Tracer] A tracer to be used when start_span, and extract
15
+ # is called.
16
+ # @param on_start_span [Proc, nil] A callback evaluated after a new span is created.
17
+ # @param on_finish_span [Proc, nil] A callback evaluated after a span is finished.
18
+ # @param ignore_paths [Array<Class>] An array of paths to be skiped by the tracer.
19
+ # @param errors [Array<Class>] An array of error classes to be captured by the tracer
20
+ # as errors. Errors are **not** muted by the middleware, they're re-raised afterwards.
21
+ def initialize(app, # rubocop:disable Metrics/ParameterLists
22
+ tracer: OpenTracing.global_tracer,
23
+ on_start_span: nil,
24
+ on_finish_span: nil,
25
+ trust_incoming_span: true,
26
+ ignore_paths: Wrapper.config.rack_ignore_paths,
27
+ errors: [StandardError])
28
+ @app = app
29
+ @tracer = tracer
30
+ @on_start_span = on_start_span
31
+ @on_finish_span = on_finish_span
32
+ @trust_incoming_span = trust_incoming_span
33
+ @errors = errors
34
+ @ignore_paths = ignore_paths
35
+ end
36
+
37
+ def call(env)
38
+ method = env[REQUEST_METHOD]
39
+ path = env[REQUEST_PATH]
40
+ url = env[REQUEST_URI]
41
+
42
+ return @app.call(env) if @ignore_paths.include?(path)
43
+
44
+ handle_error(@errors) do
45
+ env["uber-trace-id"] = env["HTTP_UBER_TRACE_ID"]
46
+ context = @tracer.extract(OpenTracing::FORMAT_TEXT_MAP, env) if @trust_incoming_span
47
+ @scope = build_scope(method, url, context)
48
+ @span = @scope.span
49
+
50
+ perform_on_start_span(env, @span, @on_start_span)
51
+
52
+ @app.call(env).tap do |status_code, _headers, _body|
53
+ set_tag(@span, status_code, env)
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def handle_error(errors)
61
+ yield
62
+ rescue *errors => e
63
+ @span.set_tag("error", true)
64
+ @span.log_kv(
65
+ event: "error",
66
+ "error.kind": e.class.to_s,
67
+ "error.object": e,
68
+ message: e.message,
69
+ stack: e.backtrace.join("\n"),
70
+ )
71
+ raise
72
+ ensure
73
+ begin
74
+ @scope.close
75
+ ensure
76
+ perform_on_finish_span
77
+ end
78
+ end
79
+
80
+ def build_scope(method, url, context)
81
+ @tracer.start_active_span(
82
+ method,
83
+ child_of: context,
84
+ tags: {
85
+ "component" => "rack",
86
+ "span.kind" => "server",
87
+ "http.method" => method,
88
+ "http.url" => url,
89
+ },
90
+ )
91
+ end
92
+
93
+ def perform_on_start_span(env, span, on_start_span)
94
+ on_start_span&.call(span)
95
+ env["rack.span"] = span
96
+ end
97
+
98
+ def set_tag(span, status_code, env)
99
+ span.set_tag("http.status_code", status_code)
100
+ route = route_from_env(env)
101
+ span.operation_name = route if route
102
+ end
103
+
104
+ def route_from_env(env)
105
+ method = env[REQUEST_METHOD]
106
+ if (sinatra_route = env["sinatra.route"])
107
+ sinatra_route
108
+ elsif (rails_controller = env["action_controller.instance"])
109
+ "#{method} #{rails_controller.controller_name}/#{rails_controller.action_name}"
110
+ elsif (grape_route_args = env["grape.routing_args"] || env["rack.routing_args"])
111
+ "#{method} #{grape_route_from_args(grape_route_args)}"
112
+ end
113
+ end
114
+
115
+ def grape_route_from_args(route_args)
116
+ route_info = route_args[:route_info]
117
+ if route_info.respond_to?(:path)
118
+ route_info.path
119
+ elsif (rack_route_options = route_info.instance_variable_get(:@options))
120
+ rack_route_options[:path]
121
+ end
122
+ end
123
+
124
+ def perform_on_finish_span
125
+ return unless @on_finish_span
126
+ @on_finish_span.call(@span)
127
+ end
128
+ end
129
+ end
5
130
  end
@@ -1,26 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JCW
4
- class Subscriber
5
- class << self
6
- def subscribe_to_event!(event_name)
7
- ActiveSupport::Notifications.subscribe(event_name) do |*args|
8
- (span = OpenTracing.scope_manager.active&.span) or next
9
- event = ActiveSupport::Notifications::Event.new(*args)
10
- span.log_kv(context: span_context(event))
11
- end
4
+ module Subscriber
5
+ extend self
6
+
7
+ IGNORED_PAYLOAD_KEYS = %i[request response headers exception exception_object].freeze
8
+
9
+ def subscribe_to_event!(event)
10
+ ActiveSupport::Notifications.subscribe(event) do |name, _start, _finish, _uid, payload|
11
+ add(name, payload)
12
12
  end
13
+ end
13
14
 
14
- private
15
+ def add(name, payload)
16
+ # skip Rails internal events
17
+ return if name.start_with?("!")
15
18
 
16
- def span_context(event)
17
- {
18
- name: event.name,
19
- time: event.time,
20
- payload: event.payload.to_s,
21
- transaction_id: event.transaction_id,
22
- }.as_json
19
+ span = OpenTracing.scope_manager.active&.span
20
+ return if span.blank?
21
+
22
+ if payload.is_a?(Hash)
23
+ # we should only mutate the copy of the payload
24
+ payload = payload.dup
25
+ IGNORED_PAYLOAD_KEYS.each { |key| payload.delete(key) if payload.key?(key) }
23
26
  end
27
+
28
+ span.log_kv(message: name, context: JSON.dump(payload))
24
29
  end
25
30
  end
26
31
  end
data/lib/jcw/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JCW
4
- VERSION = "0.1.2"
4
+ VERSION = "0.2.2"
5
5
  end
data/lib/jcw/wrapper.rb CHANGED
@@ -17,10 +17,12 @@ module JCW
17
17
  end
18
18
  end
19
19
 
20
- require_relative "tracing"
21
20
  require_relative "init"
22
21
  require_relative "subscriber"
23
22
  require_relative "http_tracer"
24
23
  require_relative "rack_tracer"
24
+ require_relative "interceptors/gruf/client"
25
+ require_relative "interceptors/gruf/server"
26
+ require_relative "interceptors/gruf/hpack"
25
27
  require_relative "logger"
26
28
  require_relative "logger_extension"
data/lib/jcw.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rack/tracer"
3
+ require "opentracing"
4
4
  require "jaeger/client"
5
5
  require "active_support"
6
6
  require "httprb-opentracing"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jcw
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Starovojtov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-01 00:00:00.000000000 Z
11
+ date: 2021-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -17,6 +17,9 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '5.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: 7.0.0
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -24,48 +27,51 @@ dependencies:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '5.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 7.0.0
27
33
  - !ruby/object:Gem::Dependency
28
- name: httprb-opentracing
34
+ name: gruf
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: 0.4.0
39
+ version: '2.10'
34
40
  type: :runtime
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: 0.4.0
46
+ version: '2.10'
41
47
  - !ruby/object:Gem::Dependency
42
- name: jaeger-client
48
+ name: httprb-opentracing
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
51
  - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: 1.1.0
53
+ version: 0.4.0
48
54
  type: :runtime
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
58
  - - "~>"
53
59
  - !ruby/object:Gem::Version
54
- version: 1.1.0
60
+ version: 0.4.0
55
61
  - !ruby/object:Gem::Dependency
56
- name: rack-tracer
62
+ name: jaeger-client
57
63
  requirement: !ruby/object:Gem::Requirement
58
64
  requirements:
59
65
  - - "~>"
60
66
  - !ruby/object:Gem::Version
61
- version: 0.9.0
67
+ version: 1.1.0
62
68
  type: :runtime
63
69
  prerelease: false
64
70
  version_requirements: !ruby/object:Gem::Requirement
65
71
  requirements:
66
72
  - - "~>"
67
73
  - !ruby/object:Gem::Version
68
- version: 0.9.0
74
+ version: 1.1.0
69
75
  - !ruby/object:Gem::Dependency
70
76
  name: bundler
71
77
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +128,20 @@ dependencies:
122
128
  - - ">="
123
129
  - !ruby/object:Gem::Version
124
130
  version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: opentracing_test_tracer
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
125
145
  - !ruby/object:Gem::Dependency
126
146
  name: pry
127
147
  requirement: !ruby/object:Gem::Requirement
@@ -244,17 +264,20 @@ files:
244
264
  - lib/jcw/config.rb
245
265
  - lib/jcw/http_tracer.rb
246
266
  - lib/jcw/init.rb
267
+ - lib/jcw/interceptors/gruf/client.rb
268
+ - lib/jcw/interceptors/gruf/hpack.rb
269
+ - lib/jcw/interceptors/gruf/server.rb
247
270
  - lib/jcw/logger.rb
248
271
  - lib/jcw/logger_extension.rb
249
272
  - lib/jcw/rack_tracer.rb
250
273
  - lib/jcw/subscriber.rb
251
- - lib/jcw/tracing.rb
252
274
  - lib/jcw/version.rb
253
275
  - lib/jcw/wrapper.rb
254
276
  homepage: https://github.com/Cado-Labs/jcw
255
277
  licenses:
256
278
  - MIT
257
- metadata: {}
279
+ metadata:
280
+ rubygems_mfa_required: 'true'
258
281
  post_install_message:
259
282
  rdoc_options: []
260
283
  require_paths:
@@ -263,7 +286,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
263
286
  requirements:
264
287
  - - ">="
265
288
  - !ruby/object:Gem::Version
266
- version: 2.7.0
289
+ version: 2.6.0
267
290
  required_rubygems_version: !ruby/object:Gem::Requirement
268
291
  requirements:
269
292
  - - ">="
data/lib/jcw/tracing.rb DELETED
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JCW
4
- module Tracing
5
- class << self
6
- attr_reader :subscribers
7
-
8
- def register_subscribers(subscribers)
9
- @subscribers = subscribers
10
- end
11
-
12
- def subscribe_tracing_events
13
- subscribers.each { |subscriber| Subscriber.subscribe_to_event!(subscriber) }
14
- end
15
- end
16
- end
17
- end