-
-
Notifications
You must be signed in to change notification settings - Fork 365
/
configuration.rb
166 lines (151 loc) · 5.13 KB
/
configuration.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
module Split
class Configuration
BOTS = {
# Indexers
"AdsBot-Google" => 'Google Adwords',
'Baidu' => 'Chinese search engine',
'Gigabot' => 'Gigabot spider',
'Googlebot' => 'Google spider',
'msnbot' => 'Microsoft bot',
'bingbot' => 'Microsoft bing bot',
'rogerbot' => 'SeoMoz spider',
'Slurp' => 'Yahoo spider',
'Sogou' => 'Chinese search engine',
"spider" => 'generic web spider',
'WordPress' => 'WordPress spider',
'ZIBB' => 'ZIBB spider',
'YandexBot' => 'Yandex 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',
'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?',
"Wget" => 'wget unix CLI http client',
# URL expanders / previewers
'awe.sm' => 'Awe.sm URL expander',
"bitlybot" => 'bit.ly bot',
"facebookexternalhit" => 'facebook bot',
'LongURL' => 'URL expander service',
'Twitterbot' => 'Twitter URL expander',
'UnwindFetch' => 'Gnip URL expander',
# Uptime monitoring
'check_http' => 'Nagios monitor',
'NewRelicPinger' => 'NewRelic monitor',
'Panopta' => 'Monitoring service',
"Pingdom" => 'Pingdom monitoring',
'SiteUptime' => 'Site monitoring services',
# ???
"DigitalPersona Fingerprint Software" => 'HP Fingerprint scanner',
"ShowyouBot" => 'Showyou iOS app spider',
'ZyBorg' => 'Zyborg? Hmmm....',
}
attr_accessor :robot_regex
attr_accessor :ignore_ip_addresses
attr_accessor :db_failover
attr_accessor :db_failover_on_db_error
attr_accessor :db_failover_allow_parameter_override
attr_accessor :allow_multiple_experiments
attr_accessor :enabled
attr_accessor :experiments
attr_accessor :persistence
attr_accessor :algorithm
def disabled?
!enabled
end
def experiment_for(name)
if normalized_experiments
# TODO symbols
normalized_experiments[name.to_sym]
end
end
def metrics
return @metrics if defined?(@metrics)
@metrics = {}
if self.experiments
self.experiments.each do |key, value|
metric_name = value_for(value, :metric).to_sym rescue nil
if metric_name
@metrics[metric_name] ||= []
@metrics[metric_name] << Split::Experiment.new(key)
end
end
end
@metrics
end
def normalized_experiments
if @experiments.nil?
nil
else
experiment_config = {}
@experiments.keys.each do |name|
experiment_config[name.to_sym] = {}
end
@experiments.each do |experiment_name, settings|
if alternatives = value_for(settings, :alternatives)
experiment_config[experiment_name.to_sym][:alternatives] = normalize_alternatives(alternatives)
end
if goals = value_for(settings, :goals)
experiment_config[experiment_name.to_sym][:goals] = goals
end
end
experiment_config
end
end
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
def initialize
@robot_regex = /\b(?:#{escaped_bots.join('|')})\b|\A\W*\z/i
@ignore_ip_addresses = []
@db_failover = false
@db_failover_on_db_error = proc{|error|} # e.g. use Rails logger here
@db_failover_allow_parameter_override = false
@allow_multiple_experiments = false
@enabled = true
@experiments = {}
@persistence = Split::Persistence::SessionAdapter
@algorithm = Split::Algorithms::WeightedSample
end
private
def value_for(hash, key)
if hash.kind_of?(Hash)
hash[key.to_s] || hash[key.to_sym]
end
end
def escaped_bots
BOTS.map { |key, _| Regexp.escape(key) }
end
end
end