|
1 | 1 | import logging
|
2 | 2 | from datetime import timedelta
|
| 3 | +from typing import Dict |
3 | 4 |
|
4 | 5 | from envs.monkey_zoo.blackbox.analyzers.analyzer import Analyzer
|
5 |
| -from envs.monkey_zoo.blackbox.island_client.monkey_island_client import MonkeyIslandClient |
| 6 | +from envs.monkey_zoo.blackbox.tests.performance.performance_test_config import PerformanceTestConfig |
6 | 7 |
|
7 |
| -MAX_ALLOWED_SINGLE_PAGE_TIME = timedelta(seconds=2) |
8 |
| -MAX_ALLOWED_TOTAL_TIME = timedelta(seconds=5) |
9 |
| - |
10 |
| -REPORT_URLS = [ |
11 |
| - "api/report/security", |
12 |
| - "api/attack/report", |
13 |
| - "api/report/zero_trust/findings", |
14 |
| - "api/report/zero_trust/principles", |
15 |
| - "api/report/zero_trust/pillars" |
16 |
| -] |
17 |
| - |
18 |
| -logger = logging.getLogger(__name__) |
| 8 | +LOGGER = logging.getLogger(__name__) |
19 | 9 |
|
20 | 10 |
|
21 | 11 | class PerformanceAnalyzer(Analyzer):
|
22 | 12 |
|
23 |
| - def __init__(self, island_client: MonkeyIslandClient, break_if_took_too_long=False): |
24 |
| - self.break_if_took_too_long = break_if_took_too_long |
25 |
| - self.island_client = island_client |
26 |
| - |
27 |
| - def analyze_test_results(self) -> bool: |
28 |
| - if not self.island_client.is_all_monkeys_dead(): |
29 |
| - raise RuntimeError("Can't test report times since not all Monkeys have died.") |
| 13 | + def __init__(self, performance_test_config: PerformanceTestConfig, endpoint_timings: Dict[str, timedelta]): |
| 14 | + self.performance_test_config = performance_test_config |
| 15 | + self.endpoint_timings = endpoint_timings |
30 | 16 |
|
31 |
| - # Collect timings for all pages |
32 |
| - self.island_client.clear_caches() |
33 |
| - report_resource_to_response_time = {} |
34 |
| - for url in REPORT_URLS: |
35 |
| - report_resource_to_response_time[url] = self.island_client.get_elapsed_for_get_request(url) |
36 |
| - |
37 |
| - # Calculate total time and check each page |
| 17 | + def analyze_test_results(self): |
| 18 | + # Calculate total time and check each endpoint |
38 | 19 | single_page_time_less_then_max = True
|
39 | 20 | total_time = timedelta()
|
40 |
| - for page, elapsed in report_resource_to_response_time.items(): |
41 |
| - logger.info(f"page {page} took {str(elapsed)}") |
| 21 | + for endpoint, elapsed in self.endpoint_timings.items(): |
42 | 22 | total_time += elapsed
|
43 |
| - if elapsed > MAX_ALLOWED_SINGLE_PAGE_TIME: |
| 23 | + if elapsed > self.performance_test_config.max_allowed_single_page_time: |
44 | 24 | single_page_time_less_then_max = False
|
45 | 25 |
|
46 |
| - total_time_less_then_max = total_time < MAX_ALLOWED_TOTAL_TIME |
| 26 | + total_time_less_then_max = total_time < self.performance_test_config.max_allowed_total_time |
47 | 27 |
|
48 |
| - logger.info(f"total time is {str(total_time)}") |
| 28 | + PerformanceAnalyzer.log_slowest_endpoints(self.endpoint_timings) |
| 29 | + LOGGER.info(f"Total time is {str(total_time)}") |
49 | 30 |
|
50 | 31 | performance_is_good_enough = total_time_less_then_max and single_page_time_less_then_max
|
51 | 32 |
|
52 |
| - if self.break_if_took_too_long and not performance_is_good_enough: |
53 |
| - logger.warning( |
| 33 | + if self.performance_test_config.break_on_timeout and not performance_is_good_enough: |
| 34 | + LOGGER.warning( |
54 | 35 | "Calling breakpoint - pausing to enable investigation of island. Type 'c' to continue once you're done "
|
55 | 36 | "investigating. Type 'p timings' and 'p total_time' to see performance information."
|
56 | 37 | )
|
57 | 38 | breakpoint()
|
58 | 39 |
|
59 | 40 | return performance_is_good_enough
|
| 41 | + |
| 42 | + @staticmethod |
| 43 | + def log_slowest_endpoints(endpoint_timings, max_endpoints_to_display=100): |
| 44 | + slow_endpoint_list = list(endpoint_timings.items()) |
| 45 | + slow_endpoint_list.sort(key=lambda x: x[1], reverse=True) |
| 46 | + slow_endpoint_list = slow_endpoint_list[:max_endpoints_to_display] |
| 47 | + for endpoint in slow_endpoint_list: |
| 48 | + LOGGER.info(f"{endpoint[0]} took {str(endpoint[1])}") |
0 commit comments