Class: EppoClient::Client

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/client.rb

Overview

The main client singleton

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#assignment_loggerObject

Returns the value of attribute assignment_logger.



16
17
18
# File 'lib/client.rb', line 16

def assignment_logger
  @assignment_logger
end

#config_requestorObject

Returns the value of attribute config_requestor.



16
17
18
# File 'lib/client.rb', line 16

def config_requestor
  @config_requestor
end

#pollerObject

Returns the value of attribute poller.



16
17
18
# File 'lib/client.rb', line 16

def poller
  @poller
end

Instance Method Details

#get_assignment(subject_key, flag_or_experiment_key, subject_attributes = {}) ⇒ Object

rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity



23
24
25
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
70
71
72
73
74
75
76
77
78
# File 'lib/client.rb', line 23

def get_assignment(subject_key, flag_or_experiment_key, subject_attributes = {})
  EppoClient.validate_not_blank('subject_key', subject_key)
  EppoClient.validate_not_blank('flag_or_experiment_key', flag_or_experiment_key)
  experiment_config = @config_requestor.get_configuration(flag_or_experiment_key)
  override = get_subject_variation_override(experiment_config, subject_key)
  return override unless override.nil?

  if experiment_config.nil? || experiment_config.enabled == false
    EppoClient.logger('out').info(
      "[Eppo SDK] No assigned variation. No active experiment or flag for key: #{flag_or_experiment_key}"
    )
    return nil
  end

  matched_rule = EppoClient.find_matching_rule(subject_attributes, experiment_config.rules)
  if matched_rule.nil?
    EppoClient.logger('out').info(
      "[Eppo SDK] No assigned variation. Subject attributes do not match targeting rules: #{subject_attributes}"
    )
    return nil
  end

  allocation = experiment_config.allocations[matched_rule.allocation_key]
  unless in_experiment_sample?(
    subject_key,
    flag_or_experiment_key,
    experiment_config.subject_shards,
    allocation.percent_exposure
  )
    EppoClient.logger('out').info(
      '[Eppo SDK] No assigned variation. Subject is not part of experiment sample population'
    )
    return nil
  end

  shard = EppoClient.get_shard("assignment-#{subject_key}-#{flag_or_experiment_key}", experiment_config.subject_shards)
  assigned_variation = allocation.variations.find { |var| var.shard_range.shard_in_range?(shard) }.value

  assignment_event = {
    "experiment": flag_or_experiment_key,
    "variation": assigned_variation,
    "subject": subject_key,
    "timestamp": Time.now.utc.iso8601,
    "subjectAttributes": subject_attributes
  }

  begin
    @assignment_logger.log_assignment(assignment_event)
  rescue EppoClient::AssignmentLoggerError => e
    # This error means that log_assignment was not set up. This is okay to ignore.
  rescue StandardError => e
    EppoClient.logger('err').info("[Eppo SDK] Error logging assignment event: #{e}")
  end

  assigned_variation
end

#get_subject_variation_override(experiment_config, subject) ⇒ Object



85
86
87
88
# File 'lib/client.rb', line 85

def get_subject_variation_override(experiment_config, subject)
  subject_hash = Digest::MD5.hexdigest(subject.to_s)
  experiment_config&.overrides && experiment_config.overrides[subject_hash]
end

#in_experiment_sample?(subject, experiment_key, subject_shards, percent_exposure) ⇒ Boolean

Returns:

  • (Boolean)


90
91
92
93
# File 'lib/client.rb', line 90

def in_experiment_sample?(subject, experiment_key, subject_shards, percent_exposure)
  shard = EppoClient.get_shard("exposure-#{subject}-#{experiment_key}", subject_shards)
  shard <= percent_exposure * subject_shards
end

#instanceObject



18
19
20
# File 'lib/client.rb', line 18

def instance
  Client.instance
end

#shutdownObject

rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity



81
82
83
# File 'lib/client.rb', line 81

def shutdown
  @poller.stop
end