class Split::Configuration

Attributes

algorithm[RW]
allow_multiple_experiments[RW]
beta_probability_simulations[RW]
bots[W]
dashboard_pagination_default_per_page[RW]
db_failover[RW]
db_failover_allow_parameter_override[RW]
db_failover_on_db_error[RW]
enabled[RW]
experiments[R]
ignore_filter[RW]
ignore_ip_addresses[RW]
include_rails_helper[RW]
on_before_experiment_delete[RW]
on_before_experiment_reset[RW]
on_experiment_delete[RW]
on_experiment_reset[RW]
on_trial[RW]
on_trial_choose[RW]
on_trial_complete[RW]
persistence[RW]
redis[RW]
reset_manually[RW]
robot_regex[W]
start_manually[RW]
store_override[RW]
winning_alternative_recalculation_interval[RW]

Public Class Methods

new() click to toggle source
# File lib/split/configuration.rb, line 210
def initialize
  @ignore_ip_addresses = []
  @ignore_filter = proc{ |request| is_robot? || is_ignored_ip_address? }
  @db_failover = false
  @db_failover_on_db_error = proc{|error|} # e.g. use Rails logger here
  @on_experiment_reset = proc{|experiment|}
  @on_experiment_delete = proc{|experiment|}
  @on_before_experiment_reset = proc{|experiment|}
  @on_before_experiment_delete = proc{|experiment|}
  @db_failover_allow_parameter_override = false
  @allow_multiple_experiments = false
  @enabled = true
  @experiments = {}
  @persistence = Split::Persistence::SessionAdapter
  @persistence_cookie_length = 31536000 # One year from now
  @algorithm = Split::Algorithms::WeightedSample
  @include_rails_helper = true
  @beta_probability_simulations = 10000
  @winning_alternative_recalculation_interval = 60 * 60 * 24 # 1 day
  @redis = ENV.fetch(ENV.fetch('REDIS_PROVIDER', 'REDIS_URL'), 'redis://localhost:6379')
  @dashboard_pagination_default_per_page = 10
end

Public Instance Methods

bots() click to toggle source
# File lib/split/configuration.rb, line 35
def bots
  @bots ||= {
    # Indexers
    'AdsBot-Google' => 'Google Adwords',
    'Baidu' => 'Chinese search engine',
    'Baiduspider' => 'Chinese search engine',
    'bingbot' => 'Microsoft bing bot',
    'Butterfly' => 'Topsy Labs',
    'Gigabot' => 'Gigabot spider',
    'Googlebot' => 'Google spider',
    'MJ12bot' => 'Majestic-12 spider',
    'msnbot' => 'Microsoft bot',
    'rogerbot' => 'SeoMoz spider',
    'PaperLiBot' => 'PaperLi is another content curation service',
    'Slurp' => 'Yahoo spider',
    'Sogou' => 'Chinese search engine',
    'spider' => 'generic web spider',
    'UnwindFetchor' => 'Gnip crawler',
    'WordPress' => 'WordPress spider',
    'YandexAccessibilityBot' => 'Yandex accessibility spider',
    'YandexBot' => 'Yandex spider',
    'YandexMobileBot' => 'Yandex mobile spider',
    'ZIBB' => 'ZIBB spider',

    # HTTP libraries
    'Apache-HttpClient' => 'Java http library',
    'AppEngine-Google' => 'Google App Engine',
    'curl' => 'curl unix CLI http client',
    'ColdFusion' => 'ColdFusion http library',
    'EventMachine HttpClient' => 'Ruby http library',
    'Go http package' => 'Go http library',
    'Go-http-client' => 'Go http library',
    'Java' => 'Generic Java http library',
    'libwww-perl' => 'Perl client-server library loved by script kids',
    'lwp-trivial' => 'Another Perl library loved by script kids',
    'Python-urllib' => 'Python http library',
    'PycURL' => 'Python http library',
    'Test Certificate Info' => 'C http library?',
    'Typhoeus' => 'Ruby http library',
    'Wget' => 'wget unix CLI http client',

    # URL expanders / previewers
    'awe.sm' => 'Awe.sm URL expander',
    'bitlybot' => 'bit.ly bot',
    'bot@linkfluence.net' => 'Linkfluence bot',
    'facebookexternalhit' => 'facebook bot',
    'Facebot' => 'Facebook crawler',
    'Feedfetcher-Google' => 'Google Feedfetcher',
    'https://developers.google.com/+/web/snippet' => 'Google+ Snippet Fetcher',
    'LinkedInBot' => 'LinkedIn bot',
    'LongURL' => 'URL expander service',
    'NING' => 'NING - Yet Another Twitter Swarmer',
    'Pinterest' => 'Pinterest Bot',
    'redditbot' => 'Reddit Bot',
    'ShortLinkTranslate' => 'Link shortener',
    'Slackbot' => 'Slackbot link expander',
    'TweetmemeBot' => 'TweetMeMe Crawler',
    'Twitterbot' => 'Twitter URL expander',
    'UnwindFetch' => 'Gnip URL expander',
    'vkShare' => 'VKontake Sharer',

    # Uptime monitoring
    'check_http' => 'Nagios monitor',
    'GoogleStackdriverMonitoring' => 'Google Cloud monitor',
    'NewRelicPinger' => 'NewRelic monitor',
    'Panopta' => 'Monitoring service',
    'Pingdom' => 'Pingdom monitoring',
    'SiteUptime' => 'Site monitoring services',
    'UptimeRobot' => 'Monitoring service',

    # ???
    'DigitalPersona Fingerprint Software' => 'HP Fingerprint scanner',
    'ShowyouBot' => 'Showyou iOS app spider',
    'ZyBorg' => 'Zyborg? Hmmm....',
    'ELB-HealthChecker' => 'ELB Health Check'
  }
