launchdarkly-server-sdk 6.3.1 → 6.3.4

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.
@@ -0,0 +1,63 @@
1
+ require "ldclient-rb/impl/event_types"
2
+
3
+ module LaunchDarkly
4
+ module Impl
5
+ EventSummary = Struct.new(:start_date, :end_date, :counters)
6
+
7
+ EventSummaryFlagInfo = Struct.new(:default, :versions)
8
+
9
+ EventSummaryFlagVariationCounter = Struct.new(:value, :count)
10
+
11
+ # Manages the state of summarizable information for the EventProcessor, including the
12
+ # event counters and user deduplication. Note that the methods of this class are
13
+ # deliberately not thread-safe; the EventProcessor is responsible for enforcing
14
+ # synchronization across both the summarizer and the event queue.
15
+ class EventSummarizer
16
+ class Counter
17
+ end
18
+
19
+ def initialize
20
+ clear
21
+ end
22
+
23
+ # Adds this event to our counters, if it is a type of event we need to count.
24
+ def summarize_event(event)
25
+ return if !event.is_a?(LaunchDarkly::Impl::EvalEvent)
26
+
27
+ counters_for_flag = @counters[event.key]
28
+ if counters_for_flag.nil?
29
+ counters_for_flag = EventSummaryFlagInfo.new(event.default, Hash.new)
30
+ @counters[event.key] = counters_for_flag
31
+ end
32
+ counters_for_flag_version = counters_for_flag.versions[event.version]
33
+ if counters_for_flag_version.nil?
34
+ counters_for_flag_version = Hash.new
35
+ counters_for_flag.versions[event.version] = counters_for_flag_version
36
+ end
37
+ variation_counter = counters_for_flag_version[event.variation]
38
+ if variation_counter.nil?
39
+ counters_for_flag_version[event.variation] = EventSummaryFlagVariationCounter.new(event.value, 1)
40
+ else
41
+ variation_counter.count = variation_counter.count + 1
42
+ end
43
+ time = event.timestamp
44
+ if !time.nil?
45
+ @start_date = time if @start_date == 0 || time < @start_date
46
+ @end_date = time if time > @end_date
47
+ end
48
+ end
49
+
50
+ # Returns a snapshot of the current summarized event data, and resets this state.
51
+ def snapshot
52
+ ret = EventSummary.new(@start_date, @end_date, @counters)
53
+ ret
54
+ end
55
+
56
+ def clear
57
+ @start_date = 0
58
+ @end_date = 0
59
+ @counters = {}
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,90 @@
1
+ module LaunchDarkly
2
+ module Impl
3
+ class Event
4
+ def initialize(timestamp, user)
5
+ @timestamp = timestamp
6
+ @user = user
7
+ end
8
+
9
+ attr_reader :timestamp
10
+ attr_reader :kind
11
+ attr_reader :user
12
+ end
13
+
14
+ class EvalEvent < Event
15
+ def initialize(timestamp, user, key, version = nil, variation = nil, value = nil, reason = nil, default = nil,
16
+ track_events = false, debug_until = nil, prereq_of = nil)
17
+ super(timestamp, user)
18
+ @key = key
19
+ @version = version
20
+ @variation = variation
21
+ @value = value
22
+ @reason = reason
23
+ @default = default
24
+ # avoid setting rarely-used attributes if they have no value - this saves a little space per instance
25
+ @track_events = track_events if track_events
26
+ @debug_until = debug_until if debug_until
27
+ @prereq_of = prereq_of if prereq_of
28
+ end
29
+
30
+ attr_reader :key
31
+ attr_reader :version
32
+ attr_reader :variation
33
+ attr_reader :value
34
+ attr_reader :reason
35
+ attr_reader :default
36
+ attr_reader :track_events
37
+ attr_reader :debug_until
38
+ attr_reader :prereq_of
39
+ end
40
+
41
+ class IdentifyEvent < Event
42
+ def initialize(timestamp, user)
43
+ super(timestamp, user)
44
+ end
45
+ end
46
+
47
+ class CustomEvent < Event
48
+ def initialize(timestamp, user, key, data = nil, metric_value = nil)
49
+ super(timestamp, user)
50
+ @key = key
51
+ @data = data if !data.nil?
52
+ @metric_value = metric_value if !metric_value.nil?
53
+ end
54
+
55
+ attr_reader :key
56
+ attr_reader :data
57
+ attr_reader :metric_value
58
+ end
59
+
60
+ class AliasEvent < Event
61
+ def initialize(timestamp, key, context_kind, previous_key, previous_context_kind)
62
+ super(timestamp, nil)
63
+ @key = key
64
+ @context_kind = context_kind
65
+ @previous_key = previous_key
66
+ @previous_context_kind = previous_context_kind
67
+ end
68
+
69
+ attr_reader :key
70
+ attr_reader :context_kind
71
+ attr_reader :previous_key
72
+ attr_reader :previous_context_kind
73
+ end
74
+
75
+ class IndexEvent < Event
76
+ def initialize(timestamp, user)
77
+ super(timestamp, user)
78
+ end
79
+ end
80
+
81
+ class DebugEvent < Event
82
+ def initialize(eval_event)
83
+ super(eval_event.timestamp, eval_event.user)
84
+ @eval_event = eval_event
85
+ end
86
+
87
+ attr_reader :eval_event
88
+ end
89
+ end
90
+ end
@@ -35,7 +35,7 @@ module LaunchDarkly
35
35
  @client = Aws::DynamoDB::Client.new(opts[:dynamodb_opts] || {})
