diff options
author | Frederick Muriuki Muriithi | 2022-12-03 06:43:27 +0300 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2022-12-03 06:43:27 +0300 |
commit | 1a651da72faf987f7e3d0c7ba4c60cafe850c7a0 (patch) | |
tree | 4b9281cbd9b586fdad536540962a4a142f1574aa /wqflask | |
parent | 585208eca2764e33e70da05875c8e08ccbf91bf1 (diff) | |
download | genenetwork2-1a651da72faf987f7e3d0c7ba4c60cafe850c7a0.tar.gz |
jobs: Add debug UI
* wqflask/scripts/run_external.py: Save the actual return code
* wqflask/wqflask/__init__.py: Use new jobs blueprint
* wqflask/wqflask/api/jobs.py: Add new jobs debug route
* wqflask/wqflask/templates/jobs/debug.html: new template for when job
is found
* wqflask/wqflask/templates/jobs/no-such-job.html: new template for
when the job is not found
Diffstat (limited to 'wqflask')
-rw-r--r-- | wqflask/scripts/run_external.py | 2 | ||||
-rw-r--r-- | wqflask/wqflask/__init__.py | 2 | ||||
-rw-r--r-- | wqflask/wqflask/api/jobs.py | 54 | ||||
-rw-r--r-- | wqflask/wqflask/templates/jobs/debug.html | 42 | ||||
-rw-r--r-- | wqflask/wqflask/templates/jobs/no-such-job.html | 13 |
5 files changed, 112 insertions, 1 deletions
diff --git a/wqflask/scripts/run_external.py b/wqflask/scripts/run_external.py index 3cefa033..b44a6db7 100644 --- a/wqflask/scripts/run_external.py +++ b/wqflask/scripts/run_external.py @@ -101,7 +101,7 @@ def run_job(redis_conn: Redis, job_id: UUID): returncode = process.returncode set_meta(redis_conn, job_id, "completion-status", ("success" if returncode == 0 else "error")) - set_meta(redis_conn, job_id, "return-code", "error") + set_meta(redis_conn, job_id, "return-code", returncode) return process.returncode def run_job_parser(parent_parser): diff --git a/wqflask/wqflask/__init__.py b/wqflask/wqflask/__init__.py index 332e248c..ada73867 100644 --- a/wqflask/wqflask/__init__.py +++ b/wqflask/wqflask/__init__.py @@ -25,6 +25,7 @@ from wqflask.api.markdown import environments_blueprint from wqflask.api.markdown import facilities_blueprint from wqflask.api.markdown import blogs_blueprint from wqflask.api.markdown import news_blueprint +from wqflask.api.jobs import jobs as jobs_bp from wqflask.jupyter_notebooks import jupyter_notebooks @@ -60,6 +61,7 @@ app.register_blueprint(jupyter_notebooks, url_prefix="/jupyter_notebooks") app.register_blueprint(resource_management, url_prefix="/resource-management") app.register_blueprint(metadata_edit, url_prefix="/datasets/") app.register_blueprint(group_management, url_prefix="/group-management") +app.register_blueprint(jobs_bp, url_prefix="/jobs") @app.before_request def before_request(): diff --git a/wqflask/wqflask/api/jobs.py b/wqflask/wqflask/api/jobs.py new file mode 100644 index 00000000..3f18de77 --- /dev/null +++ b/wqflask/wqflask/api/jobs.py @@ -0,0 +1,54 @@ +import uuid +from datetime import datetime + +from redis import Redis +from pymonad.io import IO +from flask import Blueprint, render_template + +from jobs.jobs import job + +jobs = Blueprint("jobs", __name__) + +@jobs.route("/debug/<uuid:job_id>") +def debug_job(job_id: uuid.UUID): + """Display job data to assist in debugging.""" + from utility.tools import REDIS_URL # Avoids circular import error + + def __stream_to_lines__(stream): + removables = ( + "Set global log level to", "runserver.py: ******", + "APPLICATION_ROOT:", "DB_", "DEBUG:", "ELASTICSEARCH_", "ENV:", + "EXPLAIN_TEMPLATE_LOADING:", "GEMMA_", "GENENETWORK_FILES", + "GITHUB_", "GN2_", "GN3_", "GN_", "HOME:", "JSONIFY_", "JS_", + "JSON_", "LOG_", "MAX_", "ORCID_", "PERMANENT_", "PLINK_", + "PREFERRED_URL_SCHEME", "PRESERVE_CONTEXT_ON_EXCEPTION", + "PROPAGATE_EXCEPTIONS", "REAPER_COMMAND", "REDIS_URL", "SECRET_", + "SECURITY_", "SEND_FILE_MAX_AGE_DEFAULT", "SERVER_", "SESSION_", + "SMTP_", "SQL_", "TEMPLATES_", "TESTING:", "TMPDIR", "TRAP_", + "USE_", "WEBSERVER_") + return tuple(filter( + lambda line: not any(line.startswith(item) for item in removables), + stream.split("\n"))) + + def __fmt_datetime(val): + return datetime.strptime(val, "%Y-%m-%dT%H:%M:%S.%f").strftime( + "%A, %d %B %Y at %H:%M:%S.%f") + + def __render_debug_page__(job): + job_details = {key.replace("-", "_"): val for key,val in job.items()} + return render_template( + "jobs/debug.html", + **{ + **job_details, + "request_received_time": __fmt_datetime( + job_details["request_received_time"]), + "stderr": __stream_to_lines__(job_details["stderr"]), + "stdout": __stream_to_lines__(job_details["stdout"]) + }) + + with Redis.from_url(REDIS_URL, decode_responses=True) as rconn: + the_job = job(rconn, job_id) + + return the_job.maybe( + render_template("jobs/no-such-job.html", job_id=job_id), + lambda job: __render_debug_page__(job)) diff --git a/wqflask/wqflask/templates/jobs/debug.html b/wqflask/wqflask/templates/jobs/debug.html new file mode 100644 index 00000000..828ab1cc --- /dev/null +++ b/wqflask/wqflask/templates/jobs/debug.html @@ -0,0 +1,42 @@ +{%extends "base.html"%} +{%block title%}Debug Job{% endblock%} +{%block css%} +{%endblock%} + +{%block content%} +<h1>Debug Job</h1> + +The following show details for job "{{job_id}}" to assist in debugging. + +<h2>Metadata</h2> + +<ul> + <li><strong>Job ID:</strong> {{job_id}}</li> + <li><strong>Command:</strong> <code>{{command}}</code></li> + <li><strong>Received:</strong> {{request_received_time}}</li> + <li><strong>Return Code:</strong> {{return_code}}</li> + <li><strong>Completion Status:</strong> {{completion_status}}</li> + <li><strong>Status:</strong> {{status}}</li> +</ul> + +<h2>STDERR</h2> + +<div style="background-color: black; color: red;"> + {%for line in stderr:%} + <p>{{line}}</p> + {%endfor%} +</div> + +<h2>STDOUT</h2> + +<div style="background-color: black; color: green;"> + {%for line in stdout:%} + <p>{{line}}</p> + {%endfor%} +</div> + + +{%endblock%} + +{%block js%} +{%endblock%} diff --git a/wqflask/wqflask/templates/jobs/no-such-job.html b/wqflask/wqflask/templates/jobs/no-such-job.html new file mode 100644 index 00000000..6fe7d014 --- /dev/null +++ b/wqflask/wqflask/templates/jobs/no-such-job.html @@ -0,0 +1,13 @@ +{%extends "base.html"%} +{%block title%}No Such Job{% endblock%} +{%block css%} +{%endblock%} + +{%block content%} +<h1>No Such Job</h1> + +<p>The job with id <strong>{{job_id | string}}</strong> does not exist</p> +{%endblock%} + +{%block js%} +{%endblock%} |