Class: LaunchDarkly::LDClient

Inherits:
Object
  • Object
show all
Includes:
Evaluation
Defined in:
lib/ldclient-rb/ldclient.rb

Overview

A client for LaunchDarkly. Client instances are thread-safe. Users should create a single client instance for the lifetime of the application.

Constant Summary

Constants included from Evaluation

Evaluation::BUILTINS, Evaluation::DATE_OPERAND, Evaluation::NUMERIC_VERSION_COMPONENTS_REGEX, Evaluation::OPERATORS, Evaluation::SEMVER_OPERAND

Instance Method Summary collapse

Methods included from Evaluation

addZeroVersionComponent, #bucket_user, #bucketable_string_value, #check_prerequisites, #clause_match_user, #clause_match_user_no_segments, comparator, #error_result, #eval_internal, #evaluate, #match_any, #maybe_negate, #rule_match_user, #segment_match_user, #segment_rule_match_user, #user_value, #variation_index_for_user

Constructor Details

#initialize(sdk_key, config = Config.default, wait_for_sec = 5) ⇒ LDClient

Creates a new client instance that connects to LaunchDarkly. A custom configuration parameter can also supplied to specify advanced options, but for most use cases, the default configuration is appropriate.

Parameters:

  • sdk_key (String)

    the SDK key for your LaunchDarkly account

  • config (Config) (defaults to: Config.default)

    an optional client configuration object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/ldclient-rb/ldclient.rb', line 26

def initialize(sdk_key, config = Config.default, wait_for_sec = 5)
  @sdk_key = sdk_key
  @config = config
  @store = config.feature_store

  if @config.offline? || !@config.send_events
    @event_processor = NullEventProcessor.new
  else
    @event_processor = EventProcessor.new(sdk_key, config)
  end

  if @config.use_ldd?
    @config.logger.info { "[LDClient] Started LaunchDarkly Client in LDD mode" }
    return  # requestor and update processor are not used in this mode
  end

  if @config.update_processor
    @update_processor = @config.update_processor
  else
    factory = @config.update_processor_factory || self.method(:create_default_update_processor)
    @update_processor = factory.call(sdk_key, config)
  end

  ready = @update_processor.start
  if wait_for_sec > 0
    ok = ready.wait(wait_for_sec)
    if !ok
      @config.logger.error { "[LDClient] Timeout encountered waiting for LaunchDarkly client initialization" }
    elsif !@update_processor.initialized?
      @config.logger.error { "[LDClient] LaunchDarkly client initialization failed" }
    end
  end
end

Instance Method Details

#all_flags(user) ⇒ Hash

Returns all feature flag values for the given user. This method is deprecated - please use #all_flags_state instead. Current versions of the client-side SDK will not generate analytics events correctly if you pass the result of all_flags.

Parameters:

  • user (Hash)

    The end user requesting the feature flags

Returns:

  • (Hash)

    a hash of feature flag keys to values



189
190
191
# File 'lib/ldclient-rb/ldclient.rb', line 189

def all_flags(user)
  all_flags_state(user).values_map
end

#all_flags_state(user, options = {}) ⇒ FeatureFlagsState

Returns a FeatureFlagsState object that encapsulates the state of all feature flags for a given user, including the flag values and also metadata that can be used on the front end. This method does not send analytics events back to LaunchDarkly.

normally only used for event generation - such as flag versions and evaluation reasons - should be omitted for any flag that does not have event tracking or debugging turned on. This reduces the size of the JSON data if you are passing the flag state to the front end.

Parameters:

  • user (Hash)

    The end user requesting the feature flags

  • options={}
    Hash

    Optional parameters to control how the state is generated

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :client_side_only (Boolean) — default: false

    True if only flags marked for use with the client-side SDK should be included in the state. By default, all flags are included.

  • :with_reasons (Boolean) — default: false

    True if evaluation reasons should be included in the state (see variation_detail). By default, they are not included.

  • :details_only_for_tracked_flags (Boolean) — default: false

    True if any flag metadata that is

Returns:



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/ldclient-rb/ldclient.rb', line 210

def all_flags_state(user, options={})
  return FeatureFlagsState.new(false) if @config.offline?

  unless user && !user[:key].nil?
    @config.logger.error { "[LDClient] User and user key must be specified in all_flags_state" }
    return FeatureFlagsState.new(false)
  end

  sanitize_user(user)

  begin
    features = @store.all(FEATURES)
  rescue => exn
    Util.log_exception(@config.logger, "Unable to read flags for all_flags_state", exn)
    return FeatureFlagsState.new(false)
  end

  state = FeatureFlagsState.new(true)
  client_only = options[:client_side_only] || false
  with_reasons = options[:with_reasons] || false
  details_only_if_tracked = options[:details_only_for_tracked_flags] || false
  features.each do |k, f|
    if client_only && !f[:clientSide]
      next
    end
    begin
      result = evaluate(f, user, @store, @config.logger)
      state.add_flag(f, result.detail.value, result.detail.variation_index, with_reasons ? result.detail.reason : nil,
        details_only_if_tracked)
    rescue => exn
      Util.log_exception(@config.logger, "Error evaluating flag \"#{k}\" in all_flags_state", exn)
      state.add_flag(f, nil, nil, with_reasons ? { kind: 'ERROR', errorKind: 'EXCEPTION' } : nil, details_only_if_tracked)
    end
  end

  state
end

#closevoid

