summaryrefslogtreecommitdiff
path: root/lib/gitlab/experimentation.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/experimentation.rb')
-rw-r--r--lib/gitlab/experimentation.rb69
1 files changed, 59 insertions, 10 deletions
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
index 895755376ee..948f720b01b 100644
--- a/lib/gitlab/experimentation.rb
+++ b/lib/gitlab/experimentation.rb
@@ -14,13 +14,15 @@ module Gitlab
signup_flow: {
feature_toggle: :experimental_separate_sign_up_flow,
environment: ::Gitlab.dev_env_or_com?,
- enabled_ratio: 0.1
+ enabled_ratio: 0.1,
+ tracking_category: 'Growth::Acquisition::Experiment::SignUpFlow'
}
}.freeze
# Controller concern that checks if an experimentation_subject_id cookie is present and sets it if absent.
# Used for A/B testing of experimental features. Exposes the `experiment_enabled?(experiment_name)` method
- # to controllers and views.
+ # to controllers and views. It returns true when the experiment is enabled and the user is selected as part
+ # of the experimental group.
#
module ControllerConcern
extend ActiveSupport::Concern
@@ -36,22 +38,67 @@ module Gitlab
cookies.permanent.signed[:experimentation_subject_id] = {
value: SecureRandom.uuid,
domain: :all,
- secure: ::Gitlab.config.gitlab.https
+ secure: ::Gitlab.config.gitlab.https,
+ httponly: true
}
end
def experiment_enabled?(experiment_key)
- Experimentation.enabled?(experiment_key, experimentation_subject_index)
+ Experimentation.enabled_for_user?(experiment_key, experimentation_subject_index) || forced_enabled?(experiment_key)
+ end
+
+ def track_experiment_event(experiment_key, action)
+ track_experiment_event_for(experiment_key, action) do |tracking_data|
+ ::Gitlab::Tracking.event(tracking_data.delete(:category), tracking_data.delete(:action), tracking_data)
+ end
+ end
+
+ def frontend_experimentation_tracking_data(experiment_key, action)
+ track_experiment_event_for(experiment_key, action) do |tracking_data|
+ gon.push(tracking_data: tracking_data)
+ end
end
private
+ def experimentation_subject_id
+ cookies.signed[:experimentation_subject_id]
+ end
+
def experimentation_subject_index
- experimentation_subject_id = cookies.signed[:experimentation_subject_id]
return if experimentation_subject_id.blank?
experimentation_subject_id.delete('-').hex % 100
end
+
+ def track_experiment_event_for(experiment_key, action)
+ return unless Experimentation.enabled?(experiment_key)
+
+ yield experimentation_tracking_data(experiment_key, action)
+ end
+
+ def experimentation_tracking_data(experiment_key, action)
+ {
+ category: tracking_category(experiment_key),
+ action: action,
+ property: tracking_group(experiment_key),
+ label: experimentation_subject_id
+ }
+ end
+
+ def tracking_category(experiment_key)
+ Experimentation.experiment(experiment_key).tracking_category
+ end
+
+ def tracking_group(experiment_key)
+ return unless Experimentation.enabled?(experiment_key)
+
+ experiment_enabled?(experiment_key) ? 'experimental_group' : 'control_group'
+ end
+
+ def forced_enabled?(experiment_key)
+ params.has_key?(:force_experiment) && params[:force_experiment] == experiment_key.to_s
+ end
end
class << self
@@ -59,18 +106,20 @@ module Gitlab
Experiment.new(EXPERIMENTS[key].merge(key: key))
end
- def enabled?(experiment_key, experimentation_subject_index)
+ def enabled?(experiment_key)
return false unless EXPERIMENTS.key?(experiment_key)
experiment = experiment(experiment_key)
+ experiment.feature_toggle_enabled? && experiment.enabled_for_environment?
+ end
- experiment.feature_toggle_enabled? &&
- experiment.enabled_for_environment? &&
- experiment.enabled_for_experimentation_subject?(experimentation_subject_index)
+ def enabled_for_user?(experiment_key, experimentation_subject_index)
+ enabled?(experiment_key) &&
+ experiment(experiment_key).enabled_for_experimentation_subject?(experimentation_subject_index)
end
end
- Experiment = Struct.new(:key, :feature_toggle, :environment, :enabled_ratio, keyword_init: true) do
+ Experiment = Struct.new(:key, :feature_toggle, :environment, :enabled_ratio, :tracking_category, keyword_init: true) do
def feature_toggle_enabled?
return Feature.enabled?(key, default_enabled: true) if feature_toggle.nil?