From 2f64471837ac3dc75396486955c7ac1e4886760e Mon Sep 17 00:00:00 2001 From: Lance Xu Date: Mon, 6 Nov 2023 09:20:05 -0500 Subject: [PATCH] Add rendering functions to report tool This update generates an index.html file in the collect bundle folder. Both Correlated Results and Plugin Results have its sub-items. Clicking items will show corresponding content in the content area. Test Plan: PASS: Verify the current report tool functions is not affected PASS: Verify the index.html is generated in the collect bundle folder PASS: Verify Correlated Results and Plugin Results are shown PASS: Verify the subitems of the Results are clickable and shown PASS: Verify the menu is expandable/collapsible PASS: Verify vertical scrollbar is applied when overflow occurs Story: 2010533 Task: 49041 Change-Id: Icf9c727b4f9418e03c0c7e273c8477e5ef9480ac Signed-off-by: Lance Xu --- .../collector/debian-scripts/report/render.py | 547 ++++++++++++++++++ .../collector/debian-scripts/report/report.py | 4 + tools/collector/debian/deb_folder/rules | 1 + 3 files changed, 552 insertions(+) create mode 100644 tools/collector/debian-scripts/report/render.py diff --git a/tools/collector/debian-scripts/report/render.py b/tools/collector/debian-scripts/report/render.py new file mode 100644 index 00000000..1c135768 --- /dev/null +++ b/tools/collector/debian-scripts/report/render.py @@ -0,0 +1,547 @@ +import os + + +# extract 'plugins' part and 'correlated' part +def extract_section(log_contents, start_phrase): + start = log_contents.find(start_phrase) + if start == -1: + return "" + end = log_contents.find("\n\n", start) + if end == -1: + end = len(log_contents) + return log_contents[start:end].strip() + + +# remove timestamp for results +def remove_timestamp(text): + lines = text.split('\n') + temp = [] + for line in lines: + if line.startswith('2023'): + temp.append(line[20:]) + else: + temp.append(line) + final_text = '\n'.join(temp) + return final_text + + +# remove 'INFO:' text +def remove_emptyinfo(text): + lines = text.split('\n') + temp = [] + for line in lines: + if line.strip() != 'INFO:': + temp.append(line) + final_text = '\n'.join(temp) + return final_text + + +# place the controller-0 in the top +def controller_sort(x): + return x[0] != 'controller-0' + + +# static css code +def html_css(): + html_content_css = """ + + + + Report Analysis + + + """ + return html_content_css + + +# return text with timestamp and INFO: removed +def process_section(section, title): + # Remove the title from the section + section = section[len(title):] + # Remove timestamps and empty information + section = remove_timestamp(section) + section = remove_emptyinfo(section) + return section + + +# static script code +def html_script(): + html_content_script = """ + + + """ + return html_content_script + + +# info part genearation +def html_info(sys_section): + controller_section = [] + storage_section = [] + worker_section = [] + sections = { + "controller": controller_section, + "storage": storage_section, + "worker": worker_section + } + + for i in sys_section: + section_lines = i.strip().split("\n") + section_type = section_lines[5] + + if "controller" in section_type: + controller_section.append(section_lines) + + if "storage" in section_type: + storage_section.append(section_lines) + + if "worker" in section_type: + worker_section.append(section_lines) + + controller_section = sorted(controller_section, key=controller_sort) + + controller_zero = controller_section.pop(0) + + html_content_one = "" + + html_content_one += """ + +
+
""" + + # controller-0 + html_content_one += """
""" + for i in controller_zero: + html_content_one += f'{i}' + html_content_one += "
" + html_content_one += "
" + + for section_type, section_list in sections.items(): + for i, section in enumerate(section_list): + html_content_one += f'" + + html_content_one += "

""" + return html_content_one + + +# menu and content generation for results +def html_result(log_contents, output_dir): + # Extract sections from the log + plugin_section = extract_section(log_contents, 'Plugin Results:') + correlated_section = extract_section(log_contents, 'Correlated Results:') + + # Process the extracted sections + plugin_section = process_section(plugin_section, 'Plugin Results:') + correlated_section = process_section(correlated_section, 'Correlated Results:') + + # HTML part + correlated_directory = os.path.join(os.getcwd(), output_dir) + os.chdir(correlated_directory) + correlated_items = [] + for file in os.listdir(correlated_directory): + if os.path.isfile(file) and '.' not in file: + correlated_items.append({'name': file, 'id': f'content-item-{file}'}) + + plugin_directory = os.path.join(correlated_directory, 'plugins') + os.chdir(plugin_directory) + + plugin_items = [] + for file in os.listdir(plugin_directory): + if os.path.isfile(file) and file != "system_info": + plugin_items.append({'name': file, 'id': f'content-item-{file}'}) + + html_content_two = "" + + html_content_two += """ +
+ """ + html_content_two += """
""" + + for item in correlated_items: + html_content_two += f'

{item["name"].capitalize()}

' + + for item in plugin_items: + html_content_two += f'

{item["name"].capitalize()}

' + + html_content_two += f'

Correlated Results

' + html_content_two += f'

Plugin Results

' + html_content_two += """ +
+
+ + """ + + return html_content_two + + +# CSS +def main(input_dir, output_dir): + + reportlog_path = os.path.join(output_dir, 'report.log') + + with open(reportlog_path, 'r') as file: + log_contents = file.read() + + sysinfo_path = os.path.join(output_dir, 'plugins/system_info') + + with open(sysinfo_path, 'r') as file: + sysinfo_contents = file.read() + + sys_section = sysinfo_contents.strip().split("\n\n") + html_content = html_css() + html_info(sys_section) + html_result(log_contents, output_dir) + html_script() + html_content = html_content.format() + + # change back to upper level + os.chdir('..') + + # Write the HTML content to a file + with open("index.html", "w") as file: + file.write(html_content) diff --git a/tools/collector/debian-scripts/report/report.py b/tools/collector/debian-scripts/report/report.py index fc1e52ad..4ab4044e 100755 --- a/tools/collector/debian-scripts/report/report.py +++ b/tools/collector/debian-scripts/report/report.py @@ -121,6 +121,7 @@ import time import algorithms from execution_engine import ExecutionEngine from plugin import Plugin +import render # Globals now = datetime.now(timezone.utc) @@ -963,4 +964,7 @@ else: # analyze the collect bundle engine.execute(obj.plugins, output_dir) +# generate report tool rendering html file +render.main(input_dir, output_dir) + sys.exit() diff --git a/tools/collector/debian/deb_folder/rules b/tools/collector/debian/deb_folder/rules index 7a31076f..318da0c9 100755 --- a/tools/collector/debian/deb_folder/rules +++ b/tools/collector/debian/deb_folder/rules @@ -38,6 +38,7 @@ override_dh_auto_install: install -m 755 -p report/algorithms.py $(ROOT)/usr/local/bin/report/algorithms.py install -m 755 -p report/plugin.py $(ROOT)/usr/local/bin/report/plugin.py install -m 755 -p report/correlator.py $(ROOT)/usr/local/bin/report/correlator.py + install -m 755 -p report/render.py $(ROOT)/usr/local/bin/report/render.py install -m 644 -p report/README $(ROOT)/usr/local/bin/report/README # Report Tool Plugin Algorithms