gitlab-org--gitlab-foss/app/experiments/application_experiment.rb

69 lines
2.1 KiB
Ruby

# frozen_string_literal: true
class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/NamespacedClass
def enabled?
return false if Feature::Definition.get(feature_flag_name).nil? # there has to be a feature flag yaml file
return false unless Gitlab.dev_env_or_com? # we have to be in an environment that allows experiments
# the feature flag has to be rolled out
Feature.get(feature_flag_name).state != :off # rubocop:disable Gitlab/AvoidFeatureGet
end
def publish(_result = nil)
super
publish_to_client
publish_to_database if @record
end
def publish_to_client
return unless should_track?
Gon.push({ experiment: { name => signature } }, true)
rescue NoMethodError
# means we're not in the request cycle, and can't add to Gon. Log a warning maybe?
end
def publish_to_database
return unless should_track?
# if the context contains a namespace, group, project, user, or actor
value = context.value
subject = value[:namespace] || value[:group] || value[:project] || value[:user] || value[:actor]
return unless ExperimentSubject.valid_subject?(subject)
variant = :experimental if @variant_name != :control
Experiment.add_subject(name, variant: variant || :control, subject: subject)
end
def record!
@record = true
end
def control_behavior
# define a default nil control behavior so we can omit it when not needed
end
# TODO: remove
# This is deprecated logic as of v0.6.0 and should eventually be removed, but
# needs to stay intact for actively running experiments. The new strategy
# utilizes Digest::SHA2, a secret seed, and generates a 64-byte string.
def key_for(source, seed = name)
source = source.keys + source.values if source.is_a?(Hash)
ingredients = Array(source).map { |v| identify(v) }
ingredients.unshift(seed)
Digest::MD5.hexdigest(ingredients.join('|'))
end
private
def feature_flag_name
name.tr('/', '_')
end
def experiment_group?
Feature.enabled?(feature_flag_name, self, type: :experiment, default_enabled: :yaml)
end
end