Skip to content
Snippets Groups Projects
Commit f35e5c8f authored by Nico Vermaas's avatar Nico Vermaas
Browse files

Merge branch 'status-plots' into 'master'

status plots functionality

See merge request !347
parents 6feeed09 5a30a121
No related branches found
No related tags found
1 merge request!347status plots functionality
Pipeline #74761 passed
...@@ -10,6 +10,7 @@ django-filter==2.3.0 ...@@ -10,6 +10,7 @@ django-filter==2.3.0
django-tables2==2.3.4 django-tables2==2.3.4
djangorestframework==3.14 djangorestframework==3.14
fontawesome-free==5.15.2 fontawesome-free==5.15.2
matplotlib==3.8.3
oauthlib==3.2.2 oauthlib==3.2.2
psycopg2-binary==2.9.3 psycopg2-binary==2.9.3
python3-openid==3.2.0 python3-openid==3.2.0
......
# graph_template.html (HTML template for rendering the graph) {% extends 'taskdatabase/base.html' %}
<!DOCTYPE html> {% load static %}
<html lang="en">
<head> {% block myBlock %}
<meta charset="UTF-8"> <div class="container-fluid">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <div class="card">
<title>Status Graph</title> <div class="card-body">
</head> <p>
<body> <a href="{% url 'create_status_graph' %}" class="btn btn-primary btn-sm" role="button"><i class="fas fa-chart-line"></i> Status Graph</a>
<h1>Status Graph</h1> </p>
<img src="records_per_hour_finished_last_100days.png" alt="Status Graph"> <img src="/atdb/static/status_graph.png" alt="Status Graph">
</body> </div>
</html> </div>
\ No newline at end of file </div>
{% endblock %}
\ No newline at end of file
# input_form.html (HTML template for input form) {% extends 'taskdatabase/base.html' %}
<!DOCTYPE html> {% load static %}
<html lang="en">
<head> {% block myBlock %}
<meta charset="UTF-8"> <div class="container-fluid">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <div class="card">
<title>Create Status Graph</title> <div class="card-body">
</head>
<body>
<form action="{% url 'create_status_graph' %}" method="post"> <form action="{% url 'create_status_graph' %}" method="post">
{% csrf_token %} {% csrf_token %}
<label for="status">Status:</label> <label for="status">Which (end) status to plot?:</label>
<input type="text" id="status" name="status" value="finished"><br><br> <input type="text" id="status" name="status" value="finished"><br><br>
<label for="days">Last X days:</label> <label for="days">Last X days:</label>
<input type="number" id="days" name="days" value="100"><br><br> <input type="number" id="days" name="days" value="30"><br><br>
<label for="bin_size">Bin Size:</label> <label for="bin_size">Bin Size:</label>
<select id="bin_size" name="bin_size"> <select id="bin_size" name="bin_size" value="day">
<option value="hour">Hour</option>
<option value="day">Day</option> <option value="day">Day</option>
<option value="hour">Hour</option>
</select><br><br> </select><br><br>
<button type="submit">Generate Graph</button> <button type="submit">Generate Graph</button>
</form> </form>
</body> </div>
</html> </div>
\ No newline at end of file </div>
{% endblock %}
\ No newline at end of file
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
{% include 'taskdatabase/pagination.html' %} {% include 'taskdatabase/pagination.html' %}
</div> </div>
</div> </div>
<p class="footer"> Version 1 Mar 2024 <p class="footer"> Version 7 Mar 2024
</div> </div>
{% include 'taskdatabase/refresh.html' %} {% include 'taskdatabase/refresh.html' %}
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
{% block myBlock %} {% block myBlock %}
<div class="hiking-container container-fluid"> <div class="container-fluid">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<div class="row"> <div class="row">
...@@ -16,11 +16,14 @@ ...@@ -16,11 +16,14 @@
&nbsp; &nbsp;
<div class="thumbnail"> <div class="thumbnail">
<h5>Health and Status of the LDV services.</h5> <h5>Health and Status of the LDV services.</h5>
{% if user.is_superuser %}
<p> <p>
{% if user.is_superuser %}
<a href="{% url 'clear-inactive-services' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-window-close"></i> Clear Services</a> <a href="{% url 'clear-inactive-services' %}" class="btn btn-secondary btn-sm" role="button"><i class="fas fa-window-close"></i> Clear Services</a>
</p>
{% endif %} {% endif %}
<a href="{% url 'create_status_graph' %}" class="btn btn-primary btn-sm" role="button"><i class="fas fa-chart-line"></i> Status Graph</a>
</p>
<table class="table table-striped"> <table class="table table-striped">
<th>LDV-Service</th><th>Host</th><th>Enabled</th><th>Last Status</th><th>Timestamp</th><th>Process id</th><th>Description</th> <th>LDV-Service</th><th>Host</th><th>Enabled</th><th>Last Status</th><th>Timestamp</th><th>Process id</th><th>Description</th>
<tbody> <tbody>
......
...@@ -52,6 +52,7 @@ urlpatterns = [ ...@@ -52,6 +52,7 @@ urlpatterns = [
path('monitoring/', views.ShowMonitoring, name='monitoring'), path('monitoring/', views.ShowMonitoring, name='monitoring'),
path('diagram/', views.DiagramView.as_view(), name='diagram'), path('diagram/', views.DiagramView.as_view(), name='diagram'),
path('config/', views.ShowConfig, name='config'), path('config/', views.ShowConfig, name='config'),
path('create_status_graph/', views.CreateStatusGraph, name='create_status_graph'),
# --- REST API --- # --- REST API ---
......
import logging import logging
import json import json
from datetime import datetime, timedelta
try:
import matplotlib.pyplot as plt
except:
# enable debugging, but without matplotlib
pass
import psycopg2
from . import config from . import config
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
...@@ -1767,3 +1775,88 @@ def UpdateSummaryFlag(request, task_id): ...@@ -1767,3 +1775,88 @@ def UpdateSummaryFlag(request, task_id):
return JsonResponse({ return JsonResponse({
'is_summary': task.is_summary 'is_summary': task.is_summary
}) })
def CreateStatusGraph(request):
query_per_hour = """
SELECT
DATE_TRUNC('hour', timestamp) AS hour,
COUNT(*) AS num_records
FROM
taskdatabase_status
WHERE name = %s
AND timestamp >= %s -- Filter for records within the last x days
GROUP BY
DATE_TRUNC('hour', timestamp)
ORDER BY
DATE_TRUNC('hour', timestamp);
"""
query_per_day = """
SELECT
DATE_TRUNC('day', timestamp) AS day,
COUNT(*) AS num_records
FROM
taskdatabase_status
WHERE name = %s
AND timestamp >= %s -- Filter for records within the last x days
GROUP BY
DATE_TRUNC('day', timestamp)
ORDER BY
DATE_TRUNC('day', timestamp);
"""
if request.method == 'POST':
status = request.POST.get('status', 'finished')
try:
days_to_check = int(request.POST.get('days', 60))
except:
days_to_check = 60
bin_size = request.POST.get('bin_size', 'day')
# Calculate the date x days ago
start_date = datetime.now() - timedelta(days=days_to_check)
database = settings.DATABASES['default']
# Connect to your PostgreSQL database
conn = psycopg2.connect(
dbname=database['NAME'],
user=database['USER'],
password=database['PASSWORD'],
host=database['HOST'],
port=database['PORT'],
)
# Execute the SQL query
cur = conn.cursor()
if bin_size == 'day':
cur.execute(query_per_day, (status,start_date))
else:
cur.execute(query_per_hour, (status, start_date))
# Fetch the results
results = cur.fetchall()
# Close cursor and connection
cur.close()
conn.close()
# Extract hours and number of records from results
records = [result[0] for result in results]
num_records = [result[1] for result in results]
# Plot the graph
plt.figure(figsize=(10, 6))
plt.plot(records, num_records, marker='o')
plt.xlabel(bin_size.capitalize())
plt.ylabel('Number of Records')
plt.title(f'{status} per {bin_size} for the last {days_to_check} days')
plt.xticks(rotation=45)
plt.grid(True)
plt.tight_layout()
plt.savefig('taskdatabase/static/status_graph.png')
# Render the template with the graph
return render(request, 'taskdatabase/graphs/status_graph.html')
return render(request, 'taskdatabase/graphs/status_graph_input_form.html', {'image_path': 'status_graph.png'})
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment