determinator 2.3.1 → 2.4.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 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.