determinator 2.3.1 → 2.4.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: '08378908b45b61bc3c88232e1e480db1200acfe98d3b42dfd10e27420067b5e8'
4
- data.tar.gz: ee822d9401d3c8a0019ae45ecdebd1f2becd56e7081764dd92ecbba9a30b6fa5
3
+ metadata.gz: 63baaf3ee379eef31694ec105e48407970d0e53e6906af8e9a1746cfac5ca5e4
4
+ data.tar.gz: 88b70dc55dedc32c98dc1eb3619fd420471127c812a7cdda7086c13349d3bdca
5
5
  SHA512:
6
- metadata.gz: '0288df451ba45366adfb9ffb1f76147c0e565ee647d278f00b23877490cdbb7ebd4fd1b832e46f3812616894d576ee285f509df67e54a68a69415ce6370bfc65'
7
- data.tar.gz: 93cc9692b60bc97bfcf629995bfd38afdbf00161864bec8b5b15568a0b409470d17b52ad1673270444afd7080ff857b10605cea4c0d733b41fbb633a8bf13dd5
6
+ metadata.gz: 1ea1835cd7e0953c5d6747bbcbddfc43804cd33ffc3ed136c72ede003c2a24c9357c7746081370404b9851788a0b64b9d45a633657365524ed77cf6a5a69bf67
7
+ data.tar.gz: 2db13fd8793c724554c2ba4766e3e769eb5d9e4042481b153a205337c5b0cfaad1bd6a691b552ee9a25109f9b8bb7b6dc6837570e909bf5d60fab1f4fe056e86
@@ -10,6 +10,10 @@ jobs:
10
10
  steps:
11
11
  - checkout
12
12
 
13
+ - run:
14
+ name: Install bundler
15
+ command: gem install bundler -v 2.1.4
16
+
13
17
  - run:
14
18
  name: Bundle Install
15
19
  command: bundle install
@@ -30,6 +34,10 @@ jobs:
30
34
  steps:
31
35
  - checkout
32
36
 
37
+ - run:
38
+ name: Install bundler
39
+ command: gem install bundler -v 2.1.4
40
+
33
41
  - run:
34
42
  name: Bundle Install
35
43
  command: bundle install
@@ -50,6 +58,10 @@ jobs:
50
58
  steps:
51
59
  - checkout
52
60
 
61
+ - run:
62
+ name: Install bundler
63
+ command: gem install bundler -v 2.1.4
64
+
53
65
  - run:
54
66
  name: Bundle Install
55
67
  command: bundle install
@@ -1,3 +1,8 @@
1
+ # 2.4.0
2
+
3
+ Feature:
4
+ - Add tracker middleware
5
+
1
6
  # v2.3.1 (2019-05-25)
2
7
 
3
8
  Feature:
data/README.md CHANGED
@@ -204,7 +204,7 @@ variant = determinator.which_variant(
204
204
  app_version: "1.2.3"
205
205
  }
206
206
  )
207
- ```
207
+ ```
208
208
  The `app_version` constraint for that flag needs to follow ruby gem version constraints. We support the following operators: `>, <, >=, <=, ~>`. For example:
209
209
  `app_version: ">=1.2.0"`
210
210
 
@@ -220,6 +220,8 @@ Determinator.configure(retrieval: nil)
220
220
 
221
221
  * Tag your rspec test with `:determinator_support`, so the `forced_determination` helper method will be available.
222
222
 
223
+ Please note, `RSpec::Determinator` mocks a determination _outcome_, not the process of choosing one. Set the `only_for` argument to be the properties you require for Determinator to return the specified outcome. At the moment this mock does not allow for the testing of the `id` or `guid` arguments (only the properties).
224
+
223
225
  ```ruby
224
226
  RSpec.describe "something", :determinator_support do
225
227
 
@@ -251,6 +253,70 @@ end
251
253
 
252
254
  * Check out [the specs for `RSpec::Determinator`](spec/rspec/determinator_spec.rb) to find out what you can do!
253
255
 
256
+ ## Tracking
257
+
258
+ The library includes a middleware to track all determinations being made, allowing logging them at the end of the request
259
+ (including some useful request metrics).
260
+
261
+ To enable it, e.g. in Rails:
262
+
263
+ ```ruby
264
+ # config/application.rb
265
+
266
+ require 'determinator/tracking/rack/middleware'
267
+
268
+ # possibly near the top of your stack, in case other middlewares make determinations
269
+ config.middleware.use Determinator::Tracking::Rack::Middleware
270
+ ```
271
+
272
+ or for Sidekiq:
273
+
274
+ ```ruby
275
+ # config/initializers/sidekiq.rb
276
+
277
+ require 'determinator/tracking/sidekiq/middleware'
278
+
279
+ Sidekiq.configure_server do |config|
280
+ config.server_middleware do |chain|
281
+ chain.add Determinator::Tracking::Sidekiq::Middleware
282
+ end
283
+ end
284
+ ```
285
+
286
+ ```ruby
287
+ # config/initializers/determinator.rb
288
+
289
+ require 'determinator/tracking'
290
+
291
+ Determinator::Tracking.on_request do |r|
292
+ Rails.logger.info("tag=determinator_request type=#{r.type} request_time=#{r.time} error=#{r.error?} response_status=#{r.attributes[:status]} sidekiq_queue=#{r.attributes[:queue]}")
293
+ r.determinations.each do |d|
294
+ Rails.logger.info("tag=determination id=#{d.id} guid=#{d.guid} flag=#{d.feature_id} result=#{d.determination}")
295
+ end
296
+ end
297
+
298
+ # If using an APM, you can provide trace information on the request by providing a get_context hook: e.g.
299
+
300
+ Determinator::Tracking.get_context do
301
+ span = Datadog.tracer.active_root_span
302
+ return unless span
303
+ Determinator::Tracking::Context.new(
304
+ request_id: span.trace_id,
305
+ service: span.service,
306
+ resource: span.resource,
307
+ type: span.type,
308
+ meta: span.meta
309
+ )
310
+ end
311
+ ```
312
+
313
+ NOTE: this is implemented by keeping the list of requests in a per-request thread-local variable, which means that determinations will only be tracked on the main thread.
314
+
315
+ If your application is spinning out worker threads, you should make the determinations in the main thread if possible; or collect them from your worker threads and track them in the main thread with
316
+ ```
317
+ Determinator::Tracking.track(id, guid, feature, determination)
318
+ ```
319
+
254
320
  ## Testing this library
255
321
 
256
322
  This library makes use of the [Determinator Standard Tests](https://github.com/deliveroo/determinator-standard-tests) to ensure that it conforms to the same specification as determinator libraries in other languages. The standard tests can be updated to the latest ones available by updating the submodule:
@@ -23,11 +23,12 @@ Gem::Specification.new do |spec|
23
23
  spec.add_runtime_dependency "faraday"
24
24
  spec.add_runtime_dependency "semantic", "~> 1.6"
25
25
 
26
- spec.add_development_dependency "bundler", "~> 1.13"
26
+ spec.add_development_dependency "bundler", "~> 2.1.4"
27
27
  spec.add_development_dependency "rake", "~> 10.0"
28
28
  spec.add_development_dependency "rspec", "~> 3.0"
29
29
  spec.add_development_dependency "rspec-its", "~> 1.2"
30
30
  spec.add_development_dependency "guard-rspec", "~> 4.7"
31
31
  spec.add_development_dependency "factory_girl", "~> 4.8"
32
32
  spec.add_development_dependency 'webmock'
33
+ spec.add_development_dependency "sidekiq"
33
34
  end
@@ -6,6 +6,7 @@ require 'determinator/cache/fetch_wrapper'
6
6
  require 'determinator/serializers/json'
7
7
  require 'determinator/missing_response'
8
8
  require 'determinator/error_response'
9
+ require 'determinator/tracking'
9
10
 
10
11
 
11
12
  module Determinator
@@ -83,6 +84,7 @@ module Determinator
83
84
  end
84
85
 
85
86
  def notice_determination(id, guid, feature, determination)
87
+ Determinator::Tracking.track(id, guid, feature, determination)
86
88
  return unless @determination_callback
87
89
  @determination_callback.call(id, guid, feature, determination)
88
90
  end
@@ -0,0 +1,62 @@
1
+ require 'determinator/tracking/tracker'
2
+ require 'determinator/tracking/context'
3
+
4
+ module Determinator
5
+ module Tracking
6
+ class << self
7
+ def instance
8
+ Thread.current[:determinator_tracker]
9
+ end
10
+
11
+ def start!(type)
12
+ Thread.current[:determinator_tracker] = Tracker.new(type)
13
+ end
14
+
15
+ def finish!(error:, **attributes)
16
+ return false unless started?
17
+ request = instance.finish!(error: error, **attributes)
18
+ clear!
19
+ report(request)
20
+ request
21
+ end
22
+
23
+ def clear!
24
+ Thread.current[:determinator_tracker] = nil
25
+ end
26
+
27
+ def started?
28
+ !!instance
29
+ end
30
+
31
+ def track(id, guid, feature, determination)
32
+ return false unless started?
33
+ instance.track(id, guid, feature, determination)
34
+ end
35
+
36
+ def on_request(&block)
37
+ @on_request = block
38
+ end
39
+
40
+ def report(request)
41
+ return unless @on_request
42
+ @on_request.call(request)
43
+ end
44
+
45
+ def get_context(&block)
46
+ @get_context = block
47
+ end
48
+
49
+ def context
50
+ return unless @get_context
51
+ @get_context.call
52
+ rescue
53
+ nil
54
+ end
55
+
56
+ def clear_hooks!
57
+ @on_request = nil
58
+ @get_context = nil
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,15 @@
1
+ module Determinator
2
+ module Tracking
3
+ class Context
4
+ attr_reader :request_id, :service, :resource
5
+
6
+ def initialize(request_id: nil, service: nil, resource: nil, type: nil, meta: {})
7
+ @request_id = request_id
8
+ @service = service
9
+ @resource = resource
10
+ @type = type
11
+ @meta = meta
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ module Determinator
2
+ module Tracking
3
+ class Determination
4
+ attr_reader :id, :guid, :feature_id, :determination
5
+
6
+ def initialize(id:, guid:, feature_id:, determination:)
7
+ @id = id
8
+ @guid = guid
9
+ @feature_id = feature_id
10
+ @determination = determination
11
+ end
12
+
13
+ def ==(other)
14
+ id == other.id && guid == other.guid && feature_id == other.feature_id && determination == other.determination
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ require 'determinator/tracking'
2
+
3
+ module Determinator
4
+ module Tracking
5
+ module Rack
6
+ class Middleware
7
+ def initialize(app)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ Determinator::Tracking.start!(:rack)
13
+ status, headers, response = @app.call(env)
14
+ [status, headers, response]
15
+ rescue
16
+ error = true
17
+ raise
18
+ ensure
19
+ Determinator::Tracking.finish!(status: status, error: !!error)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ module Determinator
2
+ module Tracking
3
+ class Request
4
+ attr_reader :type, :time, :error, :attributes, :determinations, :context
5
+
6
+ def initialize(type:, time:, error:, attributes:, determinations:, context: nil)
7
+ @type = type
8
+ @time = time
9
+ @error = error
10
+ @attributes = attributes
11
+ @determinations = determinations
12
+ @context = context
13
+ end
14
+
15
+ def error?
16
+ error
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ require 'determinator/tracking'
2
+
3
+ module Determinator
4
+ module Tracking
5
+ module Sidekiq
6
+ class Middleware
7
+ # @param [Object] worker the worker instance
8
+ # @param [Hash] job the full job payload
9
+ # * @see https://github.com/mperham/sidekiq/wiki/Job-Format
10
+ # @param [String] queue the name of the queue the job was pulled from
11
+ # @yield the next middleware in the chain or worker `perform` method
12
+ # @return [Void]
13
+ def call(worker, job, queue)
14
+ begin
15
+ Determinator::Tracking.start!(:sidekiq)
16
+ yield
17
+ rescue => ex
18
+ error = true
19
+ raise
20
+ ensure
21
+ Determinator::Tracking.finish!(queue: queue, error: !!error)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,43 @@
1
+ require 'determinator/tracking/determination'
2
+ require 'determinator/tracking/request'
3
+
4
+ module Determinator
5
+ module Tracking
6
+ class Tracker
7
+ attr_reader :type, :determinations
8
+
9
+ def initialize(type)
10
+ @determinations = []
11
+ @type = type
12
+ @start = now
13
+ end
14
+
15
+ def track(id, guid, feature, determination)
16
+ determinations << Determinator::Tracking::Determination.new(
17
+ id: id,
18
+ guid: guid,
19
+ feature_id: feature.identifier,
20
+ determination: determination
21
+ )
22
+ end
23
+
24
+ def finish!(error:, **attributes)
25
+ request_time = now - @start
26
+ Determinator::Tracking::Request.new(
27
+ type: type,
28
+ time: request_time,
29
+ error: error,
30
+ attributes: attributes,
31
+ determinations: determinations,
32
+ context: Determinator::Tracking.context
33
+ )
34
+ end
35
+
36
+ private
37
+
38
+ def now
39
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,3 +1,3 @@
1
1
  module Determinator
2
- VERSION = '2.3.1'
2
+ VERSION = '2.4.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: determinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.1
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JP Hastings-Spital
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-25 00:00:00.000000000 Z
11
+ date: 2020-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.13'
47
+ version: 2.1.4
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.13'
54
+ version: 2.1.4
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: sidekiq
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  description:
140
154
  email:
141
155
  - jp@deliveroo.co.uk
@@ -204,6 +218,13 @@ files:
204
218
  - lib/determinator/retrieve/null_retriever.rb
205
219
  - lib/determinator/serializers/json.rb
206
220
  - lib/determinator/target_group.rb
221
+ - lib/determinator/tracking.rb
222
+ - lib/determinator/tracking/context.rb
223
+ - lib/determinator/tracking/determination.rb
224
+ - lib/determinator/tracking/rack/middleware.rb
225
+ - lib/determinator/tracking/request.rb
226
+ - lib/determinator/tracking/sidekiq/middleware.rb
227
+ - lib/determinator/tracking/tracker.rb
207
228
  - lib/determinator/version.rb
208
229
  - lib/rspec/determinator.rb
209
230
  homepage: https://github.com/deliveroo/determinator
@@ -225,8 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
246
  - !ruby/object:Gem::Version
226
247
  version: '0'
227
248
  requirements: []
228
- rubyforge_project:
229
- rubygems_version: 2.7.9
249
+ rubygems_version: 3.0.3
230
250
  signing_key:
231
251
  specification_version: 4
232
252
  summary: Determine which experiments and features a specific actor should see.