end
disabled?() click to toggle source
# File lib/split/configuration.rb, line 118
def disabled?
  !enabled
end
experiment_for(name) click to toggle source
# File lib/split/configuration.rb, line 122
def experiment_for(name)
  if normalized_experiments
    # TODO symbols
    normalized_experiments[name.to_sym]
  end
end
experiments=(experiments) click to toggle source
# File lib/split/configuration.rb, line 113
def experiments= experiments
  raise InvalidExperimentsFormatError.new('Experiments must be a Hash') unless experiments.respond_to?(:keys)
  @experiments = experiments
end
metrics() click to toggle source
# File lib/split/configuration.rb, line 129
def metrics
  return @metrics if defined?(@metrics)
  @metrics = {}
  if self.experiments
    self.experiments.each do |key, value|
      metrics = value_for(value, :metric) rescue nil
      Array(metrics).each do |metric_name|
        if metric_name
          @metrics[metric_name.to_sym] ||= []
          @metrics[metric_name.to_sym] << Split::Experiment.new(key)
        end
      end
    end
  end
  @metrics
end
normalize_alternatives(alternatives) click to toggle source
# File lib/split/configuration.rb, line 175
def normalize_alternatives(alternatives)
  given_probability, num_with_probability = alternatives.inject([0,0]) do |a,v|
    p, n = a
    if percent = value_for(v, :percent)
      [p + percent, n + 1]
    else
      a
    end
  end

  num_without_probability = alternatives.length - num_with_probability
  unassigned_probability = ((100.0 - given_probability) / num_without_probability / 100.0)

  if num_with_probability.nonzero?
    alternatives = alternatives.map do |v|
      if (name = value_for(v, :name)) && (percent = value_for(v, :percent))
        { name => percent / 100.0 }
      elsif name = value_for(v, :name)
        { name => unassigned_probability }
      else
        { v => unassigned_probability }
      end
    end

    [alternatives.shift, alternatives]
  else
    alternatives = alternatives.dup
    [alternatives.shift, alternatives]
  end
end
normalized_experiments() click to toggle source
# File lib/split/configuration.rb, line 146
def normalized_experiments
  return nil if @experiments.nil?

  experiment_config = {}
  @experiments.keys.each do |name|
    experiment_config[name.to_sym] = {}
  end

  @experiments.each do |experiment_name, settings|
    alternatives = if (alts = value_for(settings, :alternatives))
                     normalize_alternatives(alts)
                   end

    experiment_data = {
      alternatives: alternatives,
      goals: value_for(settings, :goals),
      metadata: value_for(settings, :metadata),
      algorithm: value_for(settings, :algorithm),
      resettable: value_for(settings, :resettable)
    }

    experiment_data.each do |name, value|
      experiment_config[experiment_name.to_sym][name] = value if value != nil
    end
  end

  experiment_config
end
redis_url() click to toggle source
# File lib/split/configuration.rb, line 238
def redis_url
  warn '[DEPRECATED] `redis_url` is deprecated in favor of `redis`'
  self.redis
end
redis_url=(value) click to toggle source
# File lib/split/configuration.rb, line 233
def redis_url=(value)
  warn '[DEPRECATED] `redis_url=` is deprecated in favor of `redis=`'
  self.redis = value
end
robot_regex() click to toggle source
# File lib/split/configuration.rb, line 206
def robot_regex
  @robot_regex ||= /\b(?:#{escaped_bots.join('|')})\b|\A\W*\z/i
end

Private Instance Methods

escaped_bots() click to toggle source
# File lib/split/configuration.rb, line 251
def escaped_bots
  bots.map { |key, _| Regexp.escape(key) }
end
value_for(hash, key) click to toggle source
# File lib/split/configuration.rb, line 245
def value_for(hash, key)
  if hash.kind_of?(Hash)
    hash.has_key?(key.to_s) ? hash[key.to_s] : hash[key.to_sym]
  end
end