Skip to content

Commit

Permalink
TP2000-1068 Envelope generation celery task info (#1051)
Browse files Browse the repository at this point in the history
* Add envelope task info to app-info page.

* Better and consistent formatting.

* App info page tests.
  • Loading branch information
paulpepper-trade authored Sep 27, 2023
1 parent 48c1eee commit b5e90ef
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 47 deletions.
113 changes: 80 additions & 33 deletions common/jinja2/common/app_info.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,57 @@
</h1>


<div class="govuk-grid-row">
{% if request.user.is_superuser %}
<div class="govuk-grid-row govuk-!-margin-bottom-6 info-section">
<div class="govuk-grid-column-full">
<h2 class="govuk-heading-m">Deployment information</h2>

{% set table_head = [
{"text": "Name"},
{"text": "Value"},
{"text": "Description"},
] %}

{% set table_rows = [
[
{"text": "GIT_BRANCH"},
{"text": GIT_BRANCH},
{"text": "Environment variable"},
],
[
{"text": "GIT_COMMIT"},
{"text": GIT_COMMIT},
{"text": "Environment variable"},
],
[
{"text": "APP_UPDATED_TIME"},
{"text": APP_UPDATED_TIME},
{"text": "Estimated application deploy time"},
],
[
{"text": "LAST_TRANSACTION_TIME"},
{"text": LAST_TRANSACTION_TIME},
{"text": "Last transaction change time"},
],
] %}

{{ govukTable({
"head": table_head,
"rows": table_rows
}) }}
</div>
</div>
{% endif %}


<div class="govuk-grid-row govuk-!-margin-bottom-6 info-section">
<div class="govuk-grid-column-full">
<h2 class="govuk-heading-m">Active business rule checks</h2>

{% set table_head = [
{"text": "Workbasket ID"},
{"text": "Time started"},
{"text": "Checks completed"},
{"text": "Time started"},
{"text": "Celery task ID"},
] %}
{% set table_rows = [] %}
Expand All @@ -46,15 +89,15 @@
{% for check in active_checks %}
{{ table_rows.append([
{"text": check.workbasket_id},
{"text": check.date_time_start},
{"text": check.checks_completed},
{"text": check.date_time_start},
{"text": check.task_id},
]) or "" }}
{% endfor %}
{% else %}
{{ table_rows.append([
{
"text": "No active checks.",
"text": "No active business rule checks.",
"colspan": 4,
}
]) or "" }}
Expand All @@ -76,46 +119,50 @@
</div>


{% if request.user.is_superuser %}
<div class="govuk-grid-row govuk-!-margin-top-6">
<div class="govuk-grid-row govuk-!-margin-bottom-6 info-section">
<div class="govuk-grid-column-full">
<h2 class="govuk-heading-m">Deployment Information</h2>
<h2 class="govuk-heading-m">Active envelope generation tasks</h2>

{% set table_head = [
{"text": "Name"},
{"text": "Value"},
{"text": "Description"},
{"text": "Packaged Workbasket ID"},
{"text": "Workbasket ID"},
{"text": "Time started"},
{"text": "Celery task ID"},
] %}
{% set table_rows = [] %}

{% set table_rows = [
[
{"text": "GIT_BRANCH"},
{"text": GIT_BRANCH},
{"text": "Environment variable"},
],
[
{"text": "GIT_COMMIT"},
{"text": GIT_COMMIT},
{"text": "Environment variable"},
],
[
{"text": "APP_UPDATED_TIME"},
{"text": "{:%d %b %Y, %H:%M}".format(APP_UPDATED_TIME|localtime)},
{"text": "Estimated application deploy time"},
],
[
{"text": "LAST_TRANSACTION_TIME"},
{"text": "{:%d %b %Y, %H:%M}".format(LAST_TRANSACTION_TIME|localtime)},
{"text": "Last transaction change time"},
],
] %}
{% if celery_healthy %}
{% if active_envelope_generation %}
{% for generation_info in active_envelope_generation %}
{{ table_rows.append([
{"text": generation_info.packaged_workbasket_id},
{"text": generation_info.workbasket_id},
{"text": generation_info.date_time_start},
{"text": generation_info.task_id},
]) or "" }}
{% endfor %}
{% else %}
{{ table_rows.append([
{
"text": "No active envelope generation tasks.",
"colspan": 4,
}
]) or "" }}
{% endif %}
{% else %}
{{ table_rows.append([
{
"text": "Envelope generation task details are currently unavailable.",
"colspan": 4,
}
]) or "" }}
{% endif %}

{{ govukTable({
"head": table_head,
"rows": table_rows
}) }}
</div>
</div>
{% endif %}

{% endblock %}
30 changes: 28 additions & 2 deletions common/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,39 @@ def test_healthcheck_response(response, status_code, status):
assert payload[1].tag == "response_time"


def test_app_info(valid_user_client):
def test_app_info_non_superuser(valid_user_client):
"""Users without the superuser permission have a restricted view of
application information."""
response = valid_user_client.get(reverse("app-info"))

assert response.status_code == 200

page = BeautifulSoup(str(response.content), "html.parser")
assert "Active business rule checks" in page.select("h2")[0].text
h2_elements = page.select(".info-section h2")

assert len(h2_elements) == 2
assert "Active business rule checks" in h2_elements[0].text
assert "Active envelope generation tasks" in h2_elements[1].text


def test_app_info_superuser(superuser_client, new_workbasket):
"""
Superusers should have an unrestricted view of application information.
The new_workbasket fixture provides access to transaction information in the
deployment infomation section.
"""
response = superuser_client.get(reverse("app-info"))

assert response.status_code == 200

page = BeautifulSoup(str(response.content), "html.parser")
h2_elements = page.select(".info-section h2")

assert len(h2_elements) == 3
assert "Deployment information" in h2_elements[0].text
assert "Active business rule checks" in h2_elements[1].text
assert "Active envelope generation tasks" in h2_elements[2].text


def test_index_displays_footer_links(valid_user_client):
Expand Down
71 changes: 59 additions & 12 deletions common/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import time
from datetime import datetime
from typing import Dict
from typing import Optional
from typing import Tuple
from typing import Type
Expand Down Expand Up @@ -41,6 +42,7 @@
from common.models import Transaction
from common.pagination import build_pagination_list
from common.validators import UpdateType
from publishing.models import PackagedWorkBasket
from workbaskets.models import WorkBasket
from workbaskets.views.mixins import WithCurrentWorkBasket

Expand Down Expand Up @@ -129,28 +131,64 @@ class AppInfoView(
TemplateView,
):
template_name = "common/app_info.jinja"
DATETIME_FORMAT = "%d %b %Y, %H:%M"

def active_checks(self):
results = []
def active_tasks(self) -> Dict:
inspect = app.control.inspect()
if not inspect:
return results
return {}

active_tasks = inspect.active()
if not active_tasks:
return results
return {}

return active_tasks

@staticmethod
def timestamp_to_datetime_string(timestamp):
return make_aware(
datetime.fromtimestamp(timestamp),
).strftime(AppInfoView.DATETIME_FORMAT)

def active_envelope_generation(self, active_tasks):
results = []

for _, task_info_list in active_tasks.items():
for task_info in task_info_list:
if task_info.get("name") == "publishing.tasks.create_xml_envelope_file":
date_time_start = AppInfoView.timestamp_to_datetime_string(
task_info.get("time_start"),
)

packaged_workbasket_id = task_info.get("args", [""])[0]
packaged_workbasket = PackagedWorkBasket.objects.get(
id=packaged_workbasket_id,
)
workbasket_id = packaged_workbasket.workbasket.id

results.append(
{
"task_id": task_info.get("id"),
"packaged_workbasket_id": packaged_workbasket_id,
"workbasket_id": workbasket_id,
"date_time_start": date_time_start,
},
)

return results

def active_checks(self, active_tasks):
results = []

for _, task_info_list in active_tasks.items():
for task_info in task_info_list:
if (
task_info.get("name")
== "workbaskets.tasks.call_check_workbasket_sync"
):
date_time_start = make_aware(
datetime.fromtimestamp(
task_info.get("time_start"),
),
).strftime("%Y-%m-%d, %H:%M:%S")
date_time_start = AppInfoView.timestamp_to_datetime_string(
task_info.get("time_start"),
)

workbasket_id = task_info.get("args", [""])[0]
workbasket = WorkBasket.objects.get(id=workbasket_id)
Expand All @@ -170,19 +208,28 @@ def active_checks(self):
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
try:
data["active_checks"] = self.active_checks()
active_tasks = self.active_tasks()
data["celery_healthy"] = True
data["active_checks"] = self.active_checks(active_tasks)
data["active_envelope_generation"] = self.active_envelope_generation(
active_tasks,
)
except kombu.exceptions.OperationalError as oe:
data["celery_healthy"] = False

if self.request.user.is_superuser:
data["GIT_BRANCH"] = os.getenv("GIT_BRANCH", "Unavailable")
data["GIT_COMMIT"] = os.getenv("GIT_COMMIT", "Unavailable")
data["APP_UPDATED_TIME"] = datetime.fromtimestamp(
data["APP_UPDATED_TIME"] = AppInfoView.timestamp_to_datetime_string(
os.path.getmtime(__file__),
)
last_transaction = Transaction.objects.order_by("updated_at").last()
data["LAST_TRANSACTION_TIME"] = (
Transaction.objects.order_by("-updated_at").first().updated_at
format(
last_transaction.updated_at.strftime(AppInfoView.DATETIME_FORMAT),
)
if last_transaction
else "No transactions"
)

return data
Expand Down

0 comments on commit b5e90ef

Please sign in to comment.