diff --git a/tools/regression_analysis.py b/tools/regression_analysis.py index 1fd74b481..f643fa760 100644 --- a/tools/regression_analysis.py +++ b/tools/regression_analysis.py @@ -53,7 +53,7 @@ def validate_resource_limits(limits): def container_metrics(row): entries = row.get('containers') - if not isinstance(entries, list) or not entries or row.get('container_error'): + if not isinstance(entries, list) or row.get('container_error'): return {} memory = pids = 0 units = {'B': 1, 'kB': 1000, 'KiB': 1024, 'MB': 1000**2, 'MiB': 1024**2, 'GB': 1000**3, 'GiB': 1024**3} @@ -102,10 +102,7 @@ def resource_verdict(directory, limits): before = [value(row) for row in baseline] after = [value(row) for row in tail] if any( - not isinstance(v, (int, float)) - or not math.isfinite(v) - or v < 0 - or (metric in {'rss_bytes', 'memory_bytes'} and v == 0) + not isinstance(v, (int, float)) or not math.isfinite(v) or v < 0 or (metric == 'rss_bytes' and v == 0) for v in before + after ): result['errors'].append(f'{name}/{metric}: missing or invalid samples') diff --git a/tools/test_regression_analysis.py b/tools/test_regression_analysis.py index 2f0ce72ee..f74708753 100644 --- a/tools/test_regression_analysis.py +++ b/tools/test_regression_analysis.py @@ -59,6 +59,27 @@ class AnalysisTests(unittest.TestCase): verdict = resource_verdict(self.root, {**self.limits, 'containers': {'memory_bytes': 1024**2}}) self.assertIn('docker_containers/memory_bytes', verdict['errors'][0]) + def test_empty_observed_container_set_is_successful_recovery(self): + self.resources() + rows = [json.loads(line) for line in (self.root / 'resources.jsonl').read_text().splitlines()] + for row in rows: + row['containers'] = [{'MemUsage': '10MiB / 1GiB', 'PIDs': '2'}] if row['phase'] == 'load' else [] + limits = {**self.limits, 'containers': {'memory_bytes': 0, 'pids': 0, 'count': 0}} + + def verdict(): + (self.root / 'resources.jsonl').write_text(''.join(json.dumps(row) + '\n' for row in rows)) + return resource_verdict(self.root, limits) + + result = verdict() + self.assertEqual(result['errors'], []) + for metric in limits['containers']: + self.assertEqual(result['targets']['docker_containers'][metric]['cooldown_median'], 0) + rows[-1]['container_error'] = 'collection failed' + self.assertTrue(verdict()['errors']) + del rows[-1]['container_error'] + del rows[-1]['containers'] + self.assertTrue(verdict()['errors']) + def test_stimulus_variables_are_compared_but_target_origin_is_not(self): profile = { 'vars': {'prompt': 'first', 'endpoint': 'http://127.0.0.1:1'},