Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/ldclient-rb/data_system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ module LaunchDarkly
#
# # Use the default strategy (recommended)
# config = LaunchDarkly::Config.new(
# data_system: LaunchDarkly::DataSystem.default
# data_system_config: LaunchDarkly::DataSystem.default.build
# )
#
# # Use streaming only
# config = LaunchDarkly::Config.new(
# data_system: LaunchDarkly::DataSystem.streaming
# data_system_config: LaunchDarkly::DataSystem.streaming.build
# )
#
# # Use polling only
# config = LaunchDarkly::Config.new(
# data_system: LaunchDarkly::DataSystem.polling
# data_system_config: LaunchDarkly::DataSystem.polling.build
# )
#
# == Custom Configurations
Expand All @@ -52,7 +52,7 @@ module LaunchDarkly
# .initializers([polling])
# .synchronizers([streaming, polling])
#
# config = LaunchDarkly::Config.new(data_system: data_system)
# config = LaunchDarkly::Config.new(data_system_config: data_system.build)
#
module DataSystem
#
Expand Down
40 changes: 24 additions & 16 deletions lib/ldclient-rb/events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ def record_eval_event(
debug_until = nil,
prereq_of = nil,
sampling_ratio = nil,
exclude_from_summaries = false
exclude_from_summaries = false,
override_affected = false
)
end

Expand Down Expand Up @@ -176,10 +177,11 @@ def record_eval_event(
debug_until = nil,
prereq_of = nil,
sampling_ratio = nil,
exclude_from_summaries = false
exclude_from_summaries = false,
override_affected = false
)
post_to_inbox(LaunchDarkly::Impl::EvalEvent.new(timestamp, context, key, version, variation, value, reason,
default, track_events, debug_until, prereq_of, sampling_ratio, exclude_from_summaries))
default, track_events, debug_until, prereq_of, sampling_ratio, exclude_from_summaries, override_affected))
end

def record_identify_event(context)
Expand Down Expand Up @@ -328,8 +330,10 @@ def dispatch_event(event, outbox)
will_add_full_event = false
debug_event = nil
if event.is_a?(LaunchDarkly::Impl::EvalEvent)
will_add_full_event = event.track_events
if should_debug_event(event)
# An override-affected evaluation appears only in the summary counters. It produces no
# individual feature event and no debug event, whatever the flag's configuration requests.
will_add_full_event = event.track_events && !event.override_affected
if !event.override_affected && should_debug_event(event)
debug_event = LaunchDarkly::Impl::DebugEvent.new(event)
end
else
Expand Down Expand Up @@ -630,18 +634,22 @@ def make_output_events(events, summary)
summary.counters.each do |flagKey, flagInfo|
counters = []
flagInfo.versions.each do |version, variations|
variations.each do |variation, counter|
c = {
value: counter.value,
count: counter.count,
}
c[:variation] = variation unless variation.nil?
if version.nil?
c[:unknown] = true
else
c[:version] = version
variations.each do |variation, counters_by_marker|
counters_by_marker.each do |override_affected, counter|
c = {
value: counter.value,
count: counter.count,
}
c[:variation] = variation unless variation.nil?
if version.nil?
c[:unknown] = true
else
c[:version] = version
end
# The marker is present only for override-affected counters, like the unknown marker.
c[:overrideAffected] = true if override_affected
counters.push(c)
end
counters.push(c)
end
end
flags[flagKey] = { default: flagInfo.default, counters: counters, contextKinds: flagInfo.context_kinds.to_a }
Expand Down
15 changes: 13 additions & 2 deletions lib/ldclient-rb/impl/event_summarizer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ module LaunchDarkly
module Impl
EventSummary = Struct.new(:start_date, :end_date, :counters)

# The `versions` member is a hash of hashes: flag version, then variation index, then the
# override-affected marker (a boolean), to an EventSummaryFlagVariationCounter. The marker
# takes part in the key, so override-affected and other evaluations of the same flag,
# variation, and version accumulate into separate counters.
EventSummaryFlagInfo = Struct.new(:default, :versions, :context_kinds)

EventSummaryFlagVariationCounter = Struct.new(:value, :count)
Expand Down Expand Up @@ -39,9 +43,16 @@ def summarize_event(event)

counters_for_flag.context_kinds.merge(event.context.kinds)

variation_counter = counters_for_flag_version[event.variation]
counters_for_variation = counters_for_flag_version[event.variation]
if counters_for_variation.nil?
counters_for_variation = Hash.new
counters_for_flag_version[event.variation] = counters_for_variation
end