36
36
  end
37
37
 
38
- @logger.info("${description}: using DynamoDB table \"#{table_name}\"")
38
+ @logger.info("#{description}: using DynamoDB table \"#{table_name}\"")
39
39
  end
40
40
 
41
41
  def stop
@@ -36,7 +36,7 @@ module LaunchDarkly
36
36
  # @option opts [Integer] :capacity (1000) maximum number of items in the cache
37
37
  # @return [LaunchDarkly::Interfaces::FeatureStore] a feature store object
38
38
  #
39
- def self.new_feature_store(opts, &block)
39
+ def self.new_feature_store(opts = {})
40
40
  core = LaunchDarkly::Impl::Integrations::Consul::ConsulFeatureStoreCore.new(opts)
41
41
  return LaunchDarkly::Integrations::Util::CachingStoreWrapper.new(core, opts)
42
42
  end
@@ -46,7 +46,7 @@ module LaunchDarkly
46
46
  # @option opts [Integer] :capacity (1000) maximum number of items in the cache
47
47
  # @return [LaunchDarkly::Interfaces::FeatureStore] a feature store object
48
48
  #
49
- def self.new_feature_store(table_name, opts)
49
+ def self.new_feature_store(table_name, opts = {})
50
50
  core = LaunchDarkly::Impl::Integrations::DynamoDB::DynamoDBFeatureStoreCore.new(table_name, opts)
51
51
  LaunchDarkly::Integrations::Util::CachingStoreWrapper.new(core, opts)
52
52
  end
@@ -58,7 +58,7 @@ module LaunchDarkly
58
58
  # lifecycle to be independent of the SDK client
59
59
  # @return [LaunchDarkly::Interfaces::FeatureStore] a feature store object
60
60
  #
61
- def self.new_feature_store(opts)
61
+ def self.new_feature_store(opts = {})
62
62
  return RedisFeatureStore.new(opts)
63
63
  end
64
64
 
@@ -1,7 +1,6 @@
1
1
  require "ldclient-rb/impl/big_segments"
2
2
  require "ldclient-rb/impl/diagnostic_events"
3
3
  require "ldclient-rb/impl/evaluator"
4
- require "ldclient-rb/impl/event_factory"
5
4
  require "ldclient-rb/impl/store_client_wrapper"
6
5
  require "concurrent/atomics"
7
6
  require "digest/sha1"
@@ -46,9 +45,6 @@ module LaunchDarkly
46
45
 
47
46
  @sdk_key = sdk_key
48
47
 
49
- @event_factory_default = EventFactory.new(false)
50
- @event_factory_with_reasons = EventFactory.new(true)
51
-
52
48
  # We need to wrap the feature store object with a FeatureStoreClientWrapper in order to add
53
49
  # some necessary logic around updates. Unfortunately, we have code elsewhere that accesses
54
50
  # the feature store through the Config object, so we need to make a new Config that uses
@@ -65,7 +61,7 @@ module LaunchDarkly
65
61
  get_segment = lambda { |key| @store.get(SEGMENTS, key) }
