Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TP2000-1068 Envelope generation celery task info #1051

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading