launchdarkly-server-sdk 7.3.2 → 8.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ldclient-rb/config.rb +3 -68
- data/lib/ldclient-rb/context.rb +65 -52
- data/lib/ldclient-rb/evaluation_detail.rb +5 -1
- data/lib/ldclient-rb/events.rb +78 -7
- data/lib/ldclient-rb/impl/big_segments.rb +1 -1
- data/lib/ldclient-rb/impl/context_filter.rb +1 -1
- data/lib/ldclient-rb/impl/event_types.rb +61 -3
- data/lib/ldclient-rb/impl/migrations/migrator.rb +287 -0
- data/lib/ldclient-rb/impl/migrations/tracker.rb +136 -0
- data/lib/ldclient-rb/impl/model/feature_flag.rb +23 -0
- data/lib/ldclient-rb/impl/sampler.rb +25 -0
- data/lib/ldclient-rb/integrations/test_data/flag_builder.rb +84 -15
- data/lib/ldclient-rb/interfaces.rb +97 -0
- data/lib/ldclient-rb/ldclient.rb +106 -16
- data/lib/ldclient-rb/migrations.rb +230 -0
- data/lib/ldclient-rb/reference.rb +11 -0
- data/lib/ldclient-rb/util.rb +63 -0
- data/lib/ldclient-rb/version.rb +1 -1
- data/lib/ldclient-rb.rb +1 -0
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 133fe555993b53f1e53f3348242d1c96ac2318d2c2c1ebf48e33e4d23c6e97f3
|
4
|
+
data.tar.gz: 12f604c2a17d9d06433a1ad041051e41f767efa3c7310a5925553cb5678b5709
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1be2d4708681d7e0a2665e68e878ed8d2e17975f6c28716ed139911b866acb067884b4af872e6f5469177f09b5071f1c8fbb0ac6b7519f581bb20ee11afb76df
|
7
|
+
data.tar.gz: 2d0a5df44d5de21887eb4330f34bf65d4a4bab9a153d7644077790e3262a8b6418c26c4ebe5612523be468d05ddd5a8b837dc22a347c08ef463229c337e040c3
|
data/lib/ldclient-rb/config.rb
CHANGED
@@ -13,18 +13,6 @@ module LaunchDarkly
|
|
13
13
|
#
|
14
14
|
# Constructor for creating custom LaunchDarkly configurations.
|
15
15
|
#
|
16
|
-
# `user_keys_capacity` and `user_keys_flush_interval` are deprecated
|
17
|
-
# configuration options. They exist to maintain backwards compatibility
|
18
|
-
# with previous configurations. Newer code should prefer their replacement
|
19
|
-
# options -- `context_keys_capacity` and `context_keys_flush_interval`.
|
20
|
-
#
|
21
|
-
# In the event both the user and context variations are provided, the
|
22
|
-
# context specific configuration option will take precedence.
|
23
|
-
#
|
24
|
-
# Similarly, `private_attribute_names` is deprecated. Newer code should
|
25
|
-
# prefer `private_attributes`. If both are provided, `private_attributes`
|
26
|
-
# will take precedence.
|
27
|
-
#
|
28
16
|
# @param opts [Hash] the configuration options
|
29
17
|
# @option opts [Logger] :logger See {#logger}.
|
30
18
|
# @option opts [String] :base_uri ("https://sdk.launchdarkly.com") See {#base_uri}.
|
@@ -42,12 +30,9 @@ module LaunchDarkly
|
|
42
30
|
# @option opts [Float] :poll_interval (30) See {#poll_interval}.
|
43
31
|
# @option opts [Boolean] :stream (true) See {#stream?}.
|
44
32
|
# @option opts [Boolean] all_attributes_private (false) See {#all_attributes_private}.
|
45
|
-
# @option opts [Array] :private_attribute_names See {#private_attribute_names}.
|
46
33
|
# @option opts [Array] :private_attributes See {#private_attributes}.
|
47
34
|
# @option opts [Boolean] :send_events (true) See {#send_events}.
|
48
|
-
# @option opts [Integer] :user_keys_capacity (1000) See {#user_keys_capacity}.
|
49
35
|
# @option opts [Integer] :context_keys_capacity (1000) See {#context_keys_capacity}.
|
50
|
-
# @option opts [Float] :user_keys_flush_interval (300) See {#user_keys_flush_interval}.
|
51
36
|
# @option opts [Float] :context_keys_flush_interval (300) See {#context_keys_flush_interval}.
|
52
37
|
# @option opts [Object] :data_source See {#data_source}.
|
53
38
|
# @option opts [Boolean] :diagnostic_opt_out (false) See {#diagnostic_opt_out?}.
|
@@ -76,10 +61,10 @@ module LaunchDarkly
|
|
76
61
|
@offline = opts.has_key?(:offline) ? opts[:offline] : Config.default_offline
|
77
62
|
@poll_interval = opts.has_key?(:poll_interval) && opts[:poll_interval] > Config.default_poll_interval ? opts[:poll_interval] : Config.default_poll_interval
|
78
63
|
@all_attributes_private = opts[:all_attributes_private] || false
|
79
|
-
@private_attributes = opts[:private_attributes] ||
|
64
|
+
@private_attributes = opts[:private_attributes] || []
|
80
65
|
@send_events = opts.has_key?(:send_events) ? opts[:send_events] : Config.default_send_events
|
81
|
-
@context_keys_capacity = opts[:context_keys_capacity] ||
|
82
|
-
@context_keys_flush_interval = opts[:context_keys_flush_interval] ||
|
66
|
+
@context_keys_capacity = opts[:context_keys_capacity] || Config.default_context_keys_capacity
|
67
|
+
@context_keys_flush_interval = opts[:context_keys_flush_interval] || Config.default_context_keys_flush_interval
|
83
68
|
@data_source = opts[:data_source]
|
84
69
|
@diagnostic_opt_out = opts.has_key?(:diagnostic_opt_out) && opts[:diagnostic_opt_out]
|
85
70
|
@diagnostic_recording_interval = opts.has_key?(:diagnostic_recording_interval) && opts[:diagnostic_recording_interval] > Config.minimum_diagnostic_recording_interval ?
|
@@ -258,14 +243,6 @@ module LaunchDarkly
|
|
258
243
|
#
|
259
244
|
attr_reader :private_attributes
|
260
245
|
|
261
|
-
#
|
262
|
-
# @deprecated Backwards compatibility alias for #private_attributes.
|
263
|
-
#
|
264
|
-
# @return [Integer]
|
265
|
-
# @see #private_attributes
|
266
|
-
#
|
267
|
-
alias :private_attribute_names :private_attributes
|
268
|
-
|
269
246
|
#
|
270
247
|
# Whether to send events back to LaunchDarkly. This differs from {#offline?} in that it affects
|
271
248
|
# only the sending of client-side events, not streaming or polling for events from the server.
|
@@ -281,14 +258,6 @@ module LaunchDarkly
|
|
281
258
|
#
|
282
259
|
attr_reader :context_keys_capacity
|
283
260
|
|
284
|
-
#
|
285
|
-
# @deprecated Backwards compatibility alias for #context_keys_capacity.
|
286
|
-
#
|
287
|
-
# @return [Integer]
|
288
|
-
# @see #context_keys_flush_interval
|
289
|
-
#
|
290
|
-
alias :user_keys_capacity :context_keys_capacity
|
291
|
-
|
292
261
|
#
|
293
262
|
# The interval in seconds at which the event processor will reset its set of known context keys.
|
294
263
|
# @return [Float]
|
@@ -296,14 +265,6 @@ module LaunchDarkly
|
|
296
265
|
#
|
297
266
|
attr_reader :context_keys_flush_interval
|
298
267
|
|
299
|
-
#
|
300
|
-
# @deprecated Backwards compatibility alias for #context_keys_flush_interval.
|
301
|
-
#
|
302
|
-
# @return [Integer]
|
303
|
-
# @see #context_keys_flush_interval
|
304
|
-
#
|
305
|
-
alias :user_keys_flush_interval :context_keys_flush_interval
|
306
|
-
|
307
268
|
#
|
308
269
|
# An object that is responsible for receiving feature flag data from LaunchDarkly. By default,
|
309
270
|
# the client uses its standard polling or streaming implementation; this is customizable for
|
@@ -570,18 +531,6 @@ module LaunchDarkly
|
|
570
531
|
300
|
571
532
|
end
|
572
533
|
|
573
|
-
class << self
|
574
|
-
#
|
575
|
-
# @deprecated Backwards compatibility alias for #default_context_keys_capacity
|
576
|
-
#
|
577
|
-
alias :default_user_keys_capacity :default_context_keys_capacity
|
578
|
-
|
579
|
-
#
|
580
|
-
# @deprecated Backwards compatibility alias for #default_context_keys_flush_interval
|
581
|
-
#
|
582
|
-
alias :default_user_keys_flush_interval :default_context_keys_flush_interval
|
583
|
-
end
|
584
|
-
|
585
534
|
#
|
586
535
|
# The default value for {#diagnostic_recording_interval}.
|
587
536
|
# @return [Float] 900
|
@@ -647,25 +596,11 @@ module LaunchDarkly
|
|
647
596
|
# @return [Integer]
|
648
597
|
attr_reader :context_cache_size
|
649
598
|
|
650
|
-
#
|
651
|
-
# @deprecated Backwards compatibility alias for #context_cache_size
|
652
|
-
#
|
653
|
-
# @return [Integer]
|
654
|
-
#
|
655
|
-
alias :user_cache_size :context_cache_size
|
656
|
-
|
657
599
|
# The maximum length of time (in seconds) that the Big Segment state for a context will be cached
|
658
600
|
# by the SDK.
|
659
601
|
# @return [Float]
|
660
602
|
attr_reader :context_cache_time
|
661
603
|
|
662
|
-
#
|
663
|
-
# @deprecated Backwards compatibility alias for #context_cache_time
|
664
|
-
#
|
665
|
-
# @return [Float]
|
666
|
-
#
|
667
|
-
alias :user_cache_time :context_cache_time
|
668
|
-
|
669
604
|
# The interval (in seconds) at which the SDK will poll the Big Segment store to make sure it is
|
670
605
|
# available and to determine how long ago it was updated.
|
671
606
|
# @return [Float]
|
data/lib/ldclient-rb/context.rb
CHANGED
@@ -47,9 +47,6 @@ module LaunchDarkly
|
|
47
47
|
# @return [String, nil] Returns the error associated with this LDContext if invalid
|
48
48
|
attr_reader :error
|
49
49
|
|
50
|
-
# @return [Array<Reference>] Returns the private attributes associated with this LDContext
|
51
|
-
attr_reader :private_attributes
|
52
|
-
|
53
50
|
#
|
54
51
|
# @private
|
55
52
|
# @param key [String, nil]
|
@@ -69,10 +66,10 @@ module LaunchDarkly
|
|
69
66
|
@name = name
|
70
67
|
@anonymous = anonymous || false
|
71
68
|
@attributes = attributes
|
72
|
-
@private_attributes =
|
69
|
+
@private_attributes = Set.new
|
73
70
|
(private_attributes || []).each do |attribute|
|
74
71
|
reference = Reference.create(attribute)
|
75
|
-
@private_attributes
|
72
|
+
@private_attributes.add(reference) if reference.error.nil?
|
76
73
|
end
|
77
74
|
@error = error
|
78
75
|
@contexts = contexts
|
@@ -80,6 +77,16 @@ module LaunchDarkly
|
|
80
77
|
end
|
81
78
|
private_class_method :new
|
82
79
|
|
80
|
+
protected attr_reader :name, :anonymous, :attributes
|
81
|
+
|
82
|
+
#
|
83
|
+
# @return [Array<Reference>] Returns the private attributes associated with this LDContext
|
84
|
+
#
|
85
|
+
def private_attributes
|
86
|
+
# TODO(sc-227265): Return a set instead of an array.
|
87
|
+
@private_attributes.to_a
|
88
|
+
end
|
89
|
+
|
83
90
|
#
|
84
91
|
# @return [Boolean] Is this LDContext a multi-kind context?
|
85
92
|
#
|
@@ -274,6 +281,59 @@ module LaunchDarkly
|
|
274
281
|
nil
|
275
282
|
end
|
276
283
|
|
284
|
+
#
|
285
|
+
# An LDContext can be compared to other LDContexts or to a hash object. If
|
286
|
+
# a hash is provided, it is first converted to an LDContext using the
|
287
|
+
# `LDContext.create` method.
|
288
|
+
#
|
289
|
+
# @param other [LDContext, Hash]
|
290
|
+
# @return [Boolean]
|
291
|
+
#
|
292
|
+
def ==(other)
|
293
|
+
other = LDContext.create(other) if other.is_a? Hash
|
294
|
+
return false unless other.is_a? LDContext
|
295
|
+
|
296
|
+
return false unless self.kind == other.kind
|
297
|
+
return false unless self.valid? == other.valid?
|
298
|
+
return false unless self.error == other.error
|
299
|
+
|
300
|
+
return false unless self.individual_context_count == other.individual_context_count
|
301
|
+
|
302
|
+
if self.multi_kind?
|
303
|
+
self.kinds.each do |kind|
|
304
|
+
return false unless self.individual_context(kind) == other.individual_context(kind)
|
305
|
+
end
|
306
|
+
|
307
|
+
return true
|
308
|
+
end
|
309
|
+
|
310
|
+
return false unless self.key == other.key
|
311
|
+
return false unless self.name == other.name
|
312
|
+
return false unless self.anonymous == other.anonymous
|
313
|
+
return false unless self.attributes == other.attributes
|
314
|
+
|
315
|
+
# TODO(sc-227265): Calling .to_set is unnecessary once private_attributes are sets.
|
316
|
+
return false unless self.private_attributes.to_set == other.private_attributes.to_set
|
317
|
+
|
318
|
+
true
|
319
|
+
end
|
320
|
+
alias eql? ==
|
321
|
+
|
322
|
+
#
|
323
|
+
# For a single-kind context, the provided key will return the attribute value specified. This is the same as calling
|
324
|
+
# `LDCotnext.get_value`.
|
325
|
+
#
|
326
|
+
# For multi-kind contexts, the key will be interpreted as a context kind. If the multi-kind context has an
|
327
|
+
# individual context of that kind, it will be returned. Otherwise, this method will return nil. This behaves the
|
328
|
+
# same as calling `LDContext.individual_context`.
|
329
|
+
#
|
330
|
+
# @param key [Symbol, String]
|
331
|
+
#
|
332
|
+
def [](key)
|
333
|
+
return nil unless key.is_a? Symbol or key.is_a? String
|
334
|
+
multi_kind? ? individual_context(key.to_s) : get_value(key)
|
335
|
+
end
|
336
|
+
|
277
337
|
#
|
278
338
|
# Retrieve the value of any top level, addressable attribute.
|
279
339
|
#
|
@@ -324,7 +384,6 @@ module LaunchDarkly
|
|
324
384
|
#
|
325
385
|
def self.create(data)
|
326
386
|
return create_invalid_context(ERR_NOT_HASH) unless data.is_a?(Hash)
|
327
|
-
return create_legacy_context(data) unless data.has_key?(:kind)
|
328
387
|
|
329
388
|
kind = data[:kind]
|
330
389
|
if kind == KIND_MULTI
|
@@ -394,52 +453,6 @@ module LaunchDarkly
|
|
394
453
|
new(nil, nil, nil, nil, false, nil, nil, error)
|
395
454
|
end
|
396
455
|
|
397
|
-
#
|
398
|
-
# @param data [Hash]
|
399
|
-
# @return [LDContext]
|
400
|
-
#
|
401
|
-
private_class_method def self.create_legacy_context(data)
|
402
|
-
warn("DEPRECATED: legacy user format will be removed in 8.0.0", uplevel: 1)
|
403
|
-
|
404
|
-
key = data[:key]
|
405
|
-
|
406
|
-
# Legacy users are allowed to have "" as a key but they cannot have nil as a key.
|
407
|
-
return create_invalid_context(ERR_KEY_EMPTY) if key.nil?
|
408
|
-
|
409
|
-
name = data[:name]
|
410
|
-
name_error = LaunchDarkly::Impl::Context.validate_name(name)
|
411
|
-
return create_invalid_context(name_error) unless name_error.nil?
|
412
|
-
|
413
|
-
anonymous = data[:anonymous]
|
414
|
-
anonymous_error = LaunchDarkly::Impl::Context.validate_anonymous(anonymous, true)
|
415
|
-
return create_invalid_context(anonymous_error) unless anonymous_error.nil?
|
416
|
-
|
417
|
-
custom = data[:custom]
|
418
|
-
unless custom.nil? || custom.is_a?(Hash)
|
419
|
-
return create_invalid_context(ERR_CUSTOM_NON_HASH)
|
420
|
-
end
|
421
|
-
|
422
|
-
# We only need to create an attribute hash if one of these keys exist.
|
423
|
-
# Everything else is stored in dedicated instance variables.
|
424
|
-
attributes = custom.clone
|
425
|
-
data.each do |k, v|
|
426
|
-
case k
|
427
|
-
when :ip, :email, :avatar, :firstName, :lastName, :country
|
428
|
-
attributes ||= {}
|
429
|
-
attributes[k] = v.clone
|
430
|
-
else
|
431
|
-
next
|
432
|
-
end
|
433
|
-
end
|
434
|
-
|
435
|
-
private_attributes = data[:privateAttributeNames]
|
436
|
-
if private_attributes && !private_attributes.is_a?(Array)
|
437
|
-
return create_invalid_context(ERR_PRIVATE_NON_ARRAY)
|
438
|
-
end
|
439
|
-
|
440
|
-
new(key.to_s, key.to_s, KIND_DEFAULT, name, anonymous, attributes, private_attributes)
|
441
|
-
end
|
442
|
-
|
443
456
|
#
|
444
457
|
# @param data [Hash]
|
445
458
|
# @param kind [String]
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module LaunchDarkly
|
3
2
|
# An object returned by {LDClient#variation_detail}, combining the result of a flag evaluation with
|
4
3
|
# an explanation of how it was calculated.
|
@@ -13,6 +12,7 @@ module LaunchDarkly
|
|
13
12
|
def initialize(value, variation_index, reason)
|
14
13
|
raise ArgumentError.new("variation_index must be a number") if !variation_index.nil? && !(variation_index.is_a? Numeric)
|
15
14
|
raise ArgumentError.new("reason must be an EvaluationReason") unless reason.is_a? EvaluationReason
|
15
|
+
|
16
16
|
@value = value
|
17
17
|
@variation_index = variation_index
|
18
18
|
@reason = reason
|
@@ -100,6 +100,10 @@ module LaunchDarkly
|
|
100
100
|
# a rule specified a nonexistent variation. An error message will always be logged in this case.
|
101
101
|
ERROR_MALFORMED_FLAG = :MALFORMED_FLAG
|
102
102
|
|
103
|
+
# Value for {#error_kind} indicating that there was an inconsistency between the expected type of the flag, and the
|
104
|
+
# actual type of the variation evaluated.
|
105
|
+
ERROR_WRONG_TYPE = :WRONG_TYPE
|
106
|
+
|
103
107
|
# Value for {#error_kind} indicating that the caller passed `nil` for the context parameter, or the
|
104
108
|
# context was invalid.
|
105
109
|
ERROR_USER_NOT_SPECIFIED = :USER_NOT_SPECIFIED
|
data/lib/ldclient-rb/events.rb
CHANGED
@@ -40,7 +40,9 @@ module LaunchDarkly
|
|
40
40
|
default = nil,
|
41
41
|
track_events = false,
|
42
42
|
debug_until = nil,
|
43
|
-
prereq_of = nil
|
43
|
+
prereq_of = nil,
|
44
|
+
sampling_ratio = nil,
|
45
|
+
exclude_from_summaries = false
|
44
46
|
)
|
45
47
|
end
|
46
48
|
|
@@ -55,6 +57,9 @@ module LaunchDarkly
|
|
55
57
|
)
|
56
58
|
end
|
57
59
|
|
60
|
+
def record_migration_op_event(event)
|
61
|
+
end
|
62
|
+
|
58
63
|
def flush
|
59
64
|
end
|
60
65
|
|
@@ -153,10 +158,12 @@ module LaunchDarkly
|
|
153
158
|
default = nil,
|
154
159
|
track_events = false,
|
155
160
|
debug_until = nil,
|
156
|
-
prereq_of = nil
|
161
|
+
prereq_of = nil,
|
162
|
+
sampling_ratio = nil,
|
163
|
+
exclude_from_summaries = false
|
157
164
|
)
|
158
165
|
post_to_inbox(LaunchDarkly::Impl::EvalEvent.new(timestamp, context, key, version, variation, value, reason,
|
159
|
-
default, track_events, debug_until, prereq_of))
|
166
|
+
default, track_events, debug_until, prereq_of, sampling_ratio, exclude_from_summaries))
|
160
167
|
end
|
161
168
|
|
162
169
|
def record_identify_event(context)
|
@@ -167,6 +174,10 @@ module LaunchDarkly
|
|
167
174
|
post_to_inbox(LaunchDarkly::Impl::CustomEvent.new(timestamp, context, key, data, metric_value))
|
168
175
|
end
|
169
176
|
|
177
|
+
def record_migration_op_event(event)
|
178
|
+
post_to_inbox(event)
|
179
|
+
end
|
180
|
+
|
170
181
|
def flush
|
171
182
|
# flush is done asynchronously
|
172
183
|
post_to_inbox(FlushMessage.new)
|
@@ -220,6 +231,7 @@ module LaunchDarkly
|
|
220
231
|
@config = config
|
221
232
|
@diagnostic_accumulator = config.diagnostic_opt_out? ? nil : diagnostic_accumulator
|
222
233
|
@event_sender = event_sender
|
234
|
+
@sampler = LaunchDarkly::Impl::Sampler.new(Random.new)
|
223
235
|
|
224
236
|
@context_keys = SimpleLRUCacheSet.new(config.context_keys_capacity)
|
225
237
|
@formatter = EventOutputFormatter.new(config)
|
@@ -292,7 +304,7 @@ module LaunchDarkly
|
|
292
304
|
return if @disabled.value
|
293
305
|
|
294
306
|
# Always record the event in the summary.
|
295
|
-
outbox.add_to_summary(event)
|
307
|
+
outbox.add_to_summary(event) unless event.exclude_from_summaries
|
296
308
|
|
297
309
|
# Decide whether to add the event to the payload. Feature events may be added twice, once for
|
298
310
|
# the event (if tracked) and once for debugging.
|
@@ -309,12 +321,12 @@ module LaunchDarkly
|
|
309
321
|
|
310
322
|
# For each context we haven't seen before, we add an index event - unless this is already
|
311
323
|
# an identify event for that context.
|
312
|
-
if !event.context.nil? && !notice_context(event.context) && !event.is_a?(LaunchDarkly::Impl::IdentifyEvent)
|
324
|
+
if !event.context.nil? && !notice_context(event.context) && !event.is_a?(LaunchDarkly::Impl::IdentifyEvent) && !event.is_a?(LaunchDarkly::Impl::MigrationOpEvent)
|
313
325
|
outbox.add_event(LaunchDarkly::Impl::IndexEvent.new(event.timestamp, event.context))
|
314
326
|
end
|
315
327
|
|
316
|
-
outbox.add_event(event) if will_add_full_event
|
317
|
-
outbox.add_event(debug_event)
|
328
|
+
outbox.add_event(event) if will_add_full_event && @sampler.sample(event.sampling_ratio.nil? ? 1 : event.sampling_ratio)
|
329
|
+
outbox.add_event(debug_event) if !debug_event.nil? && @sampler.sample(event.sampling_ratio.nil? ? 1 : event.sampling_ratio)
|
318
330
|
end
|
319
331
|
|
320
332
|
#
|
@@ -443,6 +455,7 @@ module LaunchDarkly
|
|
443
455
|
CUSTOM_KIND = 'custom'
|
444
456
|
INDEX_KIND = 'index'
|
445
457
|
DEBUG_KIND = 'debug'
|
458
|
+
MIGRATION_OP_KIND = 'migration_op'
|
446
459
|
SUMMARY_KIND = 'summary'
|
447
460
|
|
448
461
|
def initialize(config)
|
@@ -476,6 +489,64 @@ module LaunchDarkly
|
|
476
489
|
out[:reason] = event.reason unless event.reason.nil?
|
477
490
|
out
|
478
491
|
|
492
|
+
when LaunchDarkly::Impl::MigrationOpEvent
|
493
|
+
out = {
|
494
|
+
kind: MIGRATION_OP_KIND,
|
495
|
+
creationDate: event.timestamp,
|
496
|
+
contextKeys: event.context.keys,
|
497
|
+
operation: event.operation.to_s,
|
498
|
+
evaluation: {
|
499
|
+
key: event.key,
|
500
|
+
value: event.evaluation.value,
|
501
|
+
},
|
502
|
+
}
|
503
|
+
|
504
|
+
out[:evaluation][:version] = event.version unless event.version.nil?
|
505
|
+
out[:evaluation][:default] = event.default unless event.default.nil?
|
506
|
+
out[:evaluation][:variation] = event.evaluation.variation_index unless event.evaluation.variation_index.nil?
|
507
|
+
out[:evaluation][:reason] = event.evaluation.reason unless event.evaluation.reason.nil?
|
508
|
+
out[:samplingRatio] = event.sampling_ratio unless event.sampling_ratio.nil? || event.sampling_ratio == 1
|
509
|
+
|
510
|
+
measurements = []
|
511
|
+
|
512
|
+
unless event.invoked.empty?
|
513
|
+
measurements << {
|
514
|
+
"key": "invoked",
|
515
|
+
"values": event.invoked.map { |origin| [origin, true] }.to_h,
|
516
|
+
}
|
517
|
+
end
|
518
|
+
|
519
|
+
unless event.consistency_check.nil?
|
520
|
+
measurement = {
|
521
|
+
"key": "consistent",
|
522
|
+
"value": event.consistency_check,
|
523
|
+
}
|
524
|
+
|
525
|
+
unless event.consistency_check_ratio.nil? || event.consistency_check_ratio == 1
|
526
|
+
measurement[:samplingRatio] = event.consistency_check_ratio
|
527
|
+
end
|
528
|
+
|
529
|
+
measurements << measurement
|
530
|
+
end
|
531
|
+
|
532
|
+
|
533
|
+
unless event.latencies.empty?
|
534
|
+
measurements << {
|
535
|
+
"key": "latency_ms",
|
536
|
+
"values": event.latencies,
|
537
|
+
}
|
538
|
+
end
|
539
|
+
|
540
|
+
unless event.errors.empty?
|
541
|
+
measurements << {
|
542
|
+
"key": "error",
|
543
|
+
"values": event.errors.map { |origin| [origin, true] }.to_h,
|
544
|
+
}
|
545
|
+
end
|
546
|
+
out[:measurements] = measurements unless measurements.empty?
|
547
|
+
|
548
|
+
out
|
549
|
+
|
479
550
|
when LaunchDarkly::Impl::IdentifyEvent
|
480
551
|
{
|
481
552
|
kind: IDENTIFY_KIND,
|
@@ -23,7 +23,7 @@ module LaunchDarkly
|
|
23
23
|
@last_status = nil
|
24
24
|
|
25
25
|
unless @store.nil?
|
26
|
-
@cache = ExpiringCache.new(big_segments_config.
|
26
|
+
@cache = ExpiringCache.new(big_segments_config.context_cache_size, big_segments_config.context_cache_time)
|
27
27
|
@poll_worker = RepeatingTask.new(big_segments_config.status_poll_interval, 0, -> { poll_store_and_update_status }, logger)
|
28
28
|
@poll_worker.start
|
29
29
|
end
|
@@ -1,23 +1,33 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
module LaunchDarkly
|
2
4
|
module Impl
|
3
5
|
class Event
|
4
6
|
# @param timestamp [Integer]
|
5
7
|
# @param context [LaunchDarkly::LDContext]
|
6
|
-
|
8
|
+
# @param sampling_ratio [Integer, nil]
|
9
|
+
# @param exclude_from_summaries [Boolean]
|
10
|
+
def initialize(timestamp, context, sampling_ratio = nil, exclude_from_summaries = false)
|
7
11
|
@timestamp = timestamp
|
8
12
|
@context = context
|
13
|
+
@sampling_ratio = sampling_ratio
|
14
|
+
@exclude_from_summaries = exclude_from_summaries
|
9
15
|
end
|
10
16
|
|
11
17
|
# @return [Integer]
|
12
18
|
attr_reader :timestamp
|
13
19
|
# @return [LaunchDarkly::LDContext]
|
14
20
|
attr_reader :context
|
21
|
+
# @return [Integer, nil]
|
22
|
+
attr_reader :sampling_ratio
|
23
|
+
# @return [Boolean]
|
24
|
+
attr_reader :exclude_from_summaries
|
15
25
|
end
|
16
26
|
|
17
27
|
class EvalEvent < Event
|
18
28
|
def initialize(timestamp, context, key, version = nil, variation = nil, value = nil, reason = nil, default = nil,
|
19
|
-
track_events = false, debug_until = nil, prereq_of = nil)
|
20
|
-
super(timestamp, context)
|
29
|
+
track_events = false, debug_until = nil, prereq_of = nil, sampling_ratio = nil, exclude_from_summaries = false)
|
30
|
+
super(timestamp, context, sampling_ratio, exclude_from_summaries)
|
21
31
|
@key = key
|
22
32
|
@version = version
|
23
33
|
@variation = variation
|
@@ -41,6 +51,54 @@ module LaunchDarkly
|
|
41
51
|
attr_reader :prereq_of
|
42
52
|
end
|
43
53
|
|
54
|
+
class MigrationOpEvent < Event
|
55
|
+
#
|
56
|
+
# A migration op event represents the results of a migration-assisted read or write operation.
|
57
|
+
#
|
58
|
+
# The event includes optional measurements reporting on consistency checks, error reporting, and operation latency
|
59
|
+
# values.
|
60
|
+
#
|
61
|
+
# @param timestamp [Integer]
|
62
|
+
# @param context [LaunchDarkly::LDContext]
|
63
|
+
# @param key [string]
|
64
|
+
# @param flag [LaunchDarkly::Impl::Model::FeatureFlag, nil]
|
65
|
+
# @param operation [Symbol]
|
66
|
+
# @param default_stage [Symbol]
|
67
|
+
# @param evaluation [LaunchDarkly::EvaluationDetail]
|
68
|
+
# @param invoked [Set]
|
69
|
+
# @param consistency_check [Boolean, nil]
|
70
|
+
# @param consistency_check_ratio [Integer, nil]
|
71
|
+
# @param errors [Set]
|
72
|
+
# @param latencies [Hash<Symbol, Float>]
|
73
|
+
#
|
74
|
+
def initialize(timestamp, context, key, flag, operation, default_stage, evaluation, invoked, consistency_check, consistency_check_ratio, errors, latencies)
|
75
|
+
super(timestamp, context)
|
76
|
+
@operation = operation
|
77
|
+
@key = key
|
78
|
+
@version = flag&.version
|
79
|
+
@sampling_ratio = flag&.sampling_ratio
|
80
|
+
@default = default_stage
|
81
|
+
@evaluation = evaluation
|
82
|
+
@consistency_check = consistency_check
|
83
|
+
@consistency_check_ratio = consistency_check.nil? ? nil : consistency_check_ratio
|
84
|
+
@invoked = invoked
|
85
|
+
@errors = errors
|
86
|
+
@latencies = latencies
|
87
|
+
end
|
88
|
+
|
89
|
+
attr_reader :operation
|
90
|
+
attr_reader :key
|
91
|
+
attr_reader :version
|
92
|
+
attr_reader :sampling_ratio
|
93
|
+
attr_reader :default
|
94
|
+
attr_reader :evaluation
|
95
|
+
attr_reader :consistency_check
|
96
|
+
attr_reader :consistency_check_ratio
|
97
|
+
attr_reader :invoked
|
98
|
+
attr_reader :errors
|
99
|
+
attr_reader :latencies
|
100
|
+
end
|
101
|
+
|
44
102
|
class IdentifyEvent < Event
|
45
103
|
def initialize(timestamp, context)
|
46
104
|
super(timestamp, context)
|