Beispiel #1
0
 def initialize(self,
                zk_hosts,
                aws_keyfile,
                s3_bucket,
                s3_endpoint="s3.amazonaws.com"):
     self.decider_map = ManagedHashMap("admin",
                                       "decider",
                                       "Decider Values",
                                       "Map of decider name and its value",
                                       zk_hosts,
                                       aws_keyfile,
                                       s3_bucket,
                                       s3_endpoint=s3_endpoint)
Beispiel #2
0
 def initialize(self, zk_hosts, aws_keyfile, s3_bucket, s3_endpoint="s3.amazonaws.com"):
     self.decider_map = ManagedHashMap("admin", "decider", "Decider Values",
                                       "Map of decider name and its value",
                                       zk_hosts, aws_keyfile, s3_bucket, s3_endpoint=s3_endpoint)
Beispiel #3
0
class Decider(object):
    __metaclass__ = SingletonMetaclass

    def __init__(self):
        self.initialized = False

    def initialize(self,
                   zk_hosts,
                   aws_keyfile,
                   s3_bucket,
                   s3_endpoint="s3.amazonaws.com"):
        self.decider_map = ManagedHashMap("admin",
                                          "decider",
                                          "Decider Values",
                                          "Map of decider name and its value",
                                          zk_hosts,
                                          aws_keyfile,
                                          s3_bucket,
                                          s3_endpoint=s3_endpoint)

    def check_initialized(self):
        if not self.initialized:
            raise Exception(
                "Decider not initialized! Please call initialize()")

    def get_decider_value(self, experiment_name, default=0):
        """Retrieve the decider value associated with the ``experiment_name``."""
        experiment_name = experiment_name.lower()

        decider_value = self.decider_map.get(experiment_name)

        if decider_value is None:
            decider_value = default

        return decider_value

    def decide_experiment(self, experiment_name, default=False):
        """Decides if a experiment needs to be run. Calculate a random number
           between 1 and 100 and see if its less than a given value.
           Ex: decider.decide_experiment(config.decider.NEW_BOARD_PIN_TUPLES_READ)

        Args:
            default: A boolean, the default value to return if the experiment does not exist.

        """
        default_value = 100 if default else 0
        exp_value = self.get_decider_value(experiment_name,
                                           default=default_value)
        if exp_value == 100:
            return True
        if exp_value == 0:
            return False
        return random.randrange(0, 100, 1) < exp_value

    def is_id_in_experiment(self, decider_id, experiment_name):
        """Decides if an id needs to be run under an experiment_name.
           It modes the id by 100 and see whether it is within
           the decider range.
           Ex: decider.is_id_in_experiment(
               12345, config.decider.NEW_BOARD_PIN_TUPLES_READ)

        NOTE: If you are doing a user-sticky decider, you should probably use is_hashed_id_in_experiment(userid, decider)
        below. This function simply mods the userid by 100, which means that e.g. all user-ID based deciders set to 20%
        will affect the same 20% segment of users.
        """
        decider_value = self.get_decider_value(experiment_name)
        decider_id %= 100
        return decider_id < decider_value

    def is_hashed_id_in_experiment(self, unique_id, experiment_name):
        """Checks if a decider should be active given an ID (e.g. of a user, random request, etc.).

        This function computes a hash of the user ID and the decider, so different deciders will get different
        random samples of users.
           Ex: decider.is_hashed_id_in_decider(context.viewing_user.id, config.decider.NEW_BOARD_PIN_TUPLES_READ)
        """
        decider_value = self.get_decider_value(experiment_name)

        # We add the string decider_ so that if user IDs are used for unique_id, we don't have the same
        # hash as the experiment framework. That would lead to non-independence of this decider
        # and the experiment groups.
        hash_val = hashlib.md5("decider_%s%s" %
                               (experiment_name, unique_id)).hexdigest()
        val = int(hash_val, 16) % 100

        return val < decider_value

    def set_experiment_value(self, experiment_name, value):
        """Set the value of an experiment and update in zookeeper if we are on adminapp
           Ex: decider.set_experiment_value(config.decider.NEW_BOARD_PIN_TUPLES_READ, 80)
           Args:
            experiment_name: a string, the decider's name
            value: an int, the value you want to set
            enable_audit_history: whether to save the change to audit history
            author: A string, the committer of the change.
            comment: A string, a brief description of the change

        """
        if experiment_name.lower() != experiment_name:
            raise Exception("Only use lower case for experiment names")

        if value < 0 or value > 100:
            raise Exception("Invalid experiment value")

        self.decider_map.set(experiment_name, value)
