launchdarkly-server-sdk 7.3.2 → 8.1.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 +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)
|