# Path: slo_generator/utils.py
#     GCS_ENABLED = True
#     GCS_ENABLED = False
# LOGGER = logging.getLogger(__name__)
# def load_configs(path, ctx=os.environ, kind=None):
# def load_config(path, ctx=os.environ, kind=None):
# def parse_config(path=None, content=None, ctx=os.environ):
#     def replace_env_vars(content, ctx):
# def setup_logging():
# def get_human_time(timestamp, timezone=None):
# def get_exporters(config, spec):
# def get_backend(config, spec):
# def get_error_budget_policy(config, spec):
# def get_backend_cls(backend):
# def get_exporter_cls(exporter):
# def import_cls(cls_name, expected_type):
# def import_dynamic(package, name, prefix="class"):
# def capitalize(word):
# def snake_to_caml(word):
# def caml_to_snake(word):
# def dict_snake_to_caml(data):
# def apply_func_dict(data, func):
# def str2bool(string):
# def download_gcs_file(url):
# def decode_gcs_url(url):
# def get_files(source, extensions=['yaml', 'yml', 'json']):
# def get_target_path(source_dir, target_dir, relative_path, mkdir=True):
# def fmt_traceback(exc):
# 
# Path: slo_generator/compute.py
# def compute(slo_config,
#             config,
#             timestamp=None,
#             client=None,
#             do_export=False,
#             delete=False):
#     """Run pipeline to compute SLO, Error Budget and Burn Rate, and export the
#     results (if exporters are specified in the SLO config).
# 
#     Args:
#         slo_config (dict): SLO configuration.
#         config (dict): SLO Generator configuration.
#         timestamp (float, optional): UNIX timestamp. Defaults to now.
#         client (obj, optional): Existing metrics backend client.
#         do_export (bool, optional): Enable / Disable export. Default: False.
#         delete (bool, optional): Enable / Disable delete mode. Default: False.
#     """
#     start = time.time()
#     if timestamp is None:
#         timestamp = time.time()
# 
#     if slo_config is None:
#         LOGGER.error('SLO configuration is empty')
#         return []
# 
#     # Get exporters, backend and error budget policy
#     spec = slo_config['spec']
#     exporters = utils.get_exporters(config, spec)
#     default_exporters_spec = {
#         "exporters": config.get('default_exporters', [])
#     }
#     default_exporters = utils.get_exporters(config, default_exporters_spec)
#     exporters.extend(x for x in default_exporters if x not in exporters)
#     error_budget_policy = utils.get_error_budget_policy(config, spec)
#     backend = utils.get_backend(config, spec)
#     reports = []
#     for step in error_budget_policy['steps']:
#         report = SLOReport(config=slo_config,
#                            backend=backend,
#                            step=step,
#                            timestamp=timestamp,
#                            client=client,
#                            delete=delete)
#         json_report = report.to_json()
# 
#         if not report.valid:
#             LOGGER.error(report)
#             reports.append(json_report)
#             continue
# 
#         if delete:  # delete mode is enabled
#             continue
# 
#         LOGGER.info(report)
#         if exporters is not None and do_export is True:
#             errors = export(json_report, exporters)
#             json_report['errors'].extend(errors)
#         reports.append(json_report)
#     end = time.time()
#     run_duration = round(end - start, 1)
#     LOGGER.debug(pprint.pformat(reports))
#     LOGGER.info(f'Run finished successfully in {run_duration}s.')
#     return reports
# 
# Path: slo_generator/migrations/migrator.py
# def do_migrate(source,
#                target,
#                error_budget_policy_path,
#                exporters_path,
#                version,
#                quiet=False,
#                verbose=0):
# def exporters_v1tov2(exporters_paths, shared_config={}, quiet=False):
# def ebp_v1tov2(ebp_paths, shared_config={}, quiet=False):
# def slo_config_v1tov2(slo_config,
#                       shared_config={},
#                       shared_exporters=[],
#                       quiet=False,
#                       verbose=0):
# def report_v2tov1(report):
# def get_random_suffix():
# def add_to_shared_config(new_obj,
#                          shared_config,
#                          section,
#                          key=None,
#                          quiet=False):
# def detect_config_version(config):
# def peek(iterable):
#     def write_line_break(self, data=None):
# class CustomDumper(yaml.RoundTripDumper):
# 
# Path: slo_generator/constants.py
# LATEST_MAJOR_VERSION = 'v2'


import logging
import os
import sys
import time
import click
from pathlib import Path
from pkg_resources import get_distribution
from slo_generator import utils
from slo_generator.compute import compute as _compute
from slo_generator.migrations import migrator
from slo_generator.constants import LATEST_MAJOR_VERSION
    from functions_framework._cli import _cli
              default='config.yaml',
              show_default=True,
              help='slo-generator config path')
@click.option('--export',
              '-e',
              is_flag=True,
              help='Export SLO report to exporters')
@click.option('--delete',
              '-d',
              is_flag=True,
              help='Delete mode (used for backends with SLO APIs)')
@click.option('--timestamp',
              '-t',
              type=float,
              default=time.time(),
              help='End timestamp for query.')
def compute(slo_config, config, export, delete, timestamp):
    """Compute SLO report."""
    start = time.time()

    # Load slo-generator config
    LOGGER.debug(f"Loading slo-generator config from {config}")
    config_dict = utils.load_config(config)

    # Load SLO config(s)
    if Path(slo_config).is_dir():
        slo_configs = utils.load_configs(slo_config,
                                         kind='ServiceLevelObjective')
    else:
        slo_configs = [

# Path: slo_generator/utils.py
#     GCS_ENABLED = True
#     GCS_ENABLED = False
# LOGGER = logging.getLogger(__name__)
# def load_configs(path, ctx=os.environ, kind=None):
# def load_config(path, ctx=os.environ, kind=None):
# def parse_config(path=None, content=None, ctx=os.environ):
#     def replace_env_vars(content, ctx):
# def setup_logging():
# def get_human_time(timestamp, timezone=None):
# def get_exporters(config, spec):
# def get_backend(config, spec):
# def get_error_budget_policy(config, spec):
# def get_backend_cls(backend):
# def get_exporter_cls(exporter):
# def import_cls(cls_name, expected_type):
# def import_dynamic(package, name, prefix="class"):
# def capitalize(word):
# def snake_to_caml(word):
# def caml_to_snake(word):
# def dict_snake_to_caml(data):
# def apply_func_dict(data, func):
# def str2bool(string):
# def download_gcs_file(url):
# def decode_gcs_url(url):
# def get_files(source, extensions=['yaml', 'yml', 'json']):
# def get_target_path(source_dir, target_dir, relative_path, mkdir=True):
# def fmt_traceback(exc):
# 
# Path: slo_generator/compute.py
# def compute(slo_config,
#             config,
#             timestamp=None,
#             client=None,
#             do_export=False,
#             delete=False):
#     """Run pipeline to compute SLO, Error Budget and Burn Rate, and export the
#     results (if exporters are specified in the SLO config).
# 
#     Args:
#         slo_config (dict): SLO configuration.
#         config (dict): SLO Generator configuration.
#         timestamp (float, optional): UNIX timestamp. Defaults to now.
#         client (obj, optional): Existing metrics backend client.
#         do_export (bool, optional): Enable / Disable export. Default: False.
#         delete (bool, optional): Enable / Disable delete mode. Default: False.
#     """
#     start = time.time()
#     if timestamp is None:
#         timestamp = time.time()
# 
#     if slo_config is None:
#         LOGGER.error('SLO configuration is empty')
#         return []
# 
#     # Get exporters, backend and error budget policy
#     spec = slo_config['spec']
#     exporters = utils.get_exporters(config, spec)
#     default_exporters_spec = {
#         "exporters": config.get('default_exporters', [])
#     }
#     default_exporters = utils.get_exporters(config, default_exporters_spec)
#     exporters.extend(x for x in default_exporters if x not in exporters)
#     error_budget_policy = utils.get_error_budget_policy(config, spec)
#     backend = utils.get_backend(config, spec)
#     reports = []
#     for step in error_budget_policy['steps']:
#         report = SLOReport(config=slo_config,
#                            backend=backend,
#                            step=step,
#                            timestamp=timestamp,
#                            client=client,
#                            delete=delete)
#         json_report = report.to_json()
# 
#         if not report.valid:
#             LOGGER.error(report)
#             reports.append(json_report)
#             continue
# 
#         if delete:  # delete mode is enabled
#             continue
# 
#         LOGGER.info(report)
#         if exporters is not None and do_export is True:
#             errors = export(json_report, exporters)
#             json_report['errors'].extend(errors)
#         reports.append(json_report)
#     end = time.time()
#     run_duration = round(end - start, 1)
#     LOGGER.debug(pprint.pformat(reports))
#     LOGGER.info(f'Run finished successfully in {run_duration}s.')
#     return reports
# 
# Path: slo_generator/migrations/migrator.py
# def do_migrate(source,
#                target,
#                error_budget_policy_path,
#                exporters_path,
#                version,
#                quiet=False,
#                verbose=0):
# def exporters_v1tov2(exporters_paths, shared_config={}, quiet=False):
# def ebp_v1tov2(ebp_paths, shared_config={}, quiet=False):
# def slo_config_v1tov2(slo_config,
#                       shared_config={},
#                       shared_exporters=[],
#                       quiet=False,
#                       verbose=0):
# def report_v2tov1(report):
# def get_random_suffix():
# def add_to_shared_config(new_obj,
#                          shared_config,
#                          section,
#                          key=None,
#                          quiet=False):
# def detect_config_version(config):
# def peek(iterable):
#     def write_line_break(self, data=None):
# class CustomDumper(yaml.RoundTripDumper):
# 
# Path: slo_generator/constants.py
# LATEST_MAJOR_VERSION = 'v2'


# Path: slo_generator/cli.py
import logging
import os
import sys
import time
import click
from pathlib import Path
from pkg_resources import get_distribution
from slo_generator import utils
from slo_generator.compute import compute as _compute
from slo_generator.migrations import migrator
from slo_generator.constants import LATEST_MAJOR_VERSION
    from functions_framework._cli import _cli

              default='config.yaml',
              show_default=True,
              help='slo-generator config path')
@click.option('--export',
              '-e',
              is_flag=True,
              help='Export SLO report to exporters')
@click.option('--delete',
              '-d',
              is_flag=True,
              help='Delete mode (used for backends with SLO APIs)')
@click.option('--timestamp',
              '-t',
              type=float,
              default=time.time(),
              help='End timestamp for query.')
def compute(slo_config, config, export, delete, timestamp):
    """Compute SLO report."""
    start = time.time()

    # Load slo-generator config
    LOGGER.debug(f"Loading slo-generator config from {config}")
    config_dict = utils.load_config(config)

    # Load SLO config(s)
    if Path(slo_config).is_dir():
        slo_configs = utils.load_configs(slo_config,
                                         kind='ServiceLevelObjective')
    else:
        slo_configs = [

            utils.load_config(slo_config, kind='ServiceLevelObjective')