launchdarkly-server-sdk 6.3.1 → 6.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: d21f900f036d19f8b33271d825f3c00cda01d0ac44caf875774a196950ce2479
4
- data.tar.gz: f409fa9e445a0387ef96256d6a8cc57320ebe354cc07cc9f1f78897eff5fc82f
3
+ metadata.gz: 147fe8142bffa0d8e754e86669f524f6d787930e8bc6b8a14d30429933a036e3
4
+ data.tar.gz: e4a404cb7bc911f7c156c3fe5059ee9a4a9d7ebfeacba4c52f44ceb116276835
5
5
  SHA512:
6
- metadata.gz: 21b358fa934cbe2d5c06e9f941ebbfeb785a3d93b2bbe562859fc59af3137b0b5673de8794d1d4a32c33f2e12d212c27451242ef85c9341ac2c0c59b80d5c5d5
7
- data.tar.gz: fef2084a06846e16047d96a784b1d00351d45489baa657a48970a28190ebab67fdcc39a1716138c5b2c7f6d210be97d8289863d6f04c6a36a8bec2b5a8d49389
6
+ metadata.gz: '039348a1a0c9284e79e641b69f11bdc4e8ba57c4cad3320eea6f8bb8caf8fc0f52a02c427a2b4f26584945e5750b7728706855cfaf6bdc22a1863b55bcf934a6'
7
+ data.tar.gz: 452c574e6ff6323a74dfdcf6a5c936ff38bfaa0efc3b58ff190068322ea82e25b15dc20868eb22bf93361d3daa699bd51fa362e97f30f4fc6bcf402f9f5597d9
data/README.md CHANGED
@@ -3,8 +3,7 @@ LaunchDarkly Server-side SDK for Ruby
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/launchdarkly-server-sdk.svg)](http://badge.fury.io/rb/launchdarkly-server-sdk)
5
5
 
6
- [![Circle CI](https://circleci.com/gh/launchdarkly/ruby-server-sdk/tree/master.svg?style=svg)](https://circleci.com/gh/launchdarkly/ruby-server-sdk/tree/master)
7
- [![Security](https://hakiri.io/github/launchdarkly/ruby-server-sdk/master.svg)](https://hakiri.io/github/launchdarkly/ruby-server-sdk/master)
6
+ [![Circle CI](https://circleci.com/gh/launchdarkly/ruby-server-sdk/tree/main.svg?style=svg)](https://circleci.com/gh/launchdarkly/ruby-server-sdk/tree/main)
8
7
  [![RubyDoc](https://img.shields.io/static/v1?label=docs+-+all+versions&message=reference&color=00add8)](https://www.rubydoc.info/gems/launchdarkly-server-sdk)
9
8
  [![GitHub Pages](https://img.shields.io/static/v1?label=docs+-+latest&message=reference&color=00add8)](https://launchdarkly.github.io/ruby-server-sdk)
10
9
 
@@ -21,6 +21,7 @@ module LaunchDarkly
21
21
  # @option opts [Integer] :capacity (10000) See {#capacity}.
22
22
  # @option opts [Float] :flush_interval (30) See {#flush_interval}.
23
23
  # @option opts [Float] :read_timeout (10) See {#read_timeout}.
24
+ # @option opts [Float] :initial_reconnect_delay (1) See {#initial_reconnect_delay}.
24
25
  # @option opts [Float] :connect_timeout (2) See {#connect_timeout}.
25
26
  # @option opts [Object] :cache_store See {#cache_store}.
26
27
  # @option opts [Object] :feature_store See {#feature_store}.
@@ -43,6 +44,7 @@ module LaunchDarkly
43
44
  # @option opts [String] :wrapper_version See {#wrapper_version}.
44
45
  # @option opts [#open] :socket_factory See {#socket_factory}.
45
46
  # @option opts [BigSegmentsConfig] :big_segments See {#big_segments}.
47
+ # @option opts [Hash] :application See {#application}
46
48
  #
47
49
  def initialize(opts = {})
48
50
  @base_uri = (opts[:base_uri] || Config.default_base_uri).chomp("/")
@@ -54,6 +56,7 @@ module LaunchDarkly
54
56
  @flush_interval = opts[:flush_interval] || Config.default_flush_interval
55
57
  @connect_timeout = opts[:connect_timeout] || Config.default_connect_timeout
56
58
  @read_timeout = opts[:read_timeout] || Config.default_read_timeout
59
+ @initial_reconnect_delay = opts[:initial_reconnect_delay] || Config.default_initial_reconnect_delay
57
60
  @feature_store = opts[:feature_store] || Config.default_feature_store
58
61
  @stream = opts.has_key?(:stream) ? opts[:stream] : Config.default_stream
59
62
  @use_ldd = opts.has_key?(:use_ldd) ? opts[:use_ldd] : Config.default_use_ldd
@@ -75,6 +78,7 @@ module LaunchDarkly
75
78
  @wrapper_version = opts[:wrapper_version]
76
79
  @socket_factory = opts[:socket_factory]
77
80
  @big_segments = opts[:big_segments] || BigSegmentsConfig.new(store: nil)
81
+ @application = LaunchDarkly::Impl::Util.validate_application_info(opts[:application] || {}, @logger)
78
82
  end
79
83
 
80
84
  #
@@ -180,6 +184,13 @@ module LaunchDarkly
180
184
  #
181
185
  attr_reader :read_timeout
182
186
 
187
+ #
188
+ # The initial delay before reconnecting after an error in the SSE client.
189
+ # This only applies to the streaming connection.
190
+ # @return [Float]
191
+ #
192
+ attr_reader :initial_reconnect_delay
193
+
183
194
  #
184
195
  # The connect timeout for network connections in seconds.
185
196
  # @return [Float]
@@ -275,6 +286,24 @@ module LaunchDarkly
275
286
  #
276
287
  attr_reader :big_segments
277
288
 
289
+ #
290
+ # An object that allows configuration of application metadata.
291
+ #
292
+ # Application metadata may be used in LaunchDarkly analytics or other product features, but does not affect feature flag evaluations.
293
+ #
294
+ # If you want to set non-default values for any of these fields, provide the appropriately configured hash to the {Config} object.
295
+ #
296
+ # @example Configuring application information
297
+ # opts[:application] = {
298
+ # id: "MY APPLICATION ID",
299
+ # version: "MY APPLICATION VERSION"
300
+ # }
301
+ # config = LDConfig.new(opts)
302
+ #
303
+ # @return [Hash]
304
+ #
305
+ attr_reader :application
306
+
278
307
  # @deprecated This is replaced by {#data_source}.
279
308
  attr_reader :update_processor
280
309
 
@@ -395,6 +424,14 @@ module LaunchDarkly
395
424
  10
396
425
  end
397
426
 
427
+ #
428
+ # The default value for {#initial_reconnect_delay}.
429
+ # @return [Float] 1
430
+ #
431
+ def self.default_initial_reconnect_delay
432
+ 1
433
+ end
434
+
398
435
  #
399
436
  # The default value for {#connect_timeout}.
400
437
  # @return [Float] 10
@@ -1,5 +1,7 @@
1
1
  require "ldclient-rb/impl/diagnostic_events"
2
2
  require "ldclient-rb/impl/event_sender"
3
+ require "ldclient-rb/impl/event_summarizer"
4
+ require "ldclient-rb/impl/event_types"
3
5
  require "ldclient-rb/impl/util"
4
6
 
5
7
  require "concurrent"
@@ -26,16 +28,33 @@ require "time"
26
28
  #
27
29
 
28
30
  module LaunchDarkly
29
- MAX_FLUSH_WORKERS = 5
30
- USER_ATTRS_TO_STRINGIFY_FOR_EVENTS = [ :key, :secondary, :ip, :country, :email, :firstName, :lastName,
31
- :avatar, :name ]
31
+ module EventProcessorMethods
32
+ def record_eval_event(
33
+ user,
34
+ key,
35
+ version = nil,
36
+ variation = nil,
37
+ value = nil,
38
+ reason = nil,
39
+ default = nil,
40
+ track_events = false,
41
+ debug_until = nil,
42
+ prereq_of = nil
43
+ )
44
+ end
32
45
 
33
- private_constant :MAX_FLUSH_WORKERS
34
- private_constant :USER_ATTRS_TO_STRINGIFY_FOR_EVENTS
46
+ def record_identify_event(user)
47
+ end
35
48
 
36
- # @private
37
- class NullEventProcessor
38
- def add_event(event)
49
+ def record_custom_event(
50
+ user,
51
+ key,
52
+ data = nil,
53
+ metric_value = nil
54
+ )
55
+ end
56
+
57
+ def record_alias_event(user, previous_user)
39
58
  end
40
59
 
41
60
  def flush
@@ -45,12 +64,16 @@ module LaunchDarkly
45
64
  end
46
65
  end
47
66
 
67
+ MAX_FLUSH_WORKERS = 5
68
+ USER_ATTRS_TO_STRINGIFY_FOR_EVENTS = [ :key, :secondary, :ip, :country, :email, :firstName, :lastName,
69
+ :avatar, :name ]
70
+
71
+ private_constant :MAX_FLUSH_WORKERS
72
+ private_constant :USER_ATTRS_TO_STRINGIFY_FOR_EVENTS
73
+
48
74
  # @private
49
- class EventMessage
50
- def initialize(event)
51
- @event = event
52
- end
53
- attr_reader :event
75
+ class NullEventProcessor
76
+ include EventProcessorMethods
54
77
  end
55
78
 
56
79
  # @private
@@ -90,6 +113,8 @@ module LaunchDarkly
90
113
 
91
114
  # @private
92
115
  class EventProcessor
116
+ include EventProcessorMethods
117
+
93
118
  def initialize(sdk_key, config, client = nil, diagnostic_accumulator = nil, test_properties = nil)
94
119
  raise ArgumentError, "sdk_key must not be nil" if sdk_key.nil? # see LDClient constructor comment on sdk_key
95
120
  @logger = config.logger
@@ -116,16 +141,46 @@ module LaunchDarkly
116
141
  @stopped = Concurrent::AtomicBoolean.new(false)
117
142
  @inbox_full = Concurrent::AtomicBoolean.new(false)
118
143
 
119
- event_sender = test_properties && test_properties.has_key?(:event_sender) ?
120
- test_properties[:event_sender] :
144
+ event_sender = (test_properties || {})[:event_sender] ||
121
145
  Impl::EventSender.new(sdk_key, config, client ? client : Util.new_http_client(config.events_uri, config))
122
146
 
147
+ @timestamp_fn = (test_properties || {})[:timestamp_fn] || proc { Impl::Util.current_time_millis }
148
+
123
149
  EventDispatcher.new(@inbox, sdk_key, config, diagnostic_accumulator, event_sender)
124
150
  end
125
151
 
126
- def add_event(event)
127
- event[:creationDate] = Impl::Util.current_time_millis
128
- post_to_inbox(EventMessage.new(event))
152
+ def record_eval_event(
153
+ user,
154
+ key,
155
+ version = nil,
156
+ variation = nil,
157
+ value = nil,
158
+ reason = nil,
159
+ default = nil,
160
+ track_events = false,
161
+ debug_until = nil,
162
+ prereq_of = nil
163
+ )
164
+ post_to_inbox(LaunchDarkly::Impl::EvalEvent.new(timestamp, user, key, version, variation, value, reason,
165
+ default, track_events, debug_until, prereq_of))
166
+ end
167
+
168
+ def record_identify_event(user)
169
+ post_to_inbox(LaunchDarkly::Impl::IdentifyEvent.new(timestamp, user))
170
+ end
171
+
172
+ def record_custom_event(user, key, data = nil, metric_value = nil)
173
+ post_to_inbox(LaunchDarkly::Impl::CustomEvent.new(timestamp, user, key, data, metric_value))
174
+ end
175
+
176
+ def record_alias_event(user, previous_user)
177
+ post_to_inbox(LaunchDarkly::Impl::AliasEvent.new(
178
+ timestamp,
179
+ user.nil? ? nil : user[:key],
180
+ user_to_context_kind(user),
181
+ previous_user.nil? ? nil : previous_user[:key],
182
+ user_to_context_kind(previous_user)
183
+ ))
129
184
  end
130
185
 
131
186
  def flush
@@ -155,9 +210,11 @@ module LaunchDarkly
155
210
  sync_msg.wait_for_completion
156
211
  end
157
212
 
158
- private
213
+ private def timestamp
214
+ @timestamp_fn.call()
215
+ end
159
216
 
160
- def post_to_inbox(message)
217
+ private def post_to_inbox(message)
161
218
  begin
162
219
  @inbox.push(message, non_block=true)
163
220
  rescue ThreadError
@@ -170,6 +227,10 @@ module LaunchDarkly
170
227
  end
171
228
  end
172
229
  end
230
+
231
+ private def user_to_context_kind(user)
232
+ (user.nil? || !user[:anonymous]) ? 'user' : 'anonymousUser'
233
+ end
173
234
  end
174
235
 
175
236
  # @private
@@ -209,8 +270,6 @@ module LaunchDarkly
209
270
  begin
210
271
  message = inbox.pop
211
272
  case message
212
- when EventMessage
213
- dispatch_event(message.event, outbox)
214
273
  when FlushMessage
215
274
  trigger_flush(outbox, flush_workers)
216
275
  when FlushUsersMessage
@@ -224,6 +283,8 @@ module LaunchDarkly
224
283
  do_shutdown(flush_workers, diagnostic_event_workers)
225
284
  running = false
226
285
  message.completed
286
+ else
287
+ dispatch_event(message, outbox)
227
288
  end
228
289
  rescue => e
229
290
  Util.log_exception(@config.logger, "Unexpected error in event processor", e)
@@ -257,11 +318,10 @@ module LaunchDarkly
257
318
  # the event (if tracked) and once for debugging.
258
319
  will_add_full_event = false
259
320
  debug_event = nil
260
- if event[:kind] == "feature"
261
- will_add_full_event = event[:trackEvents]
321
+ if event.is_a?(LaunchDarkly::Impl::EvalEvent)
322
+ will_add_full_event = event.track_events
262
323
  if should_debug_event(event)
263
- debug_event = event.clone
264
- debug_event[:debug] = true
324
+ debug_event = LaunchDarkly::Impl::DebugEvent.new(event)
265
325
  end
266
326
  else
267
327
  will_add_full_event = true
@@ -270,12 +330,8 @@ module LaunchDarkly
270
330
  # For each user we haven't seen before, we add an index event - unless this is already
271
331
  # an identify event for that user.
272
332
  if !(will_add_full_event && @config.inline_users_in_events)
273
- if event.has_key?(:user) && !notice_user(event[:user]) && event[:kind] != "identify"
274
- outbox.add_event({
275
- kind: "index",
276
- creationDate: event[:creationDate],
277
- user: event[:user]
278
- })
333
+ if !event.user.nil? && !notice_user(event.user) && !event.is_a?(LaunchDarkly::Impl::IdentifyEvent)
334
+ outbox.add_event(LaunchDarkly::Impl::IndexEvent.new(event.timestamp, event.user))
279
335
  end
280
336
  end
281
337
 
@@ -295,7 +351,7 @@ module LaunchDarkly
295
351
  end
296
352
 
297
353
  def should_debug_event(event)
298
- debug_until = event[:debugEventsUntilDate]
354
+ debug_until = event.debug_until
299
355
  if !debug_until.nil?
300
356
  last_past = @last_known_past_time.value
301
357
  debug_until > last_past && debug_until > Impl::Util.current_time_millis
@@ -365,12 +421,11 @@ module LaunchDarkly
365
421
  @capacity_exceeded = false
366
422
  @dropped_events = 0
367
423
  @events = []
368
- @summarizer = EventSummarizer.new
424
+ @summarizer = LaunchDarkly::Impl::EventSummarizer.new
369
425
  end
370
426
 
371
427
  def add_event(event)
372
428
  if @events.length < @capacity
373
- @logger.debug { "[LDClient] Enqueueing event: #{event.to_json}" }
374
429
  @events.push(event)
375
430
  @capacity_exceeded = false
376
431
  else
@@ -404,6 +459,15 @@ module LaunchDarkly
404
459
 
405
460
  # @private
406
461
  class EventOutputFormatter
462
+ FEATURE_KIND = 'feature'
463
+ IDENTIFY_KIND = 'identify'
464
+ CUSTOM_KIND = 'custom'
465
+ ALIAS_KIND = 'alias'
466
+ INDEX_KIND = 'index'
467
+ DEBUG_KIND = 'debug'
468
+ SUMMARY_KIND = 'summary'
469
+ ANONYMOUS_USER_CONTEXT_KIND = 'anonymousUser'
470
+
407
471
  def initialize(config)
408
472
  @inline_users = config.inline_users_in_events
409
473
  @user_filter = UserFilter.new(config)
@@ -418,100 +482,130 @@ module LaunchDarkly
418
482
  events_out
419
483
  end
420
484
 
421
- private
422
-
423
- def process_user(event)
424
- filtered = @user_filter.transform_user_props(event[:user])
425
- Util.stringify_attrs(filtered, USER_ATTRS_TO_STRINGIFY_FOR_EVENTS)
426
- end
427
-
428
- def make_output_event(event)
429
- case event[:kind]
430
- when "feature"
431
- is_debug = event[:debug]
485
+ private def make_output_event(event)
486
+ case event
487
+
488
+ when LaunchDarkly::Impl::EvalEvent
432
489
  out = {
433
- kind: is_debug ? "debug" : "feature",
434
- creationDate: event[:creationDate],
435
- key: event[:key],
436
- value: event[:value]
490
+ kind: FEATURE_KIND,
491
+ creationDate: event.timestamp,
492
+ key: event.key,
493
+ value: event.value
437
494
  }
438
- out[:default] = event[:default] if event.has_key?(:default)
439
- out[:variation] = event[:variation] if event.has_key?(:variation)
440
- out[:version] = event[:version] if event.has_key?(:version)
441
- out[:prereqOf] = event[:prereqOf] if event.has_key?(:prereqOf)
442
- out[:contextKind] = event[:contextKind] if event.has_key?(:contextKind)
443
- if @inline_users || is_debug
444
- out[:user] = process_user(event)
445
- else
446
- out[:userKey] = event[:user][:key]
447
- end
448
- out[:reason] = event[:reason] if !event[:reason].nil?
495
+ out[:default] = event.default if !event.default.nil?
496
+ out[:variation] = event.variation if !event.variation.nil?
497
+ out[:version] = event.version if !event.version.nil?
498
+ out[:prereqOf] = event.prereq_of if !event.prereq_of.nil?
499
+ set_opt_context_kind(out, event.user)
500
+ set_user_or_user_key(out, event.user)
501
+ out[:reason] = event.reason if !event.reason.nil?
449
502
  out
450
- when "identify"
503
+
504
+ when LaunchDarkly::Impl::IdentifyEvent
451
505
  {
452
- kind: "identify",
453
- creationDate: event[:creationDate],
454
- key: event[:user][:key].to_s,
455
- user: process_user(event)
506
+ kind: IDENTIFY_KIND,
507
+ creationDate: event.timestamp,
508
+ key: event.user[:key].to_s,
509
+ user: process_user(event.user)
456
510
  }
457
- when "custom"
511
+
512
+ when LaunchDarkly::Impl::CustomEvent
458
513
  out = {
459
- kind: "custom",
460
- creationDate: event[:creationDate],
461
- key: event[:key]
514
+ kind: CUSTOM_KIND,
515
+ creationDate: event.timestamp,
516
+ key: event.key
462
517
  }
463
- out[:data] = event[:data] if event.has_key?(:data)
464
- if @inline_users
465
- out[:user] = process_user(event)
466
- else
467
- out[:userKey] = event[:user][:key]
468
- end
469
- out[:metricValue] = event[:metricValue] if event.has_key?(:metricValue)
470
- out[:contextKind] = event[:contextKind] if event.has_key?(:contextKind)
518
+ out[:data] = event.data if !event.data.nil?
519
+ set_user_or_user_key(out, event.user)
520
+ out[:metricValue] = event.metric_value if !event.metric_value.nil?
521
+ set_opt_context_kind(out, event.user)
471
522
  out
472
- when "index"
523
+
524
+ when LaunchDarkly::Impl::AliasEvent
525
+ {
526
+ kind: ALIAS_KIND,
527
+ creationDate: event.timestamp,
528
+ key: event.key,
529
+ contextKind: event.context_kind,
530
+ previousKey: event.previous_key,
531
+ previousContextKind: event.previous_context_kind
532
+ }
533
+
534
+ when LaunchDarkly::Impl::IndexEvent
473
535
  {
474
- kind: "index",
475
- creationDate: event[:creationDate],
476
- user: process_user(event)
536
+ kind: INDEX_KIND,
537
+ creationDate: event.timestamp,
538
+ user: process_user(event.user)
477
539
  }
540
+
541
+ when LaunchDarkly::Impl::DebugEvent
542
+ original = event.eval_event
543
+ out = {
544
+ kind: DEBUG_KIND,
545
+ creationDate: original.timestamp,
546
+ key: original.key,
547
+ user: process_user(original.user),
548
+ value: original.value
549
+ }
550
+ out[:default] = original.default if !original.default.nil?
551
+ out[:variation] = original.variation if !original.variation.nil?
552
+ out[:version] = original.version if !original.version.nil?
553
+ out[:prereqOf] = original.prereq_of if !original.prereq_of.nil?
554
+ set_opt_context_kind(out, original.user)
555
+ out[:reason] = original.reason if !original.reason.nil?
556
+ out
557
+
478
558
  else
479
- event
559
+ nil
480
560
  end
481
561
  end
482
562
 
483
563
  # Transforms the summary data into the format used for event sending.
484
- def make_summary_event(summary)
564
+ private def make_summary_event(summary)
485
565
  flags = {}
486
- summary[:counters].each { |ckey, cval|
487
- flag = flags[ckey[:key]]
488
- if flag.nil?
489
- flag = {
490
- default: cval[:default],
491
- counters: []
492
- }
493
- flags[ckey[:key]] = flag
494
- end
495
- c = {
496
- value: cval[:value],
497
- count: cval[:count]
498
- }
499
- if !ckey[:variation].nil?
500
- c[:variation] = ckey[:variation]
501
- end
502
- if ckey[:version].nil?
503
- c[:unknown] = true
504
- else
505
- c[:version] = ckey[:version]
566
+ summary.counters.each do |flagKey, flagInfo|
567
+ counters = []
568
+ flagInfo.versions.each do |version, variations|
569
+ variations.each do |variation, counter|
570
+ c = {
571
+ value: counter.value,
572
+ count: counter.count
573
+ }
574
+ c[:variation] = variation if !variation.nil?
575
+ if version.nil?
576
+ c[:unknown] = true
577
+ else
578
+ c[:version] = version
579
+ end
580
+ counters.push(c)
581
+ end
506
582
  end
507
- flag[:counters].push(c)
508
- }
583
+ flags[flagKey] = { default: flagInfo.default, counters: counters }
584
+ end
509
585
  {
510
- kind: "summary",
586
+ kind: SUMMARY_KIND,
511
587
  startDate: summary[:start_date],
512
588
  endDate: summary[:end_date],
513
589
  features: flags
514
590
  }
515
591
  end
592
+
593
+ private def set_opt_context_kind(out, user)
594
+ out[:contextKind] = ANONYMOUS_USER_CONTEXT_KIND if !user.nil? && user[:anonymous]
595
+ end
596
+
597
+ private def set_user_or_user_key(out, user)
598
+ if @inline_users
599
+ out[:user] = process_user(user)
600
+ else
601
+ key = user[:key]
602
+ out[:userKey] = key.is_a?(String) ? key : key.to_s
603
+ end
604
+ end
605
+
606
+ private def process_user(user)
607
+ filtered = @user_filter.transform_user_props(user)
608
+ Util.stringify_attrs(filtered, USER_ATTRS_TO_STRINGIFY_FOR_EVENTS)
609
+ end
516
610
  end
517
611
  end
@@ -16,21 +16,32 @@ module LaunchDarkly
16
16
 
17
17
  # Used internally to build the state map.
18
18
  # @private
19
- def add_flag(flag, value, variation, reason = nil, details_only_if_tracked = false)
20
- key = flag[:key]
21
- @flag_values[key] = value
19
+ def add_flag(flag_state, with_reasons, details_only_if_tracked)
20
+ key = flag_state[:key]
21
+ @flag_values[key] = flag_state[:value]
22
22
  meta = {}
23
- with_details = !details_only_if_tracked || flag[:trackEvents]
24
- if !with_details && flag[:debugEventsUntilDate]
25
- with_details = flag[:debugEventsUntilDate] > Impl::Util::current_time_millis
23
+
24
+ omit_details = false
25
+ if details_only_if_tracked
26
+ if !flag_state[:trackEvents] && !flag_state[:trackReason] && !(flag_state[:debugEventsUntilDate] && flag_state[:debugEventsUntilDate] > Impl::Util::current_time_millis)
27
+ omit_details = true
28
+ end
29
+ end
30
+
31
+ reason = (!with_reasons and !flag_state[:trackReason]) ? nil : flag_state[:reason]
32
+
33
+ if !reason.nil? && !omit_details
34
+ meta[:reason] = reason
26
35
  end
27
- if with_details
28
- meta[:version] = flag[:version]
29
- meta[:reason] = reason if !reason.nil?
36
+
37
+ if !omit_details
38
+ meta[:version] = flag_state[:version]
30
39
  end
31
- meta[:variation] = variation if !variation.nil?
32
- meta[:trackEvents] = true if flag[:trackEvents]
33
- meta[:debugEventsUntilDate] = flag[:debugEventsUntilDate] if flag[:debugEventsUntilDate]
40
+
41
+ meta[:variation] = flag_state[:variation] if !flag_state[:variation].nil?
42
+ meta[:trackEvents] = true if flag_state[:trackEvents]
43
+ meta[:trackReason] = true if flag_state[:trackReason]
44
+ meta[:debugEventsUntilDate] = flag_state[:debugEventsUntilDate] if flag_state[:debugEventsUntilDate]
34
45
  @flag_metadata[key] = meta
35
46
  end
36
47