diff options
Diffstat (limited to 'lib/gitlab/experimentation.rb')
-rw-r--r-- | lib/gitlab/experimentation.rb | 69 |
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? |