66
62
  get_big_segments_membership = lambda { |key| @big_segment_store_manager.get_user_membership(key) }
67
63
  @evaluator = LaunchDarkly::Impl::Evaluator.new(get_flag, get_segment, get_big_segments_membership, @config.logger)
68
-
64
+
69
65
  if !@config.offline? && @config.send_events && !@config.diagnostic_opt_out?
70
66
  diagnostic_accumulator = Impl::DiagnosticAccumulator.new(Impl::DiagnosticAccumulator.create_diagnostic_id(sdk_key))
71
67
  else
@@ -178,7 +174,7 @@ module LaunchDarkly
178
174
  # Other supported user attributes include IP address, country code, and an arbitrary hash of
179
175
  # custom attributes. For more about the supported user properties and how they work in
180
176
  # LaunchDarkly, see [Targeting users](https://docs.launchdarkly.com/home/flags/targeting-users).
181
- #
177
+ #
182
178
  # The optional `:privateAttributeNames` user property allows you to specify a list of
183
179
  # attribute names that should not be sent back to LaunchDarkly.
184
180
  # [Private attributes](https://docs.launchdarkly.com/home/users/attributes#creating-private-user-attributes)
@@ -202,7 +198,7 @@ module LaunchDarkly
202
198
  # @return the variation to show the user, or the default value if there's an an error
203
199
  #
204
200
  def variation(key, user, default)
205
- evaluate_internal(key, user, default, @event_factory_default).value
201
+ evaluate_internal(key, user, default, false).value
206
202
  end
207
203
 
208
204
  #
@@ -229,7 +225,7 @@ module LaunchDarkly
229
225
  # @return [EvaluationDetail] an object describing the result
230
226
  #
231
227
  def variation_detail(key, user, default)
232
- evaluate_internal(key, user, default, @event_factory_with_reasons)
228
+ evaluate_internal(key, user, default, true)
233
229
  end
234
230
 
235
231
  #
@@ -248,12 +244,12 @@ module LaunchDarkly
248
244
  # @return [void]
249
245
  #
250
246
  def identify(user)
251
- if !user || user[:key].nil?
252
- @config.logger.warn("Identify called with nil user or nil user key!")
247
+ if !user || user[:key].nil? || user[:key].empty?
248
+ @config.logger.warn("Identify called with nil user or empty user key!")
253
249
  return
254
250
  end
255
251
  sanitize_user(user)
256
- @event_processor.add_event(@event_factory_default.new_identify_event(user))
252
+ @event_processor.record_identify_event(user)
257
253
  end
258
254
 
259
255
  #
@@ -284,7 +280,7 @@ module LaunchDarkly
284
280
  return
285
281
  end
286
282
  sanitize_user(user)
287
- @event_processor.add_event(@event_factory_default.new_custom_event(event_name, user, data, metric_value))
283
+ @event_processor.record_custom_event(user, event_name, data, metric_value)
288
284
  end
289
285
 
290
286
  #
@@ -301,7 +297,7 @@ module LaunchDarkly
301
297
  end
302
298
  sanitize_user(current_context)
303
299
  sanitize_user(previous_context)
304
- @event_processor.add_event(@event_factory_default.new_alias_event(current_context, previous_context))
300
+ @event_processor.record_alias_event(current_context, previous_context)
305
301
  end
306
302
 
307
303
  #
@@ -338,6 +334,15 @@ module LaunchDarkly
338
334
  def all_flags_state(user, options={})
339
335
  return FeatureFlagsState.new(false) if @config.offline?
340
336
 
337
+ if !initialized?
338
+ if @store.initialized?
339
+ @config.logger.warn { "Called all_flags_state before client initialization; using last known values from data store" }
340
+ else
341
+ @config.logger.warn { "Called all_flags_state before client initialization. Data store not available; returning empty state" }
342
+ return FeatureFlagsState.new(false)
343
+ end
344
+ end
345
+
341
346
  unless user && !user[:key].nil?
342
347
  @config.logger.error { "[LDClient] User and user key must be specified in all_flags_state" }
343
348
  return FeatureFlagsState.new(false)
@@ -359,14 +364,25 @@ module LaunchDarkly
359
364
  next
360
365
  end
361
366
  begin
362
- result = @evaluator.evaluate(f, user, @event_factory_default)
363
- state.add_flag(f, result.detail.value, result.detail.variation_index, with_reasons ? result.detail.reason : nil,
364
- details_only_if_tracked)
367
+ detail = @evaluator.evaluate(f, user).detail
365
368
  rescue => exn
369
+ detail = EvaluationDetail.new(nil, nil, EvaluationReason::error(EvaluationReason::ERROR_EXCEPTION))
366
370
  Util.log_exception(@config.logger, "Error evaluating flag \"#{k}\" in all_flags_state", exn)
367
- state.add_flag(f, nil, nil, with_reasons ? EvaluationReason::error(EvaluationReason::ERROR_EXCEPTION) : nil,
368
- details_only_if_tracked)
369
371
  end
372
+
373
+ requires_experiment_data = is_experiment(f, detail.reason)
374
+ flag_state = {
375
+ key: f[:key],
376
+ value: detail.value,
377
+ variation: detail.variation_index,
378
+ reason: detail.reason,
379
+ version: f[:version],
380
+ trackEvents: f[:trackEvents] || requires_experiment_data,
381
+ trackReason: requires_experiment_data,
382
+ debugEventsUntilDate: f[:debugEventsUntilDate],
383
+ }
384
+
385
+ state.add_flag(flag_state, with_reasons, details_only_if_tracked)
370
386
  end
371
387
 
372
388
  state
@@ -410,7 +426,7 @@ module LaunchDarkly
410
426
  end
411
427
 
412
428
  # @return [EvaluationDetail]
413
- def evaluate_internal(key, user, default, event_factory)
429
+ def evaluate_internal(key, user, default, with_reasons)
414
430
  if @config.offline?
415
431
  return Evaluator.error_result(EvaluationReason::ERROR_CLIENT_NOT_READY, default)
416
432
  end
@@ -433,7 +449,7 @@ module LaunchDarkly
433
449
  else
434
450
  @config.logger.error { "[LDClient] Client has not finished initializing; feature store unavailable, returning default value" }
435
451
  detail = Evaluator.error_result(EvaluationReason::ERROR_CLIENT_NOT_READY, default)
436
- @event_processor.add_event(event_factory.new_unknown_flag_event(key, user, default, detail.reason))
452
+ record_unknown_flag_eval(key, user, default, detail.reason, with_reasons)
437
453
  return detail
438
454
  end
439
455
  end
@@ -443,32 +459,94 @@ module LaunchDarkly
443
459
  if feature.nil?
444
460
  @config.logger.info { "[LDClient] Unknown feature flag \"#{key}\". Returning default value" }
445
461
  detail = Evaluator.error_result(EvaluationReason::ERROR_FLAG_NOT_FOUND, default)
446
- @event_processor.add_event(event_factory.new_unknown_flag_event(key, user, default, detail.reason))
462
+ record_unknown_flag_eval(key, user, default, detail.reason, with_reasons)
447
463
  return detail
448
464
  end
449
465
 
450
466
  begin
451
- res = @evaluator.evaluate(feature, user, event_factory)
452
- if !res.events.nil?
453
- res.events.each do |event|
454
- @event_processor.add_event(event)
467
+ res = @evaluator.evaluate(feature, user)
468
+ if !res.prereq_evals.nil?
469
+ res.prereq_evals.each do |prereq_eval|
470
+ record_prereq_flag_eval(prereq_eval.prereq_flag, prereq_eval.prereq_of_flag, user, prereq_eval.detail, with_reasons)
455
471
  end
456
472
  end
457
473
  detail = res.detail
458
474
  if detail.default_value?
459
475
  detail = EvaluationDetail.new(default, nil, detail.reason)
460
476
  end
461
- @event_processor.add_event(event_factory.new_eval_event(feature, user, detail, default))
477
+ record_flag_eval(feature, user, detail, default, with_reasons)
462
478
  return detail
463
479
  rescue => exn
464
480
  Util.log_exception(@config.logger, "Error evaluating feature flag \"#{key}\"", exn)
465
481
  detail = Evaluator.error_result(EvaluationReason::ERROR_EXCEPTION, default)
466
- @event_processor.add_event(event_factory.new_default_event(feature, user, default, detail.reason))
482
+ record_flag_eval_error(feature, user, default, detail.reason, with_reasons)
467
483
  return detail
468
484
  end
