about summary refs log tree commit diff
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
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
-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%}