99from .statsig_network import _StatsigNetwork
1010from .statsig_options import StatsigOptions
1111from .thread_util import spawn_background_thread , THREAD_JOIN_TIMEOUT
12+ from .diagnostics import _Diagnostics
1213from .utils import logger
1314
1415RULESETS_SYNC_INTERVAL = 10
1516IDLISTS_SYNC_INTERVAL = 60
1617STORAGE_ADAPTER_KEY = "statsig.cache"
1718SYNC_OUTDATED_MAX_S = 120
1819
20+
1921def _is_specs_json_valid (specs_json ):
2022 if specs_json is None or specs_json .get ("time" ) is None :
2123 return False
@@ -30,7 +32,8 @@ class _SpecStore:
3032 _background_download_id_lists : Optional [threading .Thread ]
3133
3234 def __init__ (self , network : _StatsigNetwork , options : StatsigOptions , statsig_metadata : dict ,
33- error_boundary : _StatsigErrorBoundary , shutdown_event : threading .Event ):
35+ error_boundary : _StatsigErrorBoundary , shutdown_event : threading .Event ,
36+ init_diagnostics : _Diagnostics ):
3437 self .last_update_time = 0
3538 self .initial_update_time = 0
3639 self .init_reason = EvaluationReason .uninitialized
@@ -44,6 +47,7 @@ def __init__(self, network: _StatsigNetwork, options: StatsigOptions, statsig_me
4447 self ._background_download_configs = None
4548 self ._background_download_id_lists = None
4649 self ._sync_failure_count = 0
50+ self ._init_diagnostics = init_diagnostics
4751
4852 self ._configs = {}
4953 self ._gates = {}
@@ -119,14 +123,15 @@ def _initialize_specs(self):
119123 if self ._options .bootstrap_values is not None :
120124 logger .warning (
121125 "data_store gets priority over bootstrap_values. bootstrap_values will be ignored" )
122-
123126 self ._load_config_specs_from_storage_adapter ()
124127 if self .last_update_time == 0 :
125128 self ._log_process ("Retrying with network..." )
126129 self ._download_config_specs ()
127130
128131 elif self ._options .bootstrap_values is not None :
132+ self ._init_diagnostics .mark ("bootstrap" , "start" , "load" )
129133 self ._bootstrap_config_specs ()
134+ self ._init_diagnostics .mark ("bootstrap" , "end" , "load" )
130135
131136 else :
132137 self ._download_config_specs ()
@@ -202,22 +207,28 @@ def _download_config_specs(self):
202207 log_on_exception = True
203208 self ._sync_failure_count = 0
204209
205- specs = self ._network .post_request ("download_config_specs" , {
206- "statsigMetadata" : self ._statsig_metadata ,
207- "sinceTime" : self .last_update_time ,
208- }, log_on_exception )
210+ try :
211+ specs = self ._network .post_request ("download_config_specs" , {
212+ "statsigMetadata" : self ._statsig_metadata ,
213+ "sinceTime" : self .last_update_time ,
214+ }, log_on_exception , self ._init_diagnostics )
215+ except Exception as e :
216+ raise e
209217
210218 if specs is None :
211219 self ._sync_failure_count += 1
212220 return
213221
222+ self ._init_diagnostics .mark ("download_config_specs" , "start" , "process" )
214223 if not _is_specs_json_valid (specs ):
224+ self ._init_diagnostics .mark ("download_config_specs" , "end" , "process" , False )
215225 return
216226
217227 self ._log_process ("Done loading specs" )
218228 if self ._process_specs (specs ):
219229 self ._save_to_storage_adapter (specs )
220230 self .init_reason = EvaluationReason .network
231+ self ._init_diagnostics .mark ("download_config_specs" , "end" , "process" , self .init_reason == EvaluationReason .network )
221232
222233 def _save_to_storage_adapter (self , specs ):
223234 if not _is_specs_json_valid (specs ):
@@ -232,6 +243,7 @@ def _save_to_storage_adapter(self, specs):
232243 self ._options .data_store .set (STORAGE_ADAPTER_KEY , json .dumps (specs ))
233244
234245 def _load_config_specs_from_storage_adapter (self ):
246+ self ._init_diagnostics .mark ("bootstrap" , "start" , "load" )
235247 self ._log_process ("Loading specs from adapter" )
236248 if self ._options .data_store is None :
237249 return
@@ -254,6 +266,7 @@ def _load_config_specs_from_storage_adapter(self):
254266 self ._log_process ("Done loading specs" )
255267 if self ._process_specs (cache ):
256268 self .init_reason = EvaluationReason .data_adapter
269+ self ._init_diagnostics .mark ("bootstrap" , "end" , "load" )
257270
258271 def _spawn_bg_download_id_lists (self ):
259272 self ._background_download_id_lists = spawn_background_thread (self ._sync , (
@@ -264,9 +277,11 @@ def _download_id_lists(self):
264277 try :
265278 server_id_lists = self ._network .post_request ("get_id_lists" , {
266279 "statsigMetadata" : self ._statsig_metadata ,
267- })
280+ }, False , self ._init_diagnostics )
281+
268282 if server_id_lists is None :
269283 return
284+ self ._init_diagnostics .mark ("get_id_lists" , "start" , "process" )
270285
271286 local_id_lists = self ._id_lists
272287 workers = []
@@ -321,7 +336,10 @@ def _download_id_lists(self):
321336 # remove any list that has been deleted
322337 for list_name in deleted_lists :
323338 local_id_lists .pop (list_name , None )
339+ self ._init_diagnostics .mark ("get_id_lists" , "end" , "process" , True )
340+
324341 except Exception as e :
342+ self ._init_diagnostics .mark ("get_id_lists" , "end" , "process" , False )
325343 self ._error_boundary .log_exception (e )
326344
327345 def _download_single_id_list (
0 commit comments