jcw 0.1.3 → 0.2.3

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: c7621b3db92b4172f29ae46a914d6f5a33611f276dfaa17d1effeff36f16c68b
4
- data.tar.gz: c9ac2ea12ee2862fcb762673dd5285e7422b86fe91c38a39f9fa66bd890fa83c
3
+ metadata.gz: 2b1e12954a296bbc3e7413110a7b151fe38c0d422e156cebbd5ae7157bbe111b
4
+ data.tar.gz: '00488dffa129ca3c4a2b45fb3f8f947f1dec9b4310b8a900813426afa397fc92'
5
5
  SHA512:
6
- metadata.gz: e6558c6b64a50a283c6e9a97024ee8191fd595bb73b071ae84259ec7a61d51ab4046b6f70e33f335bedf7888f791f170375e2b7f3ab428a373259716c9acfe19
7
- data.tar.gz: c5d6da1d532632920fdce571c254737654d0e37c7aca2d89bf8852126ae15882c3f4965461b341ecfcbf04add3a366010b103d5cd83cf2fe1df8b9c71860e15d
6
+ metadata.gz: 61b7221435873848d3bb19e0e9ca30157c127601633fb4ca129fbc150fe5da98f2013bdc334139c455801fcb7fe90db8fb47809a4b1bba86f4e58d8ab1034162
7
+ data.tar.gz: 1140c437317341c6836f196711496f9dedb0e0959571d7f882c9750f6c690ca3026dd807916fd958c7a7628587cea5e985da1b55631f9b4fcbc15691a8cf7e49
@@ -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.3)
5
- activesupport (>= 5.0)
4
+ jcw (0.2.3)
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.2)
53
+ googleapis-common-protos-types (1.3.0)
54
+ google-protobuf (~> 3.14)
55
+ grpc (1.41.0)
56
+ google-protobuf (~> 3.17)
57
+ googleapis-common-protos-types (~> 1.0)
58
+ grpc-tools (1.41.0)
59
+ gruf (2.12.0)
60
+ activesupport (> 4)
61
+ concurrent-ruby (> 1)
62
+ e2mmap (>= 0.1)
63
+ grpc (~> 1.10, <= 1.41.0)
64
+ grpc-tools (~> 1.10, <= 1.41.0)
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,20 +77,21 @@ 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)
94
+ minitest (5.15.0)
77
95
  nokogiri (1.12.5)
78
96
  mini_portile2 (~> 2.6.1)
79
97
  racc (~> 1.4)
@@ -82,33 +100,33 @@ GEM
82
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
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
 
@@ -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,16 +60,17 @@ 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,
73
+ JCW::Rack::Tracer,
72
74
  on_finish_span: lambda do |span|
73
75
  JCW::Logger.current.logs.each { |log| span.log_kv(**log) }
74
76
  JCW::Logger.current.clear # Do not forget to avoid memory leaks