469
485
  end
470
486
 
471
- def sanitize_user(user)
487
+ private def record_flag_eval(flag, user, detail, default, with_reasons)
488
+ add_experiment_data = is_experiment(flag, detail.reason)
489
+ @event_processor.record_eval_event(
490
+ user,
491
+ flag[:key],
492
+ flag[:version],
493
+ detail.variation_index,
494
+ detail.value,
495
+ (add_experiment_data || with_reasons) ? detail.reason : nil,
496
+ default,
497
+ add_experiment_data || flag[:trackEvents] || false,
498
+ flag[:debugEventsUntilDate],
499
+ nil
500
+ )
501
+ end
502
+
503
+ private def record_prereq_flag_eval(prereq_flag, prereq_of_flag, user, detail, with_reasons)
504
+ add_experiment_data = is_experiment(prereq_flag, detail.reason)
505
+ @event_processor.record_eval_event(
506
+ user,
507
+ prereq_flag[:key],
508
+ prereq_flag[:version],
509
+ detail.variation_index,
510
+ detail.value,
511
+ (add_experiment_data || with_reasons) ? detail.reason : nil,
512
+ nil,
513
+ add_experiment_data || prereq_flag[:trackEvents] || false,
514
+ prereq_flag[:debugEventsUntilDate],
515
+ prereq_of_flag[:key]
516
+ )
517
+ end
518
+
519
+ private def record_flag_eval_error(flag, user, default, reason, with_reasons)
520
+ @event_processor.record_eval_event(user, flag[:key], flag[:version], nil, default, with_reasons ? reason : nil, default,
521
+ flag[:trackEvents], flag[:debugEventsUntilDate], nil)
522
+ end
523
+
524
+ private def record_unknown_flag_eval(flag_key, user, default, reason, with_reasons)
525
+ @event_processor.record_eval_event(user, flag_key, nil, nil, default, with_reasons ? reason : nil, default,
526
+ false, nil, nil)
527
+ end
528
+
529
+ private def is_experiment(flag, reason)
530
+ return false if !reason
531
+
532
+ if reason.in_experiment
533
+ return true
534
+ end
535
+
536
+ case reason[:kind]
537
+ when 'RULE_MATCH'
538
+ index = reason[:ruleIndex]
539
+ if !index.nil?
540
+ rules = flag[:rules] || []
541
+ return index >= 0 && index < rules.length && rules[index][:trackEvents]
542
+ end
543
+ when 'FALLTHROUGH'
544
+ return !!flag[:trackEventsFallthrough]
545
+ end
546
+ false
547
+ end
548
+
549
+ private def sanitize_user(user)
472
550
  if user[:key]
473
551
  user[:key] = user[:key].to_s
474
552
  end
@@ -47,7 +47,8 @@ module LaunchDarkly
47
47
  headers: headers,
48
48
  read_timeout: READ_TIMEOUT_SECONDS,
49
49
  logger: @config.logger,
50
- socket_factory: @config.socket_factory
50
+ socket_factory: @config.socket_factory,
51
+ reconnect_time: @config.initial_reconnect_delay
51
52
  }
52
53
  log_connection_started
53
54
  @es = SSE::Client.new(@config.stream_uri + "/all", **opts) do |conn|
@@ -24,6 +24,15 @@ module LaunchDarkly
24
24
  if config.socket_factory
25
25
  http_client_options["socket_class"] = config.socket_factory
26
26
  end
27
+ proxy = URI.parse(uri_s).find_proxy
28
+ if !proxy.nil?
29
+ http_client_options["proxy"] = {
30
+ proxy_address: proxy.host,
31
+ proxy_port: proxy.port,
32
+ proxy_username: proxy.user,
33
+ proxy_password: proxy.password
34
+ }
35
+ end
27
36
  return HTTP::Client.new(http_client_options)
