1010from .feature_gate import FeatureGate
1111from .layer import Layer
1212from .sdk_configs import _SDK_Configs
13- from .spec_store import _SpecStore
13+ from .spec_store import _SpecStore , EntityType
1414from .statsig_error_boundary import _StatsigErrorBoundary
1515from .statsig_errors import StatsigNameError , StatsigRuntimeError , StatsigValueError
1616from .statsig_event import StatsigEvent
2121from .statsig_user import StatsigUser
2222from .ttl_set import TTLSet
2323from .utils import HashingAlgorithm , compute_dedupe_key_for_gate , is_hash_in_sampling_rate , \
24- compute_dedupe_key_for_config
24+ compute_dedupe_key_for_config , compute_dedupe_key_for_layer
2525
2626RULESETS_SYNC_INTERVAL = 10
2727IDLISTS_SYNC_INTERVAL = 60
@@ -278,9 +278,14 @@ def task():
278278 result = self ._evaluator .get_layer (normal_user , layer_name )
279279
280280 def log_func (layer : Layer , parameter_name : str ):
281- if log_exposure :
281+ should_log , logged_sampling_rate , shadow_logged = self .__determine_sampling (
282+ EntityType .LAYER , layer_name , result , user , parameter_name )
283+
284+ if log_exposure and should_log :
282285 self ._logger .log_layer_exposure (
283- normal_user , layer , parameter_name , result
286+ normal_user , layer , parameter_name , result , sampling_rate = logged_sampling_rate ,
287+ shadow_logged = shadow_logged ,
288+ sampling_mode = _SDK_Configs .get_config_str_value ("sampling_mode" )
284289 )
285290
286291 layer = Layer ._create (
@@ -490,7 +495,8 @@ def _verify_bg_threads_running(self):
490495 def __check_gate (self , user : StatsigUser , gate_name : str , log_exposure = True ):
491496 user = self .__normalize_user (user )
492497 result = self ._evaluator .check_gate (user , gate_name )
493- should_log , logged_sampling_rate , shadow_logged = self .__determine_sampling ("GATE" , gate_name , result , user )
498+ should_log , logged_sampling_rate , shadow_logged = self .__determine_sampling (EntityType .GATE , gate_name , result ,
499+ user )
494500
495501 if log_exposure and should_log :
496502 self ._logger .log_gate_exposure (
@@ -511,7 +517,7 @@ def __get_config(self, user: StatsigUser, config_name: str, log_exposure=True):
511517
512518 result = self ._evaluator .get_config (user , config_name )
513519 result .user = user
514- should_log , logged_sampling_rate , shadow_logged = self .__determine_sampling (" CONFIG" , config_name ,
520+ should_log , logged_sampling_rate , shadow_logged = self .__determine_sampling (EntityType . CONFIG , config_name ,
515521 result , user )
516522
517523 if log_exposure and should_log :
@@ -527,47 +533,53 @@ def __get_config(self, user: StatsigUser, config_name: str, log_exposure=True):
527533 )
528534 return result
529535
530- def __determine_sampling (self , type : str , name : str , result : _ConfigEvaluation ,
531- user : StatsigUser ) -> Tuple [
536+ def __determine_sampling (self , type : EntityType , name : str , result : _ConfigEvaluation , user : StatsigUser ,
537+ param_name = "" ) -> Tuple [
532538 bool , Optional [int ], Optional [str ]]: # should_log, logged_sampling_rate, shadow_logged
533539 try :
534540 shadow_should_log , logged_sampling_rate = True , None
535541 env = self ._options .get_sdk_environment_tier ()
536542 sampling_mode = _SDK_Configs .get_config_str_value ("sampling_mode" )
537- default_rule_id_sampling_rate = _SDK_Configs .get_config_int_value ("default_rule_id_sampling_rate " )
543+ special_case_sampling_rate = _SDK_Configs .get_config_int_value ("special_case_sampling_rate " )
538544
539545 if sampling_mode is None or sampling_mode == "none" or env != "production" :
540- return True , None , None
546+ return True , None , "logged"
541547
542- if result .rule_id == "default" and result . forward_all_exposures :
543- return True , None , None
548+ if result .forward_all_exposures :
549+ return True , None , "logged"
544550
545551 samplingSetKey = f"{ name } _{ result .rule_id } "
546552 if not self ._sampling_key_set .contains (samplingSetKey ):
547553 self ._sampling_key_set .add (samplingSetKey )
548- return True , None , None
554+ return True , None , "logged"
549555
550556 if result .sample_rate is not None :
551557 exposure_key = ""
552- if type == " GATE" :
558+ if type == EntityType . GATE :
553559 exposure_key = compute_dedupe_key_for_gate (name , result .rule_id , result .boolean_value ,
554560 user .user_id , user .custom_ids )
555- elif type == " CONFIG" :
561+ elif type == EntityType . CONFIG :
556562 exposure_key = compute_dedupe_key_for_config (name , result .rule_id , user .user_id , user .custom_ids )
563+ elif type == EntityType .LAYER :
564+ exposure_key = compute_dedupe_key_for_layer (name , result .allocated_experiment , param_name ,
565+ result .rule_id ,
566+ user .user_id , user .custom_ids )
557567 shadow_should_log = is_hash_in_sampling_rate (exposure_key , result .sample_rate )
558568 logged_sampling_rate = result .sample_rate
559569
560- if default_rule_id_sampling_rate is not None and result .rule_id == "default" :
561- shadow_should_log = is_hash_in_sampling_rate (name , default_rule_id_sampling_rate )
562- logged_sampling_rate = default_rule_id_sampling_rate
570+ special_case_rules = ["disabled" , "default" , "" ]
571+
572+ if result .rule_id in special_case_rules and special_case_sampling_rate is not None :
573+ shadow_should_log = is_hash_in_sampling_rate (name , special_case_sampling_rate )
574+ logged_sampling_rate = special_case_sampling_rate
563575
576+ shadow_logged = None if result .sample_rate is None else "logged" if shadow_should_log else "dropped"
564577 if sampling_mode == "on" :
565- return shadow_should_log , logged_sampling_rate , None
578+ return shadow_should_log , logged_sampling_rate , shadow_logged
566579 if sampling_mode == "shadow" :
567- shadow_logged = None if result .sample_rate is None else "logged" if shadow_should_log else "dropped"
568580 return True , logged_sampling_rate , shadow_logged
569581
570- return True , None , None
582+ return True , None , "logged"
571583 except Exception as e :
572584 self ._errorBoundary .log_exception ("__determine_sampling" , e , log_mode = "debug" )
573585 return True , None , None
0 commit comments