Beispiel #4
0
class Decider(object):
    __metaclass__ = SingletonMetaclass

    def __init__(self):
        self.initialized = False

    def initialize(self, zk_hosts, aws_keyfile, s3_bucket, s3_endpoint="s3.amazonaws.com"):
        self.decider_map = ManagedHashMap("admin", "decider", "Decider Values",
                                          "Map of decider name and its value",
                                          zk_hosts, aws_keyfile, s3_bucket, s3_endpoint=s3_endpoint)

    def check_initialized(self):
        if not self.initialized:
            raise Exception("Decider not initialized! Please call initialize()")

    def get_decider_value(self, experiment_name, default=0):
        """Retrieve the decider value associated with the ``experiment_name``."""
        experiment_name = experiment_name.lower()

        decider_value = self.decider_map.get(experiment_name)

        if decider_value is None:
            decider_value = default

        return decider_value

    def decide_experiment(self, experiment_name, default=False):
        """Decides if a experiment needs to be run. Calculate a random number
           between 1 and 100 and see if its less than a given value.
           Ex: decider.decide_experiment(config.decider.NEW_BOARD_PIN_TUPLES_READ)

        Args:
            default: A boolean, the default value to return if the experiment does not exist.

        """
        default_value = 100 if default else 0
        exp_value = self.get_decider_value(experiment_name, default=default_value)
        if exp_value == 100:
            return True
        if exp_value == 0:
            return False
        return random.randrange(0, 100, 1) < exp_value

    def is_id_in_experiment(self, decider_id, experiment_name):
        """Decides if an id needs to be run under an experiment_name.
           It modes the id by 100 and see whether it is within
           the decider range.
           Ex: decider.is_id_in_experiment(
               12345, config.decider.NEW_BOARD_PIN_TUPLES_READ)

        NOTE: If you are doing a user-sticky decider, you should probably use is_hashed_id_in_experiment(userid, decider)
        below. This function simply mods the userid by 100, which means that e.g. all user-ID based deciders set to 20%
        will affect the same 20% segment of users.
        """
        decider_value = self.get_decider_value(experiment_name)
        decider_id %= 100
        return decider_id < decider_value

    def is_hashed_id_in_experiment(self, unique_id, experiment_name):
        """Checks if a decider should be active given an ID (e.g. of a user, random request, etc.).

        This function computes a hash of the user ID and the decider, so different deciders will get different
        random samples of users.
           Ex: decider.is_hashed_id_in_decider(context.viewing_user.id, config.decider.NEW_BOARD_PIN_TUPLES_READ)
        """
        decider_value = self.get_decider_value(experiment_name)

        # We add the string decider_ so that if user IDs are used for unique_id, we don't have the same
        # hash as the experiment framework. That would lead to non-independence of this decider
        # and the experiment groups.
        hash_val = hashlib.md5("decider_%s%s" % (experiment_name, unique_id)).hexdigest()
        val = int(hash_val, 16) % 100

        return val < decider_value

    def set_experiment_value(self, experiment_name, value):
        """Set the value of an experiment and update in zookeeper if we are on adminapp
           Ex: decider.set_experiment_value(config.decider.NEW_BOARD_PIN_TUPLES_READ, 80)
           Args:
            experiment_name: a string, the decider's name
            value: an int, the value you want to set
            enable_audit_history: whether to save the change to audit history
            author: A string, the committer of the change.
            comment: A string, a brief description of the change

        """
        if experiment_name.lower() != experiment_name:
            raise Exception("Only use lower case for experiment names")

        if value < 0 or value > 100:
            raise Exception("Invalid experiment value")

        self.decider_map.set(experiment_name, value)