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
59
60
61
62
63
64
65
66
67
68
69
# 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

  requestor = Requestor.new(sdk_key, config)

  if @config.offline?
    @update_processor = NullUpdateProcessor.new
  else
    if @config.update_processor.nil?
      if @config.stream?
        @update_processor = StreamProcessor.new(sdk_key, config, requestor)
      else
        @config.logger.info { "Disabling streaming API" }
        @config.logger.warn { "You should only disable the streaming API if instructed to do so by LaunchDarkly support" }
        @update_processor = PollingProcessor.new(config, requestor)
      end
    else
      @update_processor = @config.update_processor
    end
  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



200
201
202
# File 'lib/ldclient-rb/ldclient.rb', line 200

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.

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.

Returns:



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
247
248
249
250
251
# File 'lib/ldclient-rb/ldclient.rb', line 217

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
  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)
    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)
    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



257
258
259
260
261
262
# File 'lib/ldclient-rb/ldclient.rb', line 257

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

#flushObject



71
72
73
# File 'lib/ldclient-rb/ldclient.rb', line 71

def flush
  @event_processor.flush
end

#identify(user) ⇒ void

This method returns an undefined value.

Registers the user

Parameters:

  • The (Hash)

    user to register



174
175
176
177
# File 'lib/ldclient-rb/ldclient.rb', line 174

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



86
87
88
# File 'lib/ldclient-rb/ldclient.rb', line 86

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

#secure_mode_hash(user) ⇒ Object



80
81
82
# File 'lib/ldclient-rb/ldclient.rb', line 80

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

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

Returns:

  • (Boolean)


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

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



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

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



122
123
124
# File 'lib/ldclient-rb/ldclient.rb', line 122

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



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

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