Skip to content

Commit

Permalink
Status page jobs updates (#1083)
Browse files Browse the repository at this point in the history
* Status page jobs updates

Signed-off-by: Nikolai <nrozanov@iponweb.net>

* Naming fix

Signed-off-by: Nikolai <nrozanov@iponweb.net>

* Small updates + use modal dialog instead of copying to clipboard

Signed-off-by: Nikolai <nrozanov@iponweb.net>

* Fix for modal window

Signed-off-by: Nikolai <nrozanov@iponweb.net>

* Fix for modal form

Signed-off-by: Nikolai <nrozanov@iponweb.net>

* Fix for modal form close button

Signed-off-by: Nikolai <nrozanov@iponweb.net>

* remove extra x

Signed-off-by: Nicolas Höning <nicolas@seita.nl>

---------

Signed-off-by: Nikolai <nrozanov@iponweb.net>
Signed-off-by: Nicolas Höning <nicolas@seita.nl>
Co-authored-by: Nikolai <nrozanov@iponweb.net>
Co-authored-by: Nicolas Höning <nicolas@seita.nl>
  • Loading branch information
3 people committed Jun 11, 2024
1 parent 1d7b6ca commit eeeb616
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 81 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import timedelta, datetime
import json
import pytest
import pytz

Expand Down Expand Up @@ -309,10 +310,10 @@ def test_build_asset_jobs_data(db, app, add_battery_assets):
jobs_data = build_asset_jobs_data(battery_asset)
assert sorted([j["queue"] for j in jobs_data]) == ["forecasting", "scheduling"]
for job_data in jobs_data:
metadata = json.loads(job_data["metadata"])
if job_data["queue"] == "forecasting":
assert job_data["job_id"] == forecasting_jobs[0].id
assert metadata["job_id"] == forecasting_jobs[0].id
else:
assert job_data["job_id"] == scheduling_job.id
assert metadata["job_id"] == scheduling_job.id
assert job_data["status"] == "queued"
assert job_data["asset_or_sensor_type"] == "sensor"
assert job_data["asset_id"] == battery.id
assert job_data["entity"] == f"sensor: {battery.name} (Id: {battery.id})"
14 changes: 11 additions & 3 deletions flexmeasures/data/services/sensors.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

import json
import hashlib
from datetime import datetime, timedelta
from flask import current_app
from timely_beliefs import BeliefsDataFrame
Expand Down Expand Up @@ -212,6 +214,7 @@ def build_asset_jobs_data(
- status: job status (e.g finished, failed, etc)
- err: job error (equals to None when there was no error for a job)
- enqueued_at: time when the job was enqueued
- metadata_hash: hash of job metadata (internal field)
"""

jobs = list()
Expand All @@ -222,6 +225,7 @@ def build_asset_jobs_data(
"scheduling",
"asset",
asset.id,
asset.name,
current_app.job_cache.get(asset.id, "scheduling", "asset"),
)
)
Expand All @@ -232,6 +236,7 @@ def build_asset_jobs_data(
"scheduling",
"sensor",
sensor.id,
sensor.name,
current_app.job_cache.get(sensor.id, "scheduling", "sensor"),
)
)
Expand All @@ -240,13 +245,14 @@ def build_asset_jobs_data(
"forecasting",
"sensor",
sensor.id,
sensor.name,
current_app.job_cache.get(sensor.id, "forecasting", "sensor"),
)
)

jobs_data = list()
# Building the actual return list - we also unpack lists of jobs, each to its own entry, and we add error info
for queue, asset_or_sensor_type, asset_id, jobs in jobs:
for queue, asset_or_sensor_type, entity_id, entity_name, jobs in jobs:
for job in jobs:
e = job.meta.get(
"exception",
Expand All @@ -262,15 +268,17 @@ def build_asset_jobs_data(
else None
)

metadata = json.dumps({**job.meta, "job_id": job.id}, default=str, indent=4)
jobs_data.append(
{
"job_id": job.id,
"metadata": metadata,
"queue": queue,
"asset_or_sensor_type": asset_or_sensor_type,
"asset_id": asset_id,
"entity": f"{asset_or_sensor_type}: {entity_name} (Id: {entity_id})",
"status": job.get_status(),
"err": job_err,
"enqueued_at": job.enqueued_at,
"metadata_hash": hashlib.sha256(metadata.encode()).hexdigest(),
}
)

Expand Down
12 changes: 3 additions & 9 deletions flexmeasures/ui/crud/assets/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,25 +155,19 @@ def status(self, id: str):

# add data about forecasting and scheduling jobs
redis_connection_err = None
scheduling_job_data, forecasting_job_data = list(), list()
all_jobs_data = list()
try:
jobs_data = build_asset_jobs_data(asset)
except NoRedisConfigured as e:
redis_connection_err = e.args[0]
else:
scheduling_job_data = [
jd for jd in jobs_data if jd["queue"] == "scheduling"
]
forecasting_job_data = [
jd for jd in jobs_data if jd["queue"] == "forecasting"
]
all_jobs_data = jobs_data

return render_flexmeasures_template(
"views/status.html",
asset=asset,
sensors=status_data,
scheduling_job_data=scheduling_job_data,
forecasting_job_data=forecasting_job_data,
jobs_data=all_jobs_data,
redis_connection_err=redis_connection_err,
)

Expand Down
97 changes: 32 additions & 65 deletions flexmeasures/ui/templates/views/status.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,78 +58,29 @@ <h3>Data connectivity for sensors of {{ asset.name }}</h3>
{% endfor %}
</tbody>
</table>
<h3>Latest scheduling jobs of {{ asset.name }}</h3>
<table id="scheduling_jobs" class="table table-striped table-responsive paginate nav-on-click">
<h3>Latest jobs of {{ asset.name }}</h3>
<table id="scheduling_forecasting_jobs" class="table table-striped table-responsive paginate nav-on-click">
<thead>
<tr>
<th>Job id</th>
<th>Asset id</th>
<th>Sensor or asset</th>
<th>Created at</th>
<th>Queue</th>
<th>Entity</th>
<th class="text-right no-sort">Status</th>
<th class="text-right">Info</th>
<th class="d-none">URL</th>
</tr>
</thead>
<tbody>
{% for job_data in scheduling_job_data: %}
{% for job_data in jobs_data: %}
<tr title="View data">
<td>
{{ job_data.job_id }}
</td>
<td>
{{ job_data.asset_id }}
</td>
<td>
{{ job_data.asset_or_sensor_type }}
</td>
<td title="Enqueued at: {{ job_data.enqueued_at}}">
{{ job_data.enqueued_at | naturalized_datetime }}
</td>
<td class="text-right"
title="{{ job_data['err'] is none and job_data['status'] or job_data['status'] + ' : ' + job_data['err'] }}">
<span>
{% if job_data["status"] == "finished" %}
🟢
{% elif job_data["status"] == "failed" %}
🔴
{% else %}
🟡
{% endif %}
</span>
</td>
<td class="hidden d-none invisible" style="display:none;">
/tasks/0/view/job/{{ job_data.job_id }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<h3>Latest forecasting jobs of {{ asset.name }}</h3>
<table id="forecasting_jobs" class="table table-striped table-responsive paginate nav-on-click">
<thead>
<tr>
<th>Job id</th>
<th>Asset id</th>
<th>Sensor or asset</th>
<th>Created at</th>
<th class="text-right no-sort">Status</th>
<th class="d-none">URL</th>
</tr>
</thead>
<tbody>
{% for job_data in forecasting_job_data: %}
<tr title="View data">
<td>
{{ job_data.job_id }}
</td>
<td>
{{ job_data.asset_id }}
{{ job_data.queue }}
</td>
<td>
{{ job_data.asset_or_sensor_type }}
</td>
<td title="Enqueued at: {{ job_data.enqueued_at}}">
{{ job_data.enqueued_at | naturalized_datetime }}
{{ job_data.entity }}
</td>
<td class="text-right"
title="{{ job_data['err'] is none and job_data['status'] or job_data['status'] + ' : ' + job_data['err'] }}">
Expand All @@ -143,7 +94,28 @@ <h3>Latest forecasting jobs of {{ asset.name }}</h3>
{% endif %}
</span>
</td>
<td class="d-none">
<td class="text-right">
<!-- Button -->
<a href="#" class="btn btn-default btn-success" role="button" id="job-metadata-info-button" data-bs-target="#JobMetadataModal-{{ job_data['metadata_hash'] }}" data-bs-toggle="modal">
Info
</a>

<!-- Modal -->
<div class="modal fade" id="JobMetadataModal-{{ job_data['metadata_hash'] }}" tabindex="-1" role="dialog" aria-labelledby="JobMetadataInfo" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="JobMetadataInfo">Info</h5>
<button id="modalCloseButton" type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onmousedown="event.stopPropagation(); event.preventDefault();"></button>
</div>
<div class="modal-body">
<pre>{{ job_data['metadata'] }}</pre>
</div>
</div>
</div>
</div>
</td>
<td class="hidden d-none invisible" style="display:none;">
/tasks/0/view/job/{{ job_data.job_id }}
</td>
</tr>
Expand All @@ -156,17 +128,12 @@ <h3>Latest forecasting jobs of {{ asset.name }}</h3>
</div>
</div>
</div>


</div>


<!-- sort scheduling and forecasting jobs by 'Created at' column -->
<script>
$(document).ready(function() {
$('#scheduling_jobs').DataTable({"order": [[ 3, "desc" ]]});
$('#forecasting_jobs').DataTable({"order": [[ 3, "desc" ]]});
$('#scheduling_forecasting_jobs').DataTable({"order": [[ 0, "desc" ]]});
});
</script>

{% endblock %}
{% endblock %}

0 comments on commit eeeb616

Please sign in to comment.