# 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/constants.py
# COLORED_OUTPUT = int(os.environ.get("COLORED_OUTPUT", "0"))
# 
# MIN_VALID_EVENTS = int(os.environ.get("MIN_VALID_EVENTS", "1"))
# 
# NO_DATA = -1
# 
# class Colors:
#     """Colors for console output."""
#     HEADER = '\033[95m'
#     OKBLUE = '\033[94m'
#     OKGREEN = '\033[92m'
#     WARNING = '\033[93m'
#     FAIL = '\033[91m'
#     ENDC = '\033[0m'
#     BOLD = '\033[1m'
#     UNDERLINE = '\033[4m'


import logging
from dataclasses import asdict, dataclass, fields, field
from slo_generator import utils
from slo_generator.constants import (COLORED_OUTPUT, MIN_VALID_EVENTS, NO_DATA,
                                     Colors)
            obj: Backend data.
        """
        # Grab backend class and method dynamically.
        cls_name = backend.get('class')
        method = config['spec']['method']
        excluded_keys = ['class', 'service_level_indicator', 'name']
        backend_cfg = {
            k: v for k, v in backend.items() if k not in excluded_keys
        }
        cls = utils.get_backend_cls(cls_name)
        if not cls:
            LOGGER.warning(f'{self.info} | Backend {cls_name} not loaded.')
            self.valid = False
            return None
        instance = cls(client=client, **backend_cfg)
        method = getattr(instance, method)
        LOGGER.debug(f'{self.info} | '
                     f'Using backend {cls_name}.{method.__name__} (from '
                     f'SLO config file).')

        # Delete mode activation.
        if delete and hasattr(instance, 'delete'):
            method = instance.delete
            LOGGER.info(f'{self.info} | Delete mode enabled.')

        # Run backend method and return results.
        try:
            data = method(self.timestamp, self.window, config)
            LOGGER.debug(f'{self.info} | Backend response: {data}')
        except Exception as exc:  # pylint:disable=broad-except

# 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/constants.py
# COLORED_OUTPUT = int(os.environ.get("COLORED_OUTPUT", "0"))
# 
# MIN_VALID_EVENTS = int(os.environ.get("MIN_VALID_EVENTS", "1"))
# 
# NO_DATA = -1
# 
# class Colors:
#     """Colors for console output."""
#     HEADER = '\033[95m'
#     OKBLUE = '\033[94m'
#     OKGREEN = '\033[92m'
#     WARNING = '\033[93m'
#     FAIL = '\033[91m'
#     ENDC = '\033[0m'
#     BOLD = '\033[1m'
#     UNDERLINE = '\033[4m'


# Path: slo_generator/report.py
import logging
from dataclasses import asdict, dataclass, fields, field
from slo_generator import utils
from slo_generator.constants import (COLORED_OUTPUT, MIN_VALID_EVENTS, NO_DATA,
                                     Colors)

            obj: Backend data.
        """
        # Grab backend class and method dynamically.
        cls_name = backend.get('class')
        method = config['spec']['method']
        excluded_keys = ['class', 'service_level_indicator', 'name']
        backend_cfg = {
            k: v for k, v in backend.items() if k not in excluded_keys
        }
        cls = utils.get_backend_cls(cls_name)
        if not cls:
            LOGGER.warning(f'{self.info} | Backend {cls_name} not loaded.')
            self.valid = False
            return None
        instance = cls(client=client, **backend_cfg)
        method = getattr(instance, method)
        LOGGER.debug(f'{self.info} | '
                     f'Using backend {cls_name}.{method.__name__} (from '
                     f'SLO config file).')

        # Delete mode activation.
        if delete and hasattr(instance, 'delete'):
            method = instance.delete
            LOGGER.info(f'{self.info} | Delete mode enabled.')

        # Run backend method and return results.
        try:
            data = method(self.timestamp, self.window, config)
            LOGGER.debug(f'{self.info} | Backend response: {data}')
        except Exception as exc:  # pylint:disable=broad-except

            self.errors.append(utils.fmt_traceback(exc))