94 lines
5.1 KiB
HTML
94 lines
5.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Node Monitor</title>
|
|
<link rel="stylesheet" href="{{ url_for('static', path='/style.css') }}">
|
|
</head>
|
|
<body>
|
|
<div class="header-container">
|
|
<h1>Node Monitoring System</h1>
|
|
<p>Total Nodes: <span id="node-count">{{ nodes|length }}</span></p>
|
|
<p>Service UUID: <code>{{ service_uuid }}</code></p>
|
|
</div>
|
|
|
|
<div id="node-grid-container">
|
|
{% if nodes %}
|
|
<div class="connection-grid" style="grid-template-columns: minmax(100px, 1fr) repeat({{ nodes|length }}, minmax(100px, 1fr));">
|
|
<!-- Header Row (Column UUIDs) -->
|
|
<div class="grid-row header-row">
|
|
<div class="grid-cell empty-cell"></div> {# Top-left corner #}
|
|
{% for node in nodes %}
|
|
<div class="grid-cell header-cell">
|
|
<div class="node-uuid" title="{{ node.uuid }}">{{ node.uuid[:8] }}...</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<!-- Data Rows -->
|
|
{% for row_node in nodes %}
|
|
<div class="grid-row">
|
|
<!-- Row Header (UUID) -->
|
|
<div class="grid-cell header-cell">
|
|
<div class="node-uuid" title="{{ row_node.uuid }}">{{ row_node.uuid[:8] }}...</div>
|
|
</div>
|
|
|
|
<!-- Cells for connections/status -->
|
|
{% for col_node in nodes %}
|
|
<div class="grid-cell
|
|
{% if row_node.uuid == col_node.uuid %}
|
|
node-{{ row_node.health_status }}
|
|
{% else %}
|
|
{% set latency = row_node.connections[col_node.uuid] if col_node.uuid in row_node.connections else None %}
|
|
{% if latency is not none and latency is not equalto 0.0 %}
|
|
{% if latency <= 200 %}latency-low
|
|
{% elif latency <= 1000 %}latency-medium
|
|
{% else %}latency-high
|
|
{% endif %}
|
|
{% else %}
|
|
latency-unavailable
|
|
{% endif %}
|
|
{% endif %}
|
|
">
|
|
{% if row_node.uuid == col_node.uuid %}
|
|
<div class="node-status-text">Status: {{ row_node.health_status.upper() }}</div>
|
|
<div class="node-tooltip">
|
|
<p><strong>UUID:</strong> {{ row_node.uuid }}</p>
|
|
<p><strong>IP:</strong> {{ row_node.ip }}</p>
|
|
<p><strong>Last Seen:</strong> {{ row_node.formatted_last_seen }}</p>
|
|
<p><strong>Uptime:</strong> {{ row_node.formatted_uptime }}</p>
|
|
<p><strong>Load Avg (1m, 5m, 15m):</strong> {{ row_node.load_avg | map('%.2f' | format) | join(', ') if row_node.load_avg else 'N/A' }}</p>
|
|
<p><strong>Memory Usage:</strong> {{ '%.2f' | format(row_node.memory_usage_percent) + '%' if row_node.memory_usage_percent is not none else 'N/A' }}</p>
|
|
</div>
|
|
{% else %}
|
|
{% set latency = row_node.connections[col_node.uuid] if col_node.uuid in row_node.connections else None %}
|
|
{% set display_latency = 'N/A' %}
|
|
{% if latency is not none and latency is not equalto 0.0 %}
|
|
{% set display_latency = '%.1f ms' | format(latency) %}
|
|
{% endif %}
|
|
<div class="conn-status-text">Ping: {{ display_latency }}</div>
|
|
<div class="node-tooltip">
|
|
<p><strong>From:</strong> {{ row_node.uuid[:8] }}...</p>
|
|
<p><strong>to:</strong> {{ col_node.uuid[:8] }}...</p>
|
|
<p><strong>Latency:</strong> {{ display_latency }}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<p class="loading-message">No nodes reporting yet. Start a client!</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<script>
|
|
// Pass the base path for API calls if mounted under a subpath
|
|
window.API_BASE_PATH = "{{ root_path }}";
|
|
</script>
|
|
<script src="{{ url_for('static', path='/script.js') }}"></script>
|
|
</body>
|
|
</html>
|