@@ -80,6 +82,43 @@ end
80
82
  ```
81
83
  - `config.subscribe_to` - not recommended for UDP sender, because default max packet size is 65,000 bytes.
82
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
+
83
122
  ### Contributing
84
123
 
85
124
  - Fork it ( https://github.com/Cado-Labs/jcw )
@@ -95,7 +134,7 @@ Released under MIT License.
95
134
  ## Supporting
96
135
 
97
136
  <a href="https://github.com/Cado-Labs">
98
- <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" />
99
138
  </a>
100
139
 
101
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)
@@ -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,139 @@
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
+ return @app.call(env) if @ignore_paths.include?(path)
42
+
43
+ set_extract_env(env)
44
+ context = @tracer.extract(OpenTracing::FORMAT_TEXT_MAP, env) if @trust_incoming_span
45
+ scope = build_scope(method, url, context)
46
+ span = scope.span
47
+ perform_on_start_span(env, span, @on_start_span)
48
+ call_request(env, span)
49
+ rescue *@errors => error
50
+ build_error_log(span, error)
51
+ raise
52
+ ensure
53
+ begin
54
+ close_scope(scope)
55
+ ensure
56
+ perform_on_finish_span(span)
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def set_extract_env(env)
63
+ env["uber-trace-id"] = env["HTTP_UBER_TRACE_ID"]
64
+ end
65
+
66
+ def build_scope(method, url, context)
67
+ @tracer.start_active_span(
68
+ method,
69
+ child_of: context,
70
+ tags: {
71
+ "component" => "rack",
72
+ "span.kind" => "server",
73
+ "http.method" => method,
74
+ "http.url" => url,
75
+ },
76
+ )
77
+ end
78
+
79
+ def perform_on_start_span(env, span, on_start_span)
80
+ on_start_span&.call(span)
81
+ env["rack.span"] = span
82
+ end
83
+
84
+ def call_request(env, span)
85
+ @app.call(env).tap do |status_code, _headers, _body|
86
+ set_tag(span, status_code, env)
87
+ end
88
+ end
89
+
90
+ def set_tag(span, status_code, env)
91
+ span.set_tag("http.status_code", status_code)
92
+ route = route_from_env(env)
93
+ span.operation_name = route
94
+ end
95
+
96
+ def route_from_env(env)
97
+ method = env[REQUEST_METHOD]
98
+ if (sinatra_route = env["sinatra.route"])
99
+ sinatra_route
100
+ elsif (rails_controller = env["action_controller.instance"])
101
+ "#{method} #{rails_controller.controller_name}/#{rails_controller.action_name}"
102
+ elsif (grape_route_args = env["grape.routing_args"] || env["rack.routing_args"])
103
+ "#{method} #{grape_route_from_args(grape_route_args)}"
104
+ else
105
+ "#{method} #{env[REQUEST_PATH] || env["SCRIPT_NAME"] || env["PATH_INFO"]}".strip
106
+ end
107
+ end
108
+
109
+ def grape_route_from_args(route_args)
110
+ route_info = route_args[:route_info]
111
+ if route_info.respond_to?(:path)
112
+ route_info.path
113
+ elsif (rack_route_options = route_info.instance_variable_get(:@options))
114
+ rack_route_options[:path]
115
+ end
116
+ end
117
+
118
+ def build_error_log(span, error)
119
+ span.set_tag("error", true)
120
+ span.log_kv(
121
+ event: "error",
122
+ "error.kind": error.class.to_s,
123
+ "error.object": error,
124
+ message: error.message,
125
+ stack: error.backtrace.join("\n"),
126
+ )
127
+ end
128
+
129
+ def perform_on_finish_span(span)
130
+ return unless @on_finish_span
131
+ @on_finish_span.call(span)
132
+ end
133
+
134
+ def close_scope(scope)
135
+ scope&.close
136
+ end
137
+ end
138
+ end
5
139
  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.3"
4
+ VERSION = "0.2.3"
5
5
  end
data/lib/jcw/wrapper.rb CHANGED
@@ -21,5 +21,8 @@ require_relative "init"
21
21
  require_relative "subscriber"
22
22
  require_relative "http_tracer"
23
23
  require_relative "rack_tracer"
24
+ require_relative "interceptors/gruf/client"
25
+ require_relative "interceptors/gruf/server"
26
+ require_relative "interceptors/gruf/hpack"
24
27
  require_relative "logger"
25
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.3
4
+ version: 0.2.3
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-10-05 00:00:00.000000000 Z
11
+ date: 2022-01-11 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,6 +264,9 @@ 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
@@ -253,7 +276,8 @@ files:
253
276
  homepage: https://github.com/Cado-Labs/jcw
254
277
  licenses:
255
278
  - MIT
256
- metadata: {}
279
+ metadata:
280
+ rubygems_mfa_required: 'true'
257
281
  post_install_message:
258
282
  rdoc_options: []
259
283
  require_paths:
@@ -262,7 +286,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
262
286
  requirements:
263
287
  - - ">="
264
288
  - !ruby/object:Gem::Version
265
- version: 2.7.0
289
+ version: 2.6.0
266
290
  required_rubygems_version: !ruby/object:Gem::Requirement
267
291
  requirements:
268
292
  - - ">="