From 54c03ab465bfcce01d44b79d4e1c88e898e2d820 Mon Sep 17 00:00:00 2001 From: Marc PERREAUT Date: Thu, 8 Jun 2023 14:16:01 +0200 Subject: [PATCH] Avoid streaming of ProviderTagSelector evaluation errors (#17) * Fixed typing issue * Avoid streaming of ProviderTagSelector evaluation errors * Version 1.0.4 --- cloud_cost_allocation/cost_items.py | 34 +++++++++++++++---- cloud_cost_allocation/writer/base_writer.py | 4 +-- .../writer/csv_allocated_cost_writer.py | 2 +- setup.py | 2 +- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/cloud_cost_allocation/cost_items.py b/cloud_cost_allocation/cost_items.py index da927e5..ea106ab 100644 --- a/cloud_cost_allocation/cost_items.py +++ b/cloud_cost_allocation/cost_items.py @@ -564,6 +564,12 @@ def compute_provider_tag_selector_amounts(self, amount_to_allocation_key_indexes for item in self.cost_items: item.nb_matching_provider_tag_selectors = 0 + # Build evaluation error dict, used to avoid error streaming in case of incorrect provider tag + # selector expression + # Key = date, provider service, provider instance, provider tag selector, expression + # Value = count of errors + evaluation_error_dict = {} + # Compute raw costs of non-default provider tag selectors, by checking matching items total_provider_tag_selector_raw_amounts = [0.0] * nb_amounts total_provider_tag_selector_raw_product_amounts = [0.0] * nb_amounts @@ -584,12 +590,14 @@ def compute_provider_tag_selector_amounts(self, amount_to_allocation_key_indexes eval_true = eval(provider_tag_selector_amount.selector, eval_globals_dict, {}) except: exception = sys.exc_info()[0] - error("Caught exception '" + str(exception) + - "' while evaluating provider tag selector '" + - provider_tag_selector_amount.selector + - "' for provider service '" + - self.service + - "'") + error_key =\ + cost_item.date_str + chr(10) + self.service + chr(10) + self.instance + chr(10) +\ + provider_tag_selector_amount.selector + chr(10) + str(exception) + if error_key in evaluation_error_dict: + error_count = evaluation_error_dict[error_key] + else: + error_count = 0 + evaluation_error_dict[error_key] = error_count + 1 # If item matches provider tag selector, update raw amounts of the provider tag selector if eval_true: @@ -600,6 +608,20 @@ def compute_provider_tag_selector_amounts(self, amount_to_allocation_key_indexes total_provider_tag_selector_raw_product_amounts, amount_to_allocation_key_indexes) + # Log evaluation errors + for error_key, error_count in evaluation_error_dict.items(): + error_fields = error_key.split(chr(10)) + date_str = error_fields[0] + provider_service = error_fields[1] + provider_instance = error_fields[2] + provider_tag_selector = error_fields[3] + exception = error_fields[4] + error("Caught exception '" + exception + "' " + str(error_count) + " times " + + "when evaluating ProviderTagSelector '" + provider_tag_selector + + "' of ProviderService '" + provider_service + + "' and of ProviderInstance '" + provider_instance + "'" + + ", for date " + date_str) + # Compute the raw amounts of the default provider tag selector if '' in self.provider_tag_selector_amounts: default_provider_tag_selector = self.provider_tag_selector_amounts[''] diff --git a/cloud_cost_allocation/writer/base_writer.py b/cloud_cost_allocation/writer/base_writer.py index a6edc75..560db7b 100644 --- a/cloud_cost_allocation/writer/base_writer.py +++ b/cloud_cost_allocation/writer/base_writer.py @@ -16,11 +16,11 @@ class GenericWriter(ABC): __slots__ = ( 'config', # type: Config - 'service_instances', # type: ServiceInstance + 'service_instances', # type: dict[ServiceInstance] 'exporters', # type: dict[type -> method] ) - def __init__(self, service_instances: list[ServiceInstance], config: Config): + def __init__(self, service_instances: dict[ServiceInstance], config: Config): ''' Constructor ''' diff --git a/cloud_cost_allocation/writer/csv_allocated_cost_writer.py b/cloud_cost_allocation/writer/csv_allocated_cost_writer.py index 86e35d7..329dc09 100644 --- a/cloud_cost_allocation/writer/csv_allocated_cost_writer.py +++ b/cloud_cost_allocation/writer/csv_allocated_cost_writer.py @@ -14,7 +14,7 @@ class CSV_AllocatedCostWriter(GenericWriter): classdocs ''' - def __init__(self, service_instances: list[ServiceInstance], config: Config): + def __init__(self, service_instances: dict[ServiceInstance], config: Config): super().__init__(service_instances, config) def get_headers(self) -> list[str]: diff --git a/setup.py b/setup.py index 0278fac..bf908ac 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ # Setup setup( name='cloud-cost-allocation', - version='1.0.3', + version='1.0.4', description='Python library for shared, hierarchical cost allocation based on user-defined usage metrics.', long_description=readme, long_description_content_type='text/markdown',