28
37
  .timeout({
29
38
  read: config.read_timeout,
@@ -1,3 +1,3 @@
1
1
  module LaunchDarkly
2
- VERSION = "6.3.1"
2
+ VERSION = "6.3.4"
3
3
  end
data/lib/ldclient-rb.rb CHANGED
@@ -21,7 +21,6 @@ require "ldclient-rb/polling"
21
21
  require "ldclient-rb/user_filter"
22
22
  require "ldclient-rb/simple_lru_cache"
23
23
  require "ldclient-rb/non_blocking_thread_pool"
24
- require "ldclient-rb/event_summarizer"
25
24
  require "ldclient-rb/events"
26
25
  require "ldclient-rb/requestor"
27
26
  require "ldclient-rb/file_data_source"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: launchdarkly-server-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.3.1
4
+ version: 6.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - LaunchDarkly
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-31 00:00:00.000000000 Z
11
+ date: 2022-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-dynamodb
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 2.2.10
33
+ version: 2.2.33
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 2.2.10
40
+ version: 2.2.33
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -198,14 +198,14 @@ dependencies:
198
198
  requirements:
199
199
  - - '='
200
200
  - !ruby/object:Gem::Version
201
- version: 2.2.0
201
+ version: 2.2.1
202
202
  type: :runtime
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - '='
207
207
  - !ruby/object:Gem::Version
208
- version: 2.2.0
208
+ version: 2.2.1
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: json
211
211
  requirement: !ruby/object:Gem::Requirement
@@ -254,7 +254,6 @@ files:
254
254
  - lib/ldclient-rb/cache_store.rb
255
255
  - lib/ldclient-rb/config.rb
256
256
  - lib/ldclient-rb/evaluation_detail.rb
257
- - lib/ldclient-rb/event_summarizer.rb
258
257
  - lib/ldclient-rb/events.rb
259
258
  - lib/ldclient-rb/expiring_cache.rb
260
259
  - lib/ldclient-rb/file_data_source.rb
@@ -265,8 +264,9 @@ files:
265
264
  - lib/ldclient-rb/impl/evaluator.rb
266
265
  - lib/ldclient-rb/impl/evaluator_bucketing.rb
267
266
  - lib/ldclient-rb/impl/evaluator_operators.rb
268
- - lib/ldclient-rb/impl/event_factory.rb
269
267
  - lib/ldclient-rb/impl/event_sender.rb
268
+ - lib/ldclient-rb/impl/event_summarizer.rb
269
+ - lib/ldclient-rb/impl/event_types.rb
270
270
  - lib/ldclient-rb/impl/integrations/consul_impl.rb
271
271
  - lib/ldclient-rb/impl/integrations/dynamodb_impl.rb
272
272
  - lib/ldclient-rb/impl/integrations/file_data_source.rb
@@ -319,7 +319,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
319
319
  - !ruby/object:Gem::Version
320
320
  version: '0'
321
321
  requirements: []
322
- rubygems_version: 3.3.4
322
+ rubygems_version: 3.3.17
323
323
  signing_key:
324
324
  specification_version: 4
325
325
  summary: LaunchDarkly SDK for Ruby
@@ -1,55 +0,0 @@
1
-
2
- module LaunchDarkly
3
- # @private
4
- EventSummary = Struct.new(:start_date, :end_date, :counters)
5
-
6
- # Manages the state of summarizable information for the EventProcessor, including the
7
- # event counters and user deduplication. Note that the methods of this class are
8
- # deliberately not thread-safe; the EventProcessor is responsible for enforcing
9
- # synchronization across both the summarizer and the event queue.
10
- #
11
- # @private
12
- class EventSummarizer
13
- def initialize
14
- clear
15
- end
16
-
17
- # Adds this event to our counters, if it is a type of event we need to count.
18
- def summarize_event(event)
19
- if event[:kind] == "feature"
20
- counter_key = {
21
- key: event[:key],
22
- version: event[:version],
23
- variation: event[:variation]
24
- }
25
- c = @counters[counter_key]
26
- if c.nil?
27
- @counters[counter_key] = {
28
- value: event[:value],
29
- default: event[:default],
30
- count: 1
31
- }
32
- else
33
- c[:count] = c[:count] + 1
34
- end
35
- time = event[:creationDate]
36
- if !time.nil?
37
- @start_date = time if @start_date == 0 || time < @start_date
38
- @end_date = time if time > @end_date
39
- end
40
- end
41
- end
42
-
43
- # Returns a snapshot of the current summarized event data, and resets this state.
44
- def snapshot
45
- ret = EventSummary.new(@start_date, @end_date, @counters)
46
- ret
47
- end
48
-
49
- def clear
50
- @start_date = 0
51
- @end_date = 0
52
- @counters = {}
53
- end
54
- end
55
- end