| OLD | NEW | 
 | (Empty) | 
|   1 # Copyright 2015 The Chromium Authors. All rights reserved. |  | 
|   2 # Use of this source code is governed by a BSD-style license that can be |  | 
|   3 # found in the LICENSE file. |  | 
|   4  |  | 
|   5 """Tools for gradually enabling a feature on a deterministic set of machines. |  | 
|   6  |  | 
|   7 Add a flag to your program to control the percentage of machines that a new |  | 
|   8 feature should be enabled on:: |  | 
|   9  |  | 
|  10     def add_argparse_options(self, parser): |  | 
|  11       parser.add_argument('--myfeature-percent', type=int, default=0) |  | 
|  12  |  | 
|  13     def main(self, opts): |  | 
|  14       if experiments.is_active_for_host('myfeature', opts.myfeature_percent): |  | 
|  15         # do myfeature |  | 
|  16 """ |  | 
|  17  |  | 
|  18 import hashlib |  | 
|  19 import logging |  | 
|  20 import socket |  | 
|  21 import struct |  | 
|  22  |  | 
|  23  |  | 
|  24 def _is_active(labels, percent): |  | 
|  25   h = hashlib.md5() |  | 
|  26   for label, value in sorted(labels.iteritems()): |  | 
|  27     h.update(label) |  | 
|  28     h.update(value) |  | 
|  29  |  | 
|  30   # The first 8 bytes of the hash digest as an unsigned integer. |  | 
|  31   hash_num = struct.unpack_from('Q', h.digest())[0] |  | 
|  32  |  | 
|  33   return (hash_num % 100) < percent |  | 
|  34  |  | 
|  35  |  | 
|  36 def is_active_for_host(experiment_name, percent): |  | 
|  37   ret = _is_active({ |  | 
|  38       'name': experiment_name, |  | 
|  39       'host': socket.getfqdn(), |  | 
|  40   }, percent) |  | 
|  41  |  | 
|  42   if ret: |  | 
|  43     logging.info('Experiment "%s" is active', experiment_name) |  | 
|  44  |  | 
|  45   return ret |  | 
| OLD | NEW |