diff --git a/statsig/__init__.py b/statsig/__init__.py index 657784c..b5782a1 100644 --- a/statsig/__init__.py +++ b/statsig/__init__.py @@ -10,4 +10,5 @@ from .statsig_environment_tier import StatsigEnvironmentTier from .evaluator import _Evaluator from .interface_data_store import IDataStore +from .sdk_flags import _SDKFlags from .version import __version__ diff --git a/statsig/sdk_flags.py b/statsig/sdk_flags.py new file mode 100644 index 0000000..e2f24ba --- /dev/null +++ b/statsig/sdk_flags.py @@ -0,0 +1,10 @@ +class _SDKFlags: + _flags = {} + + @staticmethod + def set_flags(new_flags): + _SDKFlags._flags = new_flags + + @staticmethod + def on(key): + return _SDKFlags._flags.get(key, False) is True diff --git a/statsig/spec_store.py b/statsig/spec_store.py index 493ad4c..68c0845 100644 --- a/statsig/spec_store.py +++ b/statsig/spec_store.py @@ -3,6 +3,7 @@ from concurrent.futures import ThreadPoolExecutor, wait from typing import Optional +from .sdk_flags import _SDKFlags from .utils import djb2_hash from .evaluation_details import EvaluationReason @@ -177,6 +178,10 @@ def get_parsed_specs(key: str): self._layers = new_layers self._experiment_to_layer = new_experiment_to_layer self.last_update_time = specs_json.get("time", 0) + + flags = specs_json.get("sdk_flags", {}) + _SDKFlags.set_flags(flags) + sampling_rate = specs_json.get("diagnostics", {}) Diagnostics.set_sampling_rate(sampling_rate) @@ -384,6 +389,7 @@ def _download_id_lists_process(self, server_id_lists): self._error_boundary.log_exception("_download_id_lists_process", e) finally: Diagnostics.mark().get_id_list_sources().process().end({'success': not threw_error}) + def _download_single_id_list( self, url, list_name, local_list, all_lists, start_index): resp = self._network.get_request( diff --git a/statsig/statsig_network.py b/statsig/statsig_network.py index 5ff8736..8e6f1a6 100644 --- a/statsig/statsig_network.py +++ b/statsig/statsig_network.py @@ -5,6 +5,7 @@ import gzip import requests from .diagnostics import Diagnostics +from .sdk_flags import _SDKFlags from .statsig_options import StatsigOptions from .statsig_error_boundary import _StatsigErrorBoundary @@ -84,21 +85,30 @@ def retryable_request(self, endpoint, payload, log_on_exception=False, retry=0): if self.__local_mode: return None - headers = self._create_headers({ - 'STATSIG-RETRY': str(retry), - 'Content-Encoding': 'gzip', - }) - payload_data = self._verify_json_payload(payload, endpoint) if payload_data is None: return None try: - compressed_data = self._zip_payload(payload_data) + disable_compression = _SDKFlags.on("stop_log_event_compression") + + headers = self._create_headers({ + 'STATSIG-RETRY': str(retry), + }) + + if not disable_compression: + headers['Content-Encoding'] = 'gzip' + response = requests.post( - self.__api + endpoint, data=compressed_data, headers=headers, timeout=self.__req_timeout) + self.__api + endpoint, + data=payload_data if disable_compression else self._zip_payload(payload_data), + headers=headers, + timeout=self.__req_timeout + ) + if response.status_code in self.__RETRY_CODES: return payload + if response.status_code >= 300: globals.logger.warning( "Request to %s failed with code %d", endpoint, response.status_code) diff --git a/tests/test_sdk_flags.py b/tests/test_sdk_flags.py new file mode 100644 index 0000000..4faecd9 --- /dev/null +++ b/tests/test_sdk_flags.py @@ -0,0 +1,21 @@ +import unittest + +from statsig import _SDKFlags + + +class TestSDKFlags(unittest.TestCase): + + def test_empty(self): + self.assertEqual(_SDKFlags.on("not_a_flag"), False) + + def test_malformed(self): + _SDKFlags.set_flags({"bad_flag": 1}) + self.assertEqual(_SDKFlags.on("bad_flag"), False) + + def test_flag_set(self): + _SDKFlags.set_flags({"a_flag": True}) + self.assertEqual(_SDKFlags.on("a_flag"), True) + + +if __name__ == '__main__': + unittest.main()