Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding JSON output #374

Merged
merged 8 commits into from
May 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions manager.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import argparse

from plotmanager.library.utilities.exceptions import InvalidArgumentException
from plotmanager.library.utilities.commands import start_manager, stop_manager, view, analyze_logs
from plotmanager.library.utilities.commands import start_manager, stop_manager, view, json_output, analyze_logs


parser = argparse.ArgumentParser(description='This is the central manager for Swar\'s Chia Plot Manager.')

help_description = '''
There are a few different actions that you can use: "start", "restart", "stop", "view", and "analyze_logs". "start" will
start a manager process. If one already exists, it will display an error message. "restart" will try to kill any
existing manager and start a new one. "stop" will terminate the manager, but all existing plots will be completed.
"view" can be used to display an updating table that will show the progress of your plots. Once a manager has started it
will always be running in the background unless an error occurs. This field is case-sensitive.
There are a few different actions that you can use: "start", "restart", "stop", "view", "status", "json", and
"analyze_logs". "start" will start a manager process. If one already exists, it will display an error message.
"restart" will try to kill any existing manager and start a new one. "stop" will terminate the manager, but all
existing plots will be completed. "view" can be used to display an updating table that will show the progress of your
plots. Once a manager has started it will always be running in the background unless an error occurs. This field is
case-sensitive.

"analyze_logs" is a helper command that will scan all the logs in your log_directory to get your custom settings for
the progress settings in the YAML file.
Expand All @@ -34,9 +35,13 @@
stop_manager()
elif args.action == 'view':
view()
elif args.action == 'json':
json_output()
elif args.action == 'status':
view(loop=False)
elif args.action == 'analyze_logs':
analyze_logs()
else:
error_message = 'Invalid action provided. The valid options are "start", "restart", "stop", "view", and ' \
error_message = 'Invalid action provided. The valid options are "start", "restart", "stop", "view", "status", "json" and ' \
'"analyze_logs".'
raise InvalidArgumentException(error_message)
65 changes: 61 additions & 4 deletions plotmanager/library/utilities/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
from plotmanager.library.utilities.jobs import load_jobs
from plotmanager.library.utilities.log import analyze_log_dates, check_log_progress, analyze_log_times
from plotmanager.library.utilities.notifications import send_notifications
from plotmanager.library.utilities.print import print_view
from plotmanager.library.utilities.processes import is_windows, get_manager_processes, get_running_plots, start_process
from plotmanager.library.utilities.print import print_view, print_json
from plotmanager.library.utilities.processes import is_windows, get_manager_processes, get_running_plots, \
start_process, identify_drive, get_system_drives


def start_manager():
Expand Down Expand Up @@ -75,7 +76,60 @@ def stop_manager():
print("Successfully stopped manager processes.")


def view():
def json_output():
chia_location, log_directory, config_jobs, manager_check_interval, max_concurrent, progress_settings, \
notification_settings, debug_level, view_settings, instrumentation_settings = get_config_info()

all_drives = get_system_drives()

analysis = {'files': {}}
drives = {'temp': [], 'temp2': [], 'dest': []}
jobs = load_jobs(config_jobs)
for job in jobs:
drive = job.temporary_directory.split('\\')[0]
drives['temp'].append(drive)
directories = {
'dest': job.destination_directory,
'temp2': job.temporary2_directory,
}
for key, directory_list in directories.items():
if directory_list is None:
continue
if not isinstance(directory_list, list):
directory_list = [directory_list]
for directory in directory_list:
drive = identify_drive(file_path=directory, drives=all_drives)
if drive in drives[key]:
continue
drives[key].append(drive)

running_work = {}

analysis = analyze_log_dates(log_directory=log_directory, analysis=analysis)
jobs = load_jobs(config_jobs)
jobs, running_work = get_running_plots(jobs=jobs, running_work=running_work,
instrumentation_settings=instrumentation_settings)
check_log_progress(jobs=jobs, running_work=running_work, progress_settings=progress_settings,
notification_settings=notification_settings, view_settings=view_settings,
instrumentation_settings=instrumentation_settings)
print_json(jobs=jobs, running_work=running_work, view_settings=view_settings)

has_file = False
if len(running_work.values()) == 0:
has_file = True
for work in running_work.values():
if not work.log_file:
continue
has_file = True
break
if not has_file:
print("Restarting view due to psutil going stale...")
system_args = [f'"{sys.executable}"'] + sys.argv
os.execv(sys.executable, system_args)
exit()


def view(loop=False):
chia_location, log_directory, config_jobs, manager_check_interval, max_concurrent, progress_settings, \
notification_settings, debug_level, view_settings, instrumentation_settings = get_config_info()
view_check_interval = view_settings['check_interval']
Expand Down Expand Up @@ -114,7 +168,10 @@ def view():
notification_settings=notification_settings, view_settings=view_settings,
instrumentation_settings=instrumentation_settings)
print_view(jobs=jobs, running_work=running_work, analysis=analysis, drives=drives,
next_log_check=datetime.now() + timedelta(seconds=view_check_interval), view_settings=view_settings)
next_log_check=datetime.now() + timedelta(seconds=view_check_interval),
view_settings=view_settings, loop=loop)
if not loop:
break
time.sleep(view_check_interval)
has_file = False
if len(running_work.values()) == 0:
Expand Down
59 changes: 56 additions & 3 deletions plotmanager/library/utilities/print.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,35 @@
import os
import psutil
import json

from datetime import datetime, timedelta

from plotmanager.library.utilities.processes import get_manager_processes, get_chia_drives
from plotmanager.library.utilities.processes import get_manager_processes


def _get_json(pid, running_work, view_settings):
work = running_work[pid]
phase_times = work.phase_times
elapsed_time = (datetime.now() - work.datetime_start)
elapsed_time = pretty_print_time(elapsed_time.seconds)
phase_time_log = []
for i in range(1, 5):
if phase_times.get(i):
phase_time_log.append(phase_times.get(i))

row = [
work.job.name if work.job else '?',
work.k_size,
pid,
work.datetime_start.strftime(view_settings['datetime_format']),
elapsed_time,
work.current_phase,
' / '.join(phase_time_log),
work.progress,
pretty_print_bytes(work.temp_file_size, 'gb', 0, " GiB"),
]

return row


def _get_row_info(pid, running_work, view_settings):
Expand Down Expand Up @@ -66,6 +92,28 @@ def pretty_print_table(rows):
return "\n".join(console)


def get_job_json(jobs, running_work, view_settings):
rows = []
added_pids = []
for job in jobs:
for pid in job.running_work:
if pid not in running_work:
continue
rows.append(_get_json(pid, running_work, view_settings))
added_pids.append(pid)
for pid in running_work.keys():
if pid in added_pids:
continue
rows.append(_get_json(pid, running_work, view_settings))
added_pids.append(pid)
rows.sort(key=lambda x: (x[4]), reverse=True)
for i in range(len(rows)):
rows[i] = [str(i + 1)] + rows[i]
jobs = dict(jobs=rows)
print(json.dumps(jobs, separators=(',', ':')))
return rows


def get_job_data(jobs, running_work, view_settings):
rows = []
added_pids = []
Expand Down Expand Up @@ -170,7 +218,11 @@ def get_drive_data(drives, running_work, job_data):
return pretty_print_table(rows)


def print_view(jobs, running_work, analysis, drives, next_log_check, view_settings):
def print_json(jobs, running_work, view_settings):
get_job_json(jobs=jobs, running_work=running_work, view_settings=view_settings)


def print_view(jobs, running_work, analysis, drives, next_log_check, view_settings, loop):
# Job Table
job_data = get_job_data(jobs=jobs, running_work=running_work, view_settings=view_settings)

Expand Down Expand Up @@ -202,5 +254,6 @@ def print_view(jobs, running_work, analysis, drives, next_log_check, view_settin
print(f'Plots Completed Yesterday: {analysis["summary"].get(datetime.now().date() - timedelta(days=1), 0)}')
print(f'Plots Completed Today: {analysis["summary"].get(datetime.now().date(), 0)}')
print()
print(f"Next log check at {next_log_check.strftime('%Y-%m-%d %H:%M:%S')}")
if loop:
print(f"Next log check at {next_log_check.strftime('%Y-%m-%d %H:%M:%S')}")
print()