This method returns an undefined value.

Releases all network connections and other resources held by the client, making it no longer usable



252
253
254
255
256
257
# File 'lib/ldclient-rb/ldclient.rb', line 252

def close
  @config.logger.info { "[LDClient] Closing LaunchDarkly client..." }
  @update_processor.stop
  @event_processor.stop
  @store.stop
end

#flushObject



60
61
62
# File 'lib/ldclient-rb/ldclient.rb', line 60

def flush
  @event_processor.flush
end

#identify(user) ⇒ void

This method returns an undefined value.

Registers the user

Parameters:

  • The (Hash)

    user to register



163
164
165
166
# File 'lib/ldclient-rb/ldclient.rb', line 163

def identify(user)
  sanitize_user(user)
  @event_processor.add_event(kind: "identify", key: user[:key], user: user)
end

#initialized?Boolean

Returns whether the client has been initialized and is ready to serve feature flag requests

Returns:

  • (Boolean)

    true if the client has been initialized



75
76
77
# File 'lib/ldclient-rb/ldclient.rb', line 75

def initialized?
  @config.offline? || @config.use_ldd? || @update_processor.initialized?
end

#secure_mode_hash(user) ⇒ Object



69
70
71
# File 'lib/ldclient-rb/ldclient.rb', line 69

def secure_mode_hash(user)
  OpenSSL::HMAC.hexdigest("sha256", @sdk_key, user[:key].to_s)
end

#toggle?(key, user, default = False) ⇒ Boolean

Returns:

  • (Boolean)


64
65
66
67
# File 'lib/ldclient-rb/ldclient.rb', line 64

def toggle?(key, user, default = False)
  @config.logger.warn { "[LDClient] toggle? is deprecated. Use variation instead" }
  variation(key, user, default)
end

#track(event_name, user, data) ⇒ void

This method returns an undefined value.

Tracks that a user performed an event

Parameters:

  • event_name (String)

    The name of the event

  • user (Hash)

    The user that performed the event. This should be the same user hash used in calls to #toggle?

  • data (Hash)

    A hash containing any additional data associated with the event



176
177
178
179
# File 'lib/ldclient-rb/ldclient.rb', line 176

def track(event_name, user, data)
  sanitize_user(user)
  @event_processor.add_event(kind: "custom", key: event_name, user: user, data: data)
end

#variation(key, user, default) ⇒ Object

Determines the variation of a feature flag to present to a user. At a minimum, the user hash should contain a :key .

For authenticated users, the :key should be the unique identifier for your user. For anonymous users, the :key should be a session identifier or cookie. In either case, the only requirement is that the key is unique to a user.

You can also pass IP addresses and country codes in the user hash.

The user hash can contain arbitrary custom attributes stored in a :custom sub-hash:

Attribute values in the custom hash can be integers, booleans, strings, or

lists of integers, booleans, or strings.

Examples:

Basic user hash

{key: "[email protected]"}

More complete user hash

{key: "[email protected]", ip: "127.0.0.1", country: "US"}

A user hash with custom attributes

{key: "[email protected]", custom: {customer_rank: 1000, groups: ["google", "microsoft"]}}

Parameters:

  • key (String)

    the unique feature key for the feature flag, as shown on the LaunchDarkly dashboard

  • user (Hash)

    a hash containing parameters for the end user requesting the flag

  • default

    the default value of the flag

Returns:

  • the variation to show the user, or the default value if there’s an an error



111
112
113
# File 'lib/ldclient-rb/ldclient.rb', line 111

def variation(key, user, default)
  evaluate_internal(key, user, default, false).value
end

#variation_detail(key, user, default) ⇒ Object

Determines the variation of a feature flag for a user, like variation, but also provides additional information about how this value was calculated.

The return value of variation_detail is an EvaluationDetail object, which has three properties:

value: the value that was calculated for this user (same as the return value of variation)

variation_index: the positional index of this value in the flag, e.g. 0 for the first variation - or nil if the default value was returned

reason: a hash describing the main reason why this value was selected. Its :kind property will be one of the following:

  • ‘’OFF’‘: the flag was off and therefore returned its configured off value

  • ‘’FALLTHROUGH’‘: the flag was on but the user did not match any targets or rules

  • ‘’TARGET_MATCH’‘: the user key was specifically targeted for this flag

  • ‘’RULE_MATCH’‘: the user matched one of the flag’s rules; the :ruleIndex and

:ruleId properties indicate the positional index and unique identifier of the rule

  • ‘’PREREQUISITE_FAILED`‘: the flag was considered off because it had at least one

prerequisite flag that either was off or did not return the desired variation; the :prerequisiteKey property indicates the key of the prerequisite that failed

  • ‘’ERROR’‘: the flag could not be evaluated, e.g. because it does not exist or due

to an unexpected error, and therefore returned the default value; the :errorKind property describes the nature of the error, such as ‘’FLAG_NOT_FOUND’‘

The reason will also be included in analytics events, if you are capturing detailed event data for this flag.

Parameters:

  • key (String)

    the unique feature key for the feature flag, as shown on the LaunchDarkly dashboard

  • user (Hash)

    a hash containing parameters for the end user requesting the flag

  • default

    the default value of the flag

Returns:

  • an EvaluationDetail object describing the result



153
154
155
# File 'lib/ldclient-rb/ldclient.rb', line 153

def variation_detail(key, user, default)
  evaluate_internal(key, user, default, true)
end