def main(): """slo-generator CLI entrypoint.""" utils.setup_logging() args = parse_args(sys.argv[1:]) export = args.export # Load error budget policy error_budget_path = utils.normalize(args.error_budget_policy) LOGGER.debug(f"Loading Error Budget config from {error_budget_path}") error_budget_policy = utils.parse_config(error_budget_path) # Parse SLO folder for configs slo_config = args.slo_config if os.path.isfile(slo_config): slo_config_paths = [args.slo_config] else: slo_config_folder = utils.normalize(slo_config) slo_config_paths = glob.glob(f'{slo_config_folder}/slo_*.yaml') # Abort if configs are not found if not slo_config_paths: LOGGER.error( f'No SLO configs found in SLO folder {slo_config_folder}.') # Load SLO configs and compute SLO reports for cfg in slo_config_paths: slo_config_path = utils.normalize(cfg) LOGGER.debug(f'Loading SLO config from {slo_config_path}') slo_config = utils.parse_config(slo_config_path) compute(slo_config, error_budget_policy, do_export=export)
def test_compute_ssm_delete_export(self, *mocks): for config in SLO_CONFIGS_SDSM: with self.subTest(config=config): compute(config, ERROR_BUDGET_POLICY, delete=True, do_export=True)
def main(data, context): print("Running SLO computations:") print("SLO Config: %s" % pprint.pformat(slo_config)) print("Error Budget Policy: %s" % pprint.pformat(error_budget_policy)) compute.compute( slo_config, error_budget_policy, timestamp=None, client=None, do_export=True)
def main(): args = parse_args(sys.argv[1:]) slo_config_path = utils.normalize(args.slo_config) error_budget_path = utils.normalize(args.error_budget_policy) export = args.export LOGGER.info("Loading SLO config from %s" % slo_config_path) LOGGER.info("Loading Error Budget config from %s" % error_budget_path) with open(slo_config_path, 'r') as f: slo_config = yaml.safe_load(f) with open(error_budget_path, 'r') as f: error_budget_policy = yaml.safe_load(f) compute(slo_config, error_budget_policy, do_export=export)
def test_compute_dummy_obj(self): results = compute(slo_config=self.slo_config, error_budget_policy=self.error_budget_policy, backend_obj=DummySLOBackend(), backend_method='dummy_slo_function') results = list(results) pprint.pprint(results)
def cli(args): """Main CLI function. Args: args (Namespace): Argparsed CLI parameters. Returns: dict: Dict of all reports indexed by config file path. """ utils.setup_logging() export = args.export delete = args.delete timestamp = args.timestamp start = time.time() # Load error budget policy LOGGER.debug( f"Loading Error Budget config from {args.error_budget_policy}") eb_path = utils.normalize(args.error_budget_policy) eb_policy = utils.parse_config(eb_path) # Parse SLO folder for configs slo_configs = utils.list_slo_configs(args.slo_config) if not slo_configs: LOGGER.error(f'No SLO configs found in SLO folder {args.slo_config}.') # Load SLO configs and compute SLO reports all_reports = {} for path in slo_configs: slo_config_name = path.split("/")[-1] LOGGER.debug(f'Loading SLO config "{slo_config_name}"') slo_config = utils.parse_config(path) reports = compute(slo_config, eb_policy, timestamp=timestamp, do_export=export, delete=delete) all_reports[path] = reports end = time.time() duration = round(end - start, 1) LOGGER.info(f'Run summary | SLO Configs: {len(slo_configs)} | ' f'Error Budget Policy Steps: {len(eb_policy)} | ' f'Total: {len(slo_configs) * len(eb_policy)} | ' f'Duration: {duration}s') return all_reports
def test_slo_config(name): slo_config_path = utils.get_slo_config(name)['_path'] ebp_config_path = os.path.abspath(constants.ERROR_BUDGET_POLICY_PATH) try: from slo_generator.utils import parse_config from slo_generator.compute import compute slo_config = parse_config(slo_config_path) ebp_config = parse_config(ebp_config_path) timestamp = time.time() reports = compute(slo_config, ebp_config, timestamp=timestamp, do_export=False) return {"success": True, "data": reports} except Exception as e: app.logger.exception(e) return { "success": False, "errorMessage": f"Test failed: {repr(e)}", "traceback": traceback.format_exc() }
def test_compute_elasticsearch(self): for config in SLO_CONFIGS_ES: with self.subTest(config=config): compute(config, ERROR_BUDGET_POLICY)
def test_compute_prometheus(self): for config in SLO_CONFIGS_PROM: with self.subTest(config=config): compute(config, ERROR_BUDGET_POLICY)
def test_compute_ssm(self, *mocks): for config in SLO_CONFIGS_SDSM: with self.subTest(config=config): compute(config, ERROR_BUDGET_POLICY)
def test_compute_stackdriver(self, mock): for config in SLO_CONFIGS_SD: with self.subTest(config=config): compute(config, ERROR_BUDGET_POLICY)
def test_compute_dynatrace(self, mock): for config in SLO_CONFIGS_DT: with self.subTest(config=config): compute(config, ERROR_BUDGET_POLICY)
def test_compute_datadog(self): for config in SLO_CONFIGS_DD: with self.subTest(config=config): compute(config, ERROR_BUDGET_POLICY)
def test_compute_dummy_method(self): results = compute(slo_config=self.slo_config, error_budget_policy=self.error_budget_policy, backend_method=dummy_slo_function) results = list(results) pprint.pprint(results)
def test_compute_exponential(self): channel = self.make_grpc_stub(nresp=2 * len(self.error_budget_policy)) patch = mock.patch("google.api_core.grpc_helpers.create_channel") with patch as create_channel: create_channel.return_value = channel compute(self.slo_config_exp, self.error_budget_policy)