|
| 1 | +import re |
| 2 | +import requests |
| 3 | +import time |
| 4 | + |
| 5 | +EVENT_TYPE = "itimer" |
| 6 | +PROFILING_DURATION_IN_SEC = 1 |
| 7 | + |
| 8 | + |
| 9 | +def start_profiling_and_get_refresh_header(service_url): |
| 10 | + prof_page = requests.get( |
| 11 | + f"{service_url}/prof" |
| 12 | + f"?event={EVENT_TYPE}&duration={PROFILING_DURATION_IN_SEC}") |
| 13 | + |
| 14 | + assert prof_page.ok, \ |
| 15 | + f"""Profiling could not be started. |
| 16 | + URL: {prof_page.request.url} |
| 17 | + Status Code: {prof_page.status_code}""" |
| 18 | + |
| 19 | + return prof_page.headers['Refresh'] |
| 20 | + |
| 21 | + |
| 22 | +def parse_refresh_header(refresh_header): |
| 23 | + refresh_time_in_sec, refresh_path = refresh_header.split(';', 1) |
| 24 | + refresh_time_in_sec = int(refresh_time_in_sec) |
| 25 | + |
| 26 | + assert refresh_time_in_sec == PROFILING_DURATION_IN_SEC, \ |
| 27 | + f"""Profiling duration and refresh time should be equal. |
| 28 | + expected: {PROFILING_DURATION_IN_SEC} |
| 29 | + actual: {refresh_time_in_sec}""" |
| 30 | + |
| 31 | + expected_refresh_path_pattern = \ |
| 32 | + r'/prof-output-hadoop/async-prof-pid-\d+-itimer-\d+.html' |
| 33 | + assert re.fullmatch(expected_refresh_path_pattern, refresh_path), \ |
| 34 | + f"""The path to the flamegraph contains an unexpected pattern. |
| 35 | + expected pattern: {expected_refresh_path_pattern}" |
| 36 | + actual path: {refresh_path}""" |
| 37 | + |
| 38 | + return refresh_time_in_sec, refresh_path |
| 39 | + |
| 40 | + |
| 41 | +def wait_for_profiling_to_finish(refresh_time_in_sec): |
| 42 | + additional_sleep_time_in_sec = 2 |
| 43 | + time.sleep(refresh_time_in_sec + additional_sleep_time_in_sec) |
| 44 | + |
| 45 | + |
| 46 | +def fetch_flamegraph(service_url, refresh_path): |
| 47 | + flamegraph_page = requests.get(f"{service_url}{refresh_path}") |
| 48 | + |
| 49 | + assert flamegraph_page.ok, \ |
| 50 | + f"""The flamegraph could not be fetched. |
| 51 | + URL: {flamegraph_page.request.url} |
| 52 | + Status Code: {flamegraph_page.status_code}""" |
| 53 | + |
| 54 | + |
| 55 | +def test_profiling(role, port): |
| 56 | + service_url = ( |
| 57 | + f"http://test-hdfs-{role}-default-0.test-hdfs-{role}-default" |
| 58 | + f":{port}") |
| 59 | + |
| 60 | + print(f"Test profiling on {service_url}") |
| 61 | + |
| 62 | + refresh_header = start_profiling_and_get_refresh_header(service_url) |
| 63 | + |
| 64 | + refresh_time_in_sec, refresh_path = \ |
| 65 | + parse_refresh_header(refresh_header) |
| 66 | + |
| 67 | + wait_for_profiling_to_finish(refresh_time_in_sec) |
| 68 | + |
| 69 | + fetch_flamegraph(service_url, refresh_path) |
| 70 | + |
| 71 | + |
| 72 | +test_profiling(role="namenode", port=9870) |
| 73 | +test_profiling(role="datanode", port=9864) |
| 74 | +test_profiling(role="journalnode", port=8480) |
0 commit comments