Skip to content

Commit 76e1279

Browse files
authored
Some bug fixes (#359)
- id list was falling back regardless if fallback option was enabled - response.text warning produce multiline logs in datadog, its not very informative anyways so removing - do not check store populated on local mode - do not sample override - in output logger unit test, log_process should have used debug like it does in normal output logger, so the number of logs are off - if using multi instance, StatsigServer.initialize() allow the options to be optional, if its none/incorrect type, create empty statsigOptions to not break downstream.
1 parent 50910bb commit 76e1279

File tree

7 files changed

+33
-17
lines changed

7 files changed

+33
-17
lines changed

statsig/http_worker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,9 @@ def request_task():
211211
globals.logger.warning(
212212
f"Request to {url} failed with code {response.status_code}"
213213
)
214-
globals.logger.warning(response.text)
215214
return response
216215
except Exception as err:
217-
globals.logger.debug(f"Request to {url} failed with error {err}")
216+
globals.logger.warning(f"Request to {url} failed with error {err}")
218217
if create_marker is not None:
219218
self.__diagnostics.add_marker(
220219
create_marker().end(
@@ -235,6 +234,7 @@ def request_task():
235234
"request:" + tag,
236235
err,
237236
{"timeoutMs": timeout * 1000, "httpMethod": method},
237+
log_mode="none",
238238
)
239239
return None
240240

statsig/spec_updater.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ def on_complete(id_lists: list, error: Exception):
250250
init_timeout = self._options.init_timeout
251251

252252
self._network.get_id_lists(on_complete, False, init_timeout)
253-
if result[0] is False:
253+
if result[0] is False and self._options.fallback_to_statsig_api:
254254
self._network.get_id_lists_fallback(on_complete, False, init_timeout)
255255

256256
except Exception as e:

statsig/statsig_error_boundary.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def log_exception(
7878
exception: Exception,
7979
extra: Optional[dict] = None,
8080
bypass_dedupe: bool = False,
81-
log_mode: Optional[str] = "warning", # warn/debug based on error severity
81+
log_mode: Optional[str] = "warning", # warn/debug/none based on error severity
8282
):
8383
try:
8484
stack_trace = traceback.format_exc()

statsig/statsig_network.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def get_dcs_fallback(
169169
init_timeout: Optional[int] = None,
170170
):
171171
if self.statsig_options.local_mode:
172-
globals.logger.warning("Local mode is enabled. Not fetching DCS.")
172+
globals.logger.warning("Local mode is enabled. Not fetching DCS with fallback.")
173173
return
174174
dcs_proxy = self.statsig_options.proxy_configs.get(NetworkEndpoint.DOWNLOAD_CONFIG_SPECS)
175175
is_proxy_dcs = (
@@ -198,7 +198,7 @@ def get_id_lists_fallback(
198198
init_timeout: Optional[int] = None,
199199
):
200200
if self.statsig_options.local_mode:
201-
globals.logger.warning("Local mode is enabled. Not fetching ID Lists.")
201+
globals.logger.warning("Local mode is enabled. Not fetching ID Lists with fallback.")
202202
return
203203
if not self.statsig_options.fallback_to_statsig_api:
204204
return

statsig/statsig_server.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,28 @@ def initialize(self, sdkKey: str, options: Optional[StatsigOptions] = None) -> I
7878
"Invalid key provided. You must use a Server Secret Key from the Statsig console."
7979
)
8080

81-
environment_tier = options.get_sdk_environment_tier() if isinstance(options, StatsigOptions) else 'unknown'
81+
if options is None or not isinstance(options, StatsigOptions):
82+
options = StatsigOptions()
83+
84+
environment_tier = options.get_sdk_environment_tier() or 'unknown'
8285
globals.logger.info(
8386
f"Initializing Statsig SDK (v{__version__}) instance. "
8487
f"Current environment tier: {environment_tier}."
8588
)
8689

8790
init_details = self._initialize_impl(sdkKey, options)
91+
self._post_init_logging(options, init_details)
92+
93+
return init_details
94+
95+
def _post_init_logging(self, options: StatsigOptions, init_details: InitializeDetails):
96+
if options.local_mode:
97+
if init_details.init_success:
98+
globals.logger.info(
99+
"Statsig SDK instance initialized in local mode. No data will be fetched from the Statsig servers.")
100+
else:
101+
globals.logger.error("Statsig SDK instance failed to initialize in local mode.")
102+
return
88103

89104
if init_details.init_success:
90105
if init_details.store_populated:
@@ -96,8 +111,6 @@ def initialize(self, sdkKey: str, options: Optional[StatsigOptions] = None) -> I
96111
else:
97112
globals.logger.error("Statsig SDK instance Initialized failed!")
98113

99-
return init_details
100-
101114
def _initialize_impl(self, sdk_key: str, options: Optional[StatsigOptions]):
102115
threw_error = False
103116
try:
@@ -601,6 +614,9 @@ def __determine_sampling(self, type: EntityType, name: str, result: _ConfigEvalu
601614
if result.forward_all_exposures:
602615
return True, None, None
603616

617+
if result.rule_id.endswith((':override', ':id_override')):
618+
return True, None, None
619+
604620
samplingSetKey = f"{name}_{result.rule_id}"
605621
if not self._sampling_key_set.contains(samplingSetKey):
606622
self._sampling_key_set.add(samplingSetKey)

tests/test_output_logger.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def __init__(self):
2020

2121
def log_process(self, process: str, msg: str):
2222
message = sanitize(f"{process}: {msg}")
23-
self.info(message)
23+
self.debug(message)
2424

2525
def debug(self, msg, *args, **kwargs):
2626
if self._logger.isEnabledFor(logging.DEBUG) and not self._disabled:
@@ -88,15 +88,15 @@ def test_initialize_timeout(self, mock_request):
8888
options = StatsigOptions(api=_network_stub.host, init_timeout=0.1, disable_diagnostics=True,
8989
custom_logger=logger)
9090
statsig.initialize("secret-key", options)
91-
self.assertGreater(len(logger._logs.get("info")), 3)
91+
self.assertGreaterEqual(len(logger._logs.get("info")), 2)
9292

9393
@patch('requests.request', side_effect=_network_stub.mock)
9494
def test_initialize_failed_to_load_network_info(self, mock_request):
9595
logger = MockOutputLogger()
9696
logger.set_log_level(LogLevel.INFO)
9797
options = StatsigOptions(api=_network_stub.host, disable_diagnostics=True, custom_logger=logger)
9898
statsig.initialize("secret-key", options)
99-
self.assertGreater(len(logger._logs.get("info")), 2)
99+
self.assertGreaterEqual(len(logger._logs.get("info")), 2)
100100
self.assertGreater(len(logger._logs.get("warning")), 0)
101101
failed_urls = logger.check_urls_for_secret('secret-key')
102102
self.assertEqual(len(failed_urls), 0)
@@ -119,7 +119,7 @@ def test_set_logging_level_debug(self, mock_request):
119119
options = StatsigOptions(api=_network_stub.host, disable_diagnostics=True, custom_logger=logger)
120120
statsig.initialize("secret-key", options)
121121
self.assertGreater(len(logger._logs.get("debug")), 0)
122-
self.assertGreater(len(logger._logs.get("info")), 2)
122+
self.assertGreater(len(logger._logs.get("info")), 0)
123123
self.assertGreater(len(logger._logs.get("warning")), 0)
124124
failed_urls = logger.check_urls_for_secret('secret-key')
125125
self.assertEqual(len(failed_urls), 0)

tests/test_statsig_error_boundary_usage.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import unittest
2+
from unittest.mock import patch
23

34
from statsig.dynamic_config import DynamicConfig
45
from statsig.layer import Layer
5-
from statsig.spec_updater import SpecUpdater
66
from statsig.statsig_event import StatsigEvent
7+
from statsig.statsig_options import StatsigOptions
78
from statsig.statsig_server import StatsigServer
89
from statsig.statsig_user import StatsigUser
9-
from unittest.mock import patch
1010

1111

1212
def mocked_post(*args, **kwargs):
@@ -63,12 +63,12 @@ def tearDown(self) -> None:
6363
def test_errors_with_initialize(self, mock_post):
6464
statsig = StatsigServer()
6565
TestStatsigErrorBoundaryUsage.requests = []
66-
statsig.initialize("secret-key", "_BAD_OPTIONS_")
66+
statsig.initialize("secret-key", StatsigOptions(proxy_configs="proxy_configs"))
6767

6868
self.assertEqual(len(_get_requests(statsig)), 1)
6969
trace = _get_requests(self._instance)[0]['body']['info']
7070
self.assertIn(
71-
"AttributeError: 'str' object has no attribute \'proxy_configs\'", trace)
71+
"AttributeError: \'str\' object has no attribute \'get\'", trace)
7272
self.assertTrue(statsig._initialized)
7373

7474
def test_errors_with_check_gate(self, mock_post):

0 commit comments

Comments
 (0)