From ee0fc15bbaa3753d11f765d271c96c2b62f07079 Mon Sep 17 00:00:00 2001 From: Jesse S Date: Thu, 18 Apr 2024 20:11:29 -0700 Subject: [PATCH] feat: TOOLS-2893 support new 7.1 p-index memory budget config/metrics (#281) --- lib/utils/common.py | 45 ++++++++++++++++++++++----- lib/view/sheet/decleration.py | 2 +- lib/view/templates.py | 33 ++++++++++++++------ test/unit/utils/test_common.py | 56 ++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 18 deletions(-) diff --git a/lib/utils/common.py b/lib/utils/common.py index ac671a6b..5d13d58f 100644 --- a/lib/utils/common.py +++ b/lib/utils/common.py @@ -1670,7 +1670,11 @@ def _format_ns_stop_writes_metrics( service_stats, ns_stats, ): + # Notes for adding new stop-writes metrics: + # - The threshold values should be in the same units as the usage values. + for node in service_stats: + # Gather global stats relevant to namespace level stop-writes cluster_clock_skew_ms: int | None = util.get_value_from_dict( service_stats[node], "cluster_clock_skew_ms", @@ -1802,7 +1806,9 @@ def _format_ns_stop_writes_metrics( ) if usage is not None and threshold is not None and bytes_total is not None: - threshold = bytes_total * (threshold / 100) + threshold = bytes_total * ( + threshold / 100 + ) # threshold units should match metrics units (bytes) sw = _is_stop_writes_cause(usage, threshold, stop_writes) _create_stop_writes_entry( stop_writes_metrics[node], @@ -1827,7 +1833,30 @@ def _format_ns_stop_writes_metrics( ) if usage is not None and threshold is not None and bytes_total is not None: - threshold = bytes_total * (threshold / 100) + threshold = bytes_total * ( + threshold / 100 + ) # threshold units should match metrics units (bytes) + sw = _is_stop_writes_cause(usage, threshold, stop_writes) + _create_stop_writes_entry( + stop_writes_metrics[node], + metric, + usage, + sw, + threshold, + config=config, + namespace=ns, + ) + + metric = "index_used_bytes" + config = "indexes-memory-budget" + usage = util.get_value_from_dict( + stats, metric, default_value=None, return_type=int + ) + threshold = util.get_value_from_dict( + stats, config, default_value=None, return_type=int + ) + + if usage is not None and threshold is not None: sw = _is_stop_writes_cause(usage, threshold, stop_writes) _create_stop_writes_entry( stop_writes_metrics[node], @@ -3009,11 +3038,13 @@ def get_collectinfo_path(timestamp, output_prefix=""): if output_prefix: aslogdir_prefix = "%s%s" % ( str(output_prefix), - "_" - if output_prefix - and not output_prefix.endswith("-") - and not output_prefix.endswith("_") - else "", + ( + "_" + if output_prefix + and not output_prefix.endswith("-") + and not output_prefix.endswith("_") + else "" + ), ) cf_path_info = CollectinfoPathInfo() diff --git a/lib/view/sheet/decleration.py b/lib/view/sheet/decleration.py index 96546fd7..d13c4020 100644 --- a/lib/view/sheet/decleration.py +++ b/lib/view/sheet/decleration.py @@ -626,7 +626,7 @@ def do_project(self, sheet, sources): den = self.denominator_projector(sheet, sources) if den == 0: - return 0 + return None return num / den diff --git a/lib/view/templates.py b/lib/view/templates.py index a3dfd279..23168c9a 100644 --- a/lib/view/templates.py +++ b/lib/view/templates.py @@ -103,11 +103,17 @@ def weighted_avg(values: Iterable[float], weights: Iterable[float]): """ weights_total = 0.0 values_total = 0.0 + itr = 0 for v, w in zip(values, weights): weighted_value = v * w values_total += weighted_value weights_total += w + itr += 1 + + if itr == 0: + # Prevents us from printing zero if there are no elements to average. + return None if not weights_total: return 0.0 @@ -145,9 +151,11 @@ def weighted_avg(values: Iterable[float], weights: Iterable[float]): "Node ID", Projectors.String("node_ids", None), converter=( - lambda edata: "*" + edata.value - if edata.value == edata.common["principal"] - else edata.value + lambda edata: ( + "*" + edata.value + if edata.value == edata.common["principal"] + else edata.value + ) ), formatters=( Formatters.green_alert( @@ -277,6 +285,7 @@ def usage_weighted_avg(edatas: list[EntryData]): "Total", Projectors.Number( "ns_stats", + "indexes-memory-budget", # Added in 7.1 for memory only "index-type.mounts-budget", # Added in 7.0 "index-type.mounts-size-limit", ), @@ -306,6 +315,7 @@ def usage_weighted_avg(edatas: list[EntryData]): ), Projectors.Number( "ns_stats", + "indexes-memory-budget", # Added in 7.1 for memory only "index-type.mounts-budget", # Meant to be used with index_used_bytes. Both added in 7.0 "index-type.mounts-size-limit", ), @@ -327,7 +337,8 @@ def usage_weighted_avg(edatas: list[EntryData]): "Evict%", Projectors.Number( "ns_stats", - "index-type.evict-mounts-pct", # Added in 7.0 + "evict-indexes-memory-pct", # Added in 7.1 for memory only + "index-type.evict-mounts-pct", # Added in 7.0 for flash and pmem "index-type.mounts-high-water-pct", ), converter=Converters.pct, @@ -772,9 +783,9 @@ def set_index_projector(enable_index, index_populating): Projectors.Number("set_stats", "data_used_bytes"), Projectors.Func( FieldType.number, - lambda m_data, d_data: d_data - if m_data == 0 - else m_data, + lambda m_data, d_data: ( + d_data if m_data == 0 else m_data + ), Projectors.Number( "set_stats", "memory_data_bytes", @@ -2308,9 +2319,11 @@ def roster_null_to_empty_list_converter(edata): "Node ID", Projectors.String("node_ids", None), converter=( - lambda edata: "*" + edata.value - if edata.value == edata.common["principal"] - else edata.value + lambda edata: ( + "*" + edata.value + if edata.value == edata.common["principal"] + else edata.value + ) ), formatters=( Formatters.green_alert( diff --git a/test/unit/utils/test_common.py b/test/unit/utils/test_common.py index 8d5c63d8..e8619a9c 100644 --- a/test/unit/utils/test_common.py +++ b/test/unit/utils/test_common.py @@ -1277,6 +1277,62 @@ def create_tc( } }, ), + # stop_writes is not triggered by index_used_bytes + create_tc( + ns_stats={ + "1.1.1.1": { + "ns1": { + "stop_writes": "true", + "index_used_bytes": "10", + } + }, + }, + ns_config={ + "1.1.1.1": {"ns1": {"indexes-memory-budget": "90"}}, + }, + expected={ + "1.1.1.1": { + ("ns1", None, "index_used_bytes"): { + "metric": "index_used_bytes", + "config": "indexes-memory-budget", + "stop_writes": False, + "metric_usage": 10, + "metric_threshold": 90, + "namespace": "ns1", + }, + } + }, + ), + # stop_writes is triggered by index_used_bytes + create_tc( + ns_stats={ + "1.1.1.1": { + "ns1": { + "stop_writes": "true", + "index_used_bytes": "90", + } + }, + }, + ns_config={ + "1.1.1.1": { + "ns1": { + "indexes-memory-budget": "90", + } + }, + }, + expected={ + "1.1.1.1": { + ("ns1", None, "index_used_bytes"): { + "metric": "index_used_bytes", + "config": "indexes-memory-budget", + "stop_writes": True, + "metric_usage": 90, + "metric_threshold": 90, + "namespace": "ns1", + }, + } + }, + ), # stop_writes is not triggered by set.memory_data_bytes create_tc( set_stats={