override_affected = event.override_affected
variation_counter = counters_for_variation[override_affected]
if variation_counter.nil?
counters_for_flag_version[event.variation] = EventSummaryFlagVariationCounter.new(event.value, 1)
counters_for_variation[override_affected] = EventSummaryFlagVariationCounter.new(event.value, 1)
else
variation_counter.count = variation_counter.count + 1
end
Expand Down
12 changes: 11 additions & 1 deletion lib/ldclient-rb/impl/event_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ def initialize(timestamp, context, sampling_ratio = nil, exclude_from_summaries

class EvalEvent < Event
def initialize(timestamp, context, key, version = nil, variation = nil, value = nil, reason = nil, default = nil,
track_events = false, debug_until = nil, prereq_of = nil, sampling_ratio = nil, exclude_from_summaries = false)
track_events = false, debug_until = nil, prereq_of = nil, sampling_ratio = nil, exclude_from_summaries = false,
override_affected = false)
super(timestamp, context, sampling_ratio, exclude_from_summaries)
@key = key
@version = version
Expand All @@ -38,6 +39,7 @@ def initialize(timestamp, context, key, version = nil, variation = nil, value =
@track_events = track_events if track_events
@debug_until = debug_until if debug_until
@prereq_of = prereq_of if prereq_of
@override_affected = true if override_affected
end

attr_reader :key
Expand All @@ -49,6 +51,14 @@ def initialize(timestamp, context, key, version = nil, variation = nil, value =
attr_reader :track_events
attr_reader :debug_until
attr_reader :prereq_of

# True if an override affected the evaluation, directly or through a prerequisite or segment.
# Such an evaluation appears only in the summary counters, under a counter that carries the
# override-affected marker. It produces no individual feature event and no debug event.
# @return [Boolean]
def override_affected
@override_affected ? true : false
end
end

class MigrationOpEvent < Event
Expand Down
21 changes: 12 additions & 9 deletions lib/ldclient-rb/impl/file_data/reloader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
require "ldclient-rb/impl/file_data/document"
require "ldclient-rb/impl/file_data/merge"
require "ldclient-rb/impl/file_data/poller"
require "ldclient-rb/impl/util"

require "digest"

Expand Down Expand Up @@ -98,6 +97,7 @@ class Reloader
# is parsed as it is.
# @param skip_unchanged [Boolean] if true, `apply` is not invoked when the files' raw
# contents are byte-identical to the last successfully applied contents.
# @param log_prefix [String] the prefix of every log line this reloader writes
# @param clock [#call, nil] returns the seconds of a monotonic clock, for the time a file has
# been held back; nil for the system's. Scheduling always uses the system's clock.
#
Expand All @@ -107,9 +107,11 @@ def initialize(paths:, logger:, apply:, on_error: nil,
debounce_delay: DEFAULT_DEBOUNCE_DELAY,
retry_delay: DEFAULT_RETRY_DELAY,
skip_unchanged: false,
log_prefix: "[LDClient]",
clock: nil)
@paths = paths
@logger = logger
@log_prefix = log_prefix
@apply = apply
@on_error = on_error
@duplicate_keys_handling = duplicate_keys_handling
Expand Down Expand Up @@ -222,7 +224,7 @@ def stop

# An unexpected error must not end the worker: no reload would happen after it.
begin
@logger.info { "[LDClient] Reloading flag data after detecting a change" } if action == :reload
@logger.info { "#{@log_prefix} Reloading flag data after detecting a change" } if action == :reload
retry_in = reload(retrying: action == :retry)
@mutex.synchronize do
# A pending retry is superseded by this reload. The reload either succeeded, or it
Expand All @@ -241,7 +243,8 @@ def stop
end

private def log_unexpected_error(error)
Util.log_exception(@logger, "Unexpected error in file data reloader", error)
@logger.error { "#{@log_prefix} Unexpected error in file data reloader: #{error.inspect}" }
@logger.debug { "#{@log_prefix} Exception trace: #{error.backtrace}" }
end

#
Expand Down Expand Up @@ -297,9 +300,9 @@ def stop

if retrying
if @read_again_pending
@logger.debug { "[LDClient] Reading flag data again after a file was found empty" }
@logger.debug { "#{@log_prefix} Reading flag data again after a file was found empty" }
else
@logger.debug { "[LDClient] Retrying flag data load after earlier failure" }
@logger.debug { "#{@log_prefix} Retrying flag data load after earlier failure" }
end
end
@read_again_pending = false
Expand Down Expand Up @@ -350,7 +353,7 @@ def stop
reached << path
end
if e.missing && @skip_missing_paths
@logger.debug { "[LDClient] File #{path} does not exist; it contributes no data" }
@logger.debug { "#{@log_prefix} File #{path} does not exist; it contributes no data" }
had_content[path] = false
append_to_digest(digest, path, nil)
files << FileSummary.new(path, false, 0, 0)
Expand Down Expand Up @@ -521,7 +524,7 @@ def stop
retry_at = nil
paths.each do |path|
@logger.debug do
"[LDClient] File #{path} is empty, possibly while it is being rewritten; reading it again before applying it"
"#{@log_prefix} File #{path} is empty, possibly while it is being rewritten; reading it again before applying it"
end
empty = @empty_files[path]
over = [empty.since + @retry_delay, empty.first_held + MAX_HOLD_RETRY_DELAYS * @retry_delay].min
Expand All @@ -540,12 +543,12 @@ def stop
# level and do not re-invoke on_error.
message = error.message
if message == @last_error_message
@logger.debug { "[LDClient] Unable to load flags: #{message}" }
@logger.debug { "#{@log_prefix} Unable to load flags: #{message}" }
return @retry_delay
end

@last_error_message = message
@logger.error { "[LDClient] Unable to load flags: #{message}" }
@logger.error { "#{@log_prefix} Unable to load flags: #{message}" }
@on_error&.call(error)
@retry_delay
end
Expand Down
Loading
Loading