aboutsummaryrefslogtreecommitdiff
path: root/wqflask
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2022-12-03 06:43:27 +0300
committerFrederick Muriuki Muriithi2022-12-03 06:43:27 +0300
commit1a651da72faf987f7e3d0c7ba4c60cafe850c7a0 (patch)
tree4b9281cbd9b586fdad536540962a4a142f1574aa /wqflask
parent585208eca2764e33e70da05875c8e08ccbf91bf1 (diff)
downloadgenenetwork2-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.py2
-rw-r--r--wqflask/wqflask/__init__.py2
-rw-r--r--wqflask/wqflask/api/jobs.py54
-rw-r--r--wqflask/wqflask/templates/jobs/debug.html42
-rw-r--r--wqflask/wqflask/templates/jobs/no-such-job.html13
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%}