1084 lines
44 KiB
HTML
1084 lines
44 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}System Health{% endblock %}
|
|
|
|
{% block css %}
|
|
<link href="{% static 'assets/plugins/apexcharts/dist/apexcharts.css' %}" rel="stylesheet" />
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div id="content" class="app-content">
|
|
<div class="container">
|
|
<ul class="breadcrumb">
|
|
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
|
|
<li class="breadcrumb-item active">System Health</li>
|
|
</ul>
|
|
|
|
<div class="row align-items-center mb-3">
|
|
<div class="col">
|
|
<h1 class="page-header">System Health Monitor</h1>
|
|
<p class="text-muted">Real-time system performance and health monitoring</p>
|
|
</div>
|
|
<div class="col-auto">
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-outline-primary" onclick="refreshAllMetrics()">
|
|
<i class="fa fa-sync me-2"></i>Refresh All
|
|
</button>
|
|
<button type="button" class="btn btn-outline-info" onclick="exportHealthReport()">
|
|
<i class="fa fa-download me-2"></i>Export Report
|
|
</button>
|
|
<button type="button" class="btn btn-outline-warning" onclick="showAlerts()">
|
|
<i class="fa fa-exclamation-triangle me-2"></i>Alerts
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- System Status Overview -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-3">
|
|
<div class="card">
|
|
<div class="card-body text-center">
|
|
<div class="mb-2">
|
|
<i id="systemStatusIcon" class="fa fa-circle text-success fs-24px"></i>
|
|
</div>
|
|
<h5 id="systemStatusText" class="text-success">System Online</h5>
|
|
<p class="text-muted small mb-0">Overall Status</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card">
|
|
<div class="card-body text-center">
|
|
<div class="fs-24px fw-600 text-primary" id="uptimeValue">99.9%</div>
|
|
<h6 class="text-muted">Uptime</h6>
|
|
<p class="text-muted small mb-0" id="uptimeDuration">30 days, 12 hours</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card">
|
|
<div class="card-body text-center">
|
|
<div class="fs-24px fw-600 text-info" id="responseTimeValue">245ms</div>
|
|
<h6 class="text-muted">Avg Response Time</h6>
|
|
<p class="text-muted small mb-0">Last 24 hours</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card">
|
|
<div class="card-body text-center">
|
|
<div class="fs-24px fw-600 text-warning" id="activeUsersValue">127</div>
|
|
<h6 class="text-muted">Active Users</h6>
|
|
<p class="text-muted small mb-0">Currently online</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Performance Metrics -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">CPU Usage</h4>
|
|
<div class="card-tools">
|
|
<span id="cpuCurrentValue" class="badge bg-primary">45%</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="progress mb-3" style="height: 20px;">
|
|
<div id="cpuProgressBar" class="progress-bar bg-primary" style="width: 45%"></div>
|
|
</div>
|
|
<div id="cpuChart" style="height: 200px;"></div>
|
|
<div class="row text-center mt-3">
|
|
<div class="col-4">
|
|
<div class="text-muted small">Average</div>
|
|
<div id="cpuAverage" class="fw-bold">42%</div>
|
|
</div>
|
|
<div class="col-4">
|
|
<div class="text-muted small">Peak</div>
|
|
<div id="cpuPeak" class="fw-bold">78%</div>
|
|
</div>
|
|
<div class="col-4">
|
|
<div class="text-muted small">Cores</div>
|
|
<div id="cpuCores" class="fw-bold">8</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Memory Usage</h4>
|
|
<div class="card-tools">
|
|
<span id="memoryCurrentValue" class="badge bg-info">6.2 GB / 16 GB</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="progress mb-3" style="height: 20px;">
|
|
<div id="memoryProgressBar" class="progress-bar bg-info" style="width: 39%"></div>
|
|
</div>
|
|
<div id="memoryChart" style="height: 200px;"></div>
|
|
<div class="row text-center mt-3">
|
|
<div class="col-4">
|
|
<div class="text-muted small">Used</div>
|
|
<div id="memoryUsed" class="fw-bold">6.2 GB</div>
|
|
</div>
|
|
<div class="col-4">
|
|
<div class="text-muted small">Free</div>
|
|
<div id="memoryFree" class="fw-bold">9.8 GB</div>
|
|
</div>
|
|
<div class="col-4">
|
|
<div class="text-muted small">Total</div>
|
|
<div id="memoryTotal" class="fw-bold">16 GB</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Storage and Network -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Disk Usage</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<div class="d-flex justify-content-between mb-1">
|
|
<span>System Drive (C:)</span>
|
|
<span>245 GB / 500 GB</span>
|
|
</div>
|
|
<div class="progress">
|
|
<div class="progress-bar bg-warning" style="width: 49%"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="d-flex justify-content-between mb-1">
|
|
<span>Database Drive (D:)</span>
|
|
<span>1.2 TB / 2 TB</span>
|
|
</div>
|
|
<div class="progress">
|
|
<div class="progress-bar bg-success" style="width: 60%"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="d-flex justify-content-between mb-1">
|
|
<span>Backup Drive (E:)</span>
|
|
<span>800 GB / 1 TB</span>
|
|
</div>
|
|
<div class="progress">
|
|
<div class="progress-bar bg-danger" style="width: 80%"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row text-center mt-3">
|
|
<div class="col-4">
|
|
<div class="text-muted small">Total Used</div>
|
|
<div class="fw-bold">2.2 TB</div>
|
|
</div>
|
|
<div class="col-4">
|
|
<div class="text-muted small">Total Free</div>
|
|
<div class="fw-bold">1.3 TB</div>
|
|
</div>
|
|
<div class="col-4">
|
|
<div class="text-muted small">Total Space</div>
|
|
<div class="fw-bold">3.5 TB</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Network Activity</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="networkChart" style="height: 250px;"></div>
|
|
<div class="row text-center mt-3">
|
|
<div class="col-6">
|
|
<div class="text-muted small">Download</div>
|
|
<div class="fw-bold text-success">
|
|
<i class="fa fa-arrow-down me-1"></i>
|
|
<span id="downloadSpeed">12.5 MB/s</span>
|
|
</div>
|
|
</div>
|
|
<div class="col-6">
|
|
<div class="text-muted small">Upload</div>
|
|
<div class="fw-bold text-primary">
|
|
<i class="fa fa-arrow-up me-1"></i>
|
|
<span id="uploadSpeed">8.3 MB/s</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Database and Services -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Database Health</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row mb-3">
|
|
<div class="col-6">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fa fa-circle text-success me-2"></i>
|
|
<span>Primary Database</span>
|
|
</div>
|
|
<div class="text-muted small">PostgreSQL 13.4</div>
|
|
</div>
|
|
<div class="col-6 text-end">
|
|
<div class="fw-bold">Online</div>
|
|
<div class="text-muted small">Response: 15ms</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-6">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fa fa-circle text-success me-2"></i>
|
|
<span>Read Replica</span>
|
|
</div>
|
|
<div class="text-muted small">PostgreSQL 13.4</div>
|
|
</div>
|
|
<div class="col-6 text-end">
|
|
<div class="fw-bold">Online</div>
|
|
<div class="text-muted small">Lag: 2.3s</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-6">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fa fa-circle text-success me-2"></i>
|
|
<span>Redis Cache</span>
|
|
</div>
|
|
<div class="text-muted small">Redis 6.2</div>
|
|
</div>
|
|
<div class="col-6 text-end">
|
|
<div class="fw-bold">Online</div>
|
|
<div class="text-muted small">Hit Rate: 94%</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr>
|
|
|
|
<div class="row text-center">
|
|
<div class="col-4">
|
|
<div class="text-muted small">Connections</div>
|
|
<div class="fw-bold">45/100</div>
|
|
</div>
|
|
<div class="col-4">
|
|
<div class="text-muted small">Queries/sec</div>
|
|
<div class="fw-bold">1,247</div>
|
|
</div>
|
|
<div class="col-4">
|
|
<div class="text-muted small">Slow Queries</div>
|
|
<div class="fw-bold text-warning">3</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">System Services</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="service-item d-flex justify-content-between align-items-center mb-3">
|
|
<div>
|
|
<div class="fw-bold">Web Server (Nginx)</div>
|
|
<div class="text-muted small">Port 80, 443</div>
|
|
</div>
|
|
<div class="text-end">
|
|
<span class="badge bg-success">Running</span>
|
|
<div class="text-muted small">CPU: 2.1%</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="service-item d-flex justify-content-between align-items-center mb-3">
|
|
<div>
|
|
<div class="fw-bold">Application Server</div>
|
|
<div class="text-muted small">Django/Gunicorn</div>
|
|
</div>
|
|
<div class="text-end">
|
|
<span class="badge bg-success">Running</span>
|
|
<div class="text-muted small">Workers: 8</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="service-item d-flex justify-content-between align-items-center mb-3">
|
|
<div>
|
|
<div class="fw-bold">Task Queue</div>
|
|
<div class="text-muted small">Celery</div>
|
|
</div>
|
|
<div class="text-end">
|
|
<span class="badge bg-success">Running</span>
|
|
<div class="text-muted small">Queue: 12</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="service-item d-flex justify-content-between align-items-center mb-3">
|
|
<div>
|
|
<div class="fw-bold">File Storage</div>
|
|
<div class="text-muted small">MinIO</div>
|
|
</div>
|
|
<div class="text-end">
|
|
<span class="badge bg-success">Running</span>
|
|
<div class="text-muted small">Objects: 45.2K</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="service-item d-flex justify-content-between align-items-center mb-3">
|
|
<div>
|
|
<div class="fw-bold">Monitoring</div>
|
|
<div class="text-muted small">Prometheus</div>
|
|
</div>
|
|
<div class="text-end">
|
|
<span class="badge bg-warning">Warning</span>
|
|
<div class="text-muted small">High Memory</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="service-item d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<div class="fw-bold">Backup Service</div>
|
|
<div class="text-muted small">Last: 2 hours ago</div>
|
|
</div>
|
|
<div class="text-end">
|
|
<span class="badge bg-success">Running</span>
|
|
<div class="text-muted small">Next: 22:00</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Security and Logs -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Security Status</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row mb-3">
|
|
<div class="col-8">
|
|
<div class="fw-bold">SSL Certificate</div>
|
|
<div class="text-muted small">Expires: March 15, 2024</div>
|
|
</div>
|
|
<div class="col-4 text-end">
|
|
<span class="badge bg-success">Valid</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-8">
|
|
<div class="fw-bold">Firewall</div>
|
|
<div class="text-muted small">Last updated: 2 days ago</div>
|
|
</div>
|
|
<div class="col-4 text-end">
|
|
<span class="badge bg-success">Active</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-8">
|
|
<div class="fw-bold">Intrusion Detection</div>
|
|
<div class="text-muted small">Monitoring active</div>
|
|
</div>
|
|
<div class="col-4 text-end">
|
|
<span class="badge bg-success">Online</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-8">
|
|
<div class="fw-bold">Failed Login Attempts</div>
|
|
<div class="text-muted small">Last 24 hours</div>
|
|
</div>
|
|
<div class="col-4 text-end">
|
|
<span class="badge bg-warning">7</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-8">
|
|
<div class="fw-bold">Security Updates</div>
|
|
<div class="text-muted small">System patches</div>
|
|
</div>
|
|
<div class="col-4 text-end">
|
|
<span class="badge bg-info">2 Available</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Recent System Events</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="timeline">
|
|
<div class="timeline-item">
|
|
<div class="timeline-marker bg-success"></div>
|
|
<div class="timeline-content">
|
|
<div class="fw-bold">System Backup Completed</div>
|
|
<div class="text-muted small">2 hours ago</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="timeline-item">
|
|
<div class="timeline-marker bg-info"></div>
|
|
<div class="timeline-content">
|
|
<div class="fw-bold">Database Maintenance</div>
|
|
<div class="text-muted small">6 hours ago</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="timeline-item">
|
|
<div class="timeline-marker bg-warning"></div>
|
|
<div class="timeline-content">
|
|
<div class="fw-bold">High Memory Usage Alert</div>
|
|
<div class="text-muted small">8 hours ago</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="timeline-item">
|
|
<div class="timeline-marker bg-success"></div>
|
|
<div class="timeline-content">
|
|
<div class="fw-bold">Security Patch Applied</div>
|
|
<div class="text-muted small">1 day ago</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="timeline-item">
|
|
<div class="timeline-marker bg-danger"></div>
|
|
<div class="timeline-content">
|
|
<div class="fw-bold">Service Restart Required</div>
|
|
<div class="text-muted small">2 days ago</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-center mt-3">
|
|
<button type="button" class="btn btn-outline-primary btn-sm" onclick="showFullEventLog()">
|
|
<i class="fa fa-list me-2"></i>View Full Log
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Health Check Results -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Health Check Results</h4>
|
|
<div class="card-tools">
|
|
<button type="button" class="btn btn-outline-primary btn-sm" onclick="runHealthChecks()">
|
|
<i class="fa fa-play me-2"></i>Run All Checks
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Check</th>
|
|
<th>Status</th>
|
|
<th>Response Time</th>
|
|
<th>Last Checked</th>
|
|
<th>Details</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="healthCheckResults">
|
|
<tr>
|
|
<td>Database Connection</td>
|
|
<td><span class="badge bg-success">Healthy</span></td>
|
|
<td>15ms</td>
|
|
<td>2 minutes ago</td>
|
|
<td>Connection pool: 45/100</td>
|
|
<td>
|
|
<button class="btn btn-outline-primary btn-sm" onclick="runSingleCheck('database')">
|
|
<i class="fa fa-sync"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Cache Service</td>
|
|
<td><span class="badge bg-success">Healthy</span></td>
|
|
<td>3ms</td>
|
|
<td>2 minutes ago</td>
|
|
<td>Hit rate: 94.2%</td>
|
|
<td>
|
|
<button class="btn btn-outline-primary btn-sm" onclick="runSingleCheck('cache')">
|
|
<i class="fa fa-sync"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>File Storage</td>
|
|
<td><span class="badge bg-success">Healthy</span></td>
|
|
<td>45ms</td>
|
|
<td>2 minutes ago</td>
|
|
<td>Available space: 1.3TB</td>
|
|
<td>
|
|
<button class="btn btn-outline-primary btn-sm" onclick="runSingleCheck('storage')">
|
|
<i class="fa fa-sync"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Email Service</td>
|
|
<td><span class="badge bg-warning">Warning</span></td>
|
|
<td>2.3s</td>
|
|
<td>5 minutes ago</td>
|
|
<td>Queue: 23 pending</td>
|
|
<td>
|
|
<button class="btn btn-outline-primary btn-sm" onclick="runSingleCheck('email')">
|
|
<i class="fa fa-sync"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>External API</td>
|
|
<td><span class="badge bg-success">Healthy</span></td>
|
|
<td>156ms</td>
|
|
<td>2 minutes ago</td>
|
|
<td>All endpoints responding</td>
|
|
<td>
|
|
<button class="btn btn-outline-primary btn-sm" onclick="runSingleCheck('api')">
|
|
<i class="fa fa-sync"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Backup System</td>
|
|
<td><span class="badge bg-success">Healthy</span></td>
|
|
<td>-</td>
|
|
<td>2 hours ago</td>
|
|
<td>Last backup: Success</td>
|
|
<td>
|
|
<button class="btn btn-outline-primary btn-sm" onclick="runSingleCheck('backup')">
|
|
<i class="fa fa-sync"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Alerts Modal -->
|
|
<div class="modal fade" id="alertsModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">System Alerts</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="alertsContent">
|
|
<!-- Alerts will be loaded here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Event Log Modal -->
|
|
<div class="modal fade" id="eventLogModal" tabindex="-1">
|
|
<div class="modal-dialog modal-xl">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">System Event Log</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="eventLogContent">
|
|
<!-- Event log will be loaded here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script src="{% static 'assets/plugins/apexcharts/dist/apexcharts.min.js' %}"></script>
|
|
|
|
<script>
|
|
var cpuChart, memoryChart, networkChart;
|
|
var refreshInterval;
|
|
|
|
$(document).ready(function() {
|
|
initializeCharts();
|
|
startAutoRefresh();
|
|
loadInitialData();
|
|
});
|
|
|
|
function initializeCharts() {
|
|
// CPU Chart
|
|
var cpuOptions = {
|
|
series: [{
|
|
name: 'CPU Usage',
|
|
data: []
|
|
}],
|
|
chart: {
|
|
type: 'line',
|
|
height: 200,
|
|
toolbar: { show: false }
|
|
},
|
|
stroke: {
|
|
curve: 'smooth',
|
|
width: 2
|
|
},
|
|
colors: ['#007bff'],
|
|
xaxis: {
|
|
type: 'datetime',
|
|
labels: { show: false }
|
|
},
|
|
yaxis: {
|
|
min: 0,
|
|
max: 100,
|
|
labels: {
|
|
formatter: function(val) {
|
|
return val + '%';
|
|
}
|
|
}
|
|
},
|
|
grid: {
|
|
show: true,
|
|
strokeDashArray: 3
|
|
}
|
|
};
|
|
cpuChart = new ApexCharts(document.querySelector("#cpuChart"), cpuOptions);
|
|
cpuChart.render();
|
|
|
|
// Memory Chart
|
|
var memoryOptions = {
|
|
series: [{
|
|
name: 'Memory Usage',
|
|
data: []
|
|
}],
|
|
chart: {
|
|
type: 'area',
|
|
height: 200,
|
|
toolbar: { show: false }
|
|
},
|
|
fill: {
|
|
type: 'gradient',
|
|
gradient: {
|
|
shadeIntensity: 1,
|
|
opacityFrom: 0.7,
|
|
opacityTo: 0.3
|
|
}
|
|
},
|
|
stroke: {
|
|
curve: 'smooth',
|
|
width: 2
|
|
},
|
|
colors: ['#17a2b8'],
|
|
xaxis: {
|
|
type: 'datetime',
|
|
labels: { show: false }
|
|
},
|
|
yaxis: {
|
|
min: 0,
|
|
max: 100,
|
|
labels: {
|
|
formatter: function(val) {
|
|
return val + '%';
|
|
}
|
|
}
|
|
}
|
|
};
|
|
memoryChart = new ApexCharts(document.querySelector("#memoryChart"), memoryOptions);
|
|
memoryChart.render();
|
|
|
|
// Network Chart
|
|
var networkOptions = {
|
|
series: [{
|
|
name: 'Download',
|
|
data: []
|
|
}, {
|
|
name: 'Upload',
|
|
data: []
|
|
}],
|
|
chart: {
|
|
type: 'line',
|
|
height: 250,
|
|
toolbar: { show: false }
|
|
},
|
|
stroke: {
|
|
curve: 'smooth',
|
|
width: 2
|
|
},
|
|
colors: ['#28a745', '#007bff'],
|
|
xaxis: {
|
|
type: 'datetime',
|
|
labels: { show: false }
|
|
},
|
|
yaxis: {
|
|
labels: {
|
|
formatter: function(val) {
|
|
return val + ' MB/s';
|
|
}
|
|
}
|
|
},
|
|
legend: {
|
|
position: 'top'
|
|
}
|
|
};
|
|
networkChart = new ApexCharts(document.querySelector("#networkChart"), networkOptions);
|
|
networkChart.render();
|
|
}
|
|
|
|
function loadInitialData() {
|
|
// Load initial chart data
|
|
$.get('{% url "core:get_system_metrics" %}', function(data) {
|
|
updateMetrics(data);
|
|
updateCharts(data);
|
|
});
|
|
}
|
|
|
|
function startAutoRefresh() {
|
|
refreshInterval = setInterval(function() {
|
|
refreshAllMetrics();
|
|
}, 30000); // Refresh every 30 seconds
|
|
}
|
|
|
|
function refreshAllMetrics() {
|
|
$.get('{% url "core:get_system_metrics" %}', function(data) {
|
|
updateMetrics(data);
|
|
updateCharts(data);
|
|
}).fail(function() {
|
|
toastr.error('Failed to refresh system metrics');
|
|
});
|
|
}
|
|
|
|
function updateMetrics(data) {
|
|
// Update overview cards
|
|
$('#uptimeValue').text(data.uptime.percentage + '%');
|
|
$('#uptimeDuration').text(data.uptime.duration);
|
|
$('#responseTimeValue').text(data.response_time + 'ms');
|
|
$('#activeUsersValue').text(data.active_users);
|
|
|
|
// Update CPU
|
|
$('#cpuCurrentValue').text(data.cpu.current + '%');
|
|
$('#cpuProgressBar').css('width', data.cpu.current + '%');
|
|
$('#cpuAverage').text(data.cpu.average + '%');
|
|
$('#cpuPeak').text(data.cpu.peak + '%');
|
|
$('#cpuCores').text(data.cpu.cores);
|
|
|
|
// Update Memory
|
|
$('#memoryCurrentValue').text(data.memory.used + ' / ' + data.memory.total);
|
|
var memoryPercent = (data.memory.used_bytes / data.memory.total_bytes) * 100;
|
|
$('#memoryProgressBar').css('width', memoryPercent + '%');
|
|
$('#memoryUsed').text(data.memory.used);
|
|
$('#memoryFree').text(data.memory.free);
|
|
$('#memoryTotal').text(data.memory.total);
|
|
|
|
// Update Network
|
|
$('#downloadSpeed').text(data.network.download);
|
|
$('#uploadSpeed').text(data.network.upload);
|
|
|
|
// Update system status
|
|
updateSystemStatus(data.status);
|
|
}
|
|
|
|
function updateCharts(data) {
|
|
// Update CPU chart
|
|
if (data.cpu.history) {
|
|
cpuChart.updateSeries([{
|
|
name: 'CPU Usage',
|
|
data: data.cpu.history
|
|
}]);
|
|
}
|
|
|
|
// Update Memory chart
|
|
if (data.memory.history) {
|
|
memoryChart.updateSeries([{
|
|
name: 'Memory Usage',
|
|
data: data.memory.history
|
|
}]);
|
|
}
|
|
|
|
// Update Network chart
|
|
if (data.network.history) {
|
|
networkChart.updateSeries([{
|
|
name: 'Download',
|
|
data: data.network.download_history
|
|
}, {
|
|
name: 'Upload',
|
|
data: data.network.upload_history
|
|
}]);
|
|
}
|
|
}
|
|
|
|
function updateSystemStatus(status) {
|
|
var statusIcon = $('#systemStatusIcon');
|
|
var statusText = $('#systemStatusText');
|
|
|
|
statusIcon.removeClass('text-success text-warning text-danger');
|
|
|
|
switch(status.level) {
|
|
case 'healthy':
|
|
statusIcon.addClass('text-success');
|
|
statusText.text('System Healthy').removeClass('text-warning text-danger').addClass('text-success');
|
|
break;
|
|
case 'warning':
|
|
statusIcon.addClass('text-warning');
|
|
statusText.text('System Warning').removeClass('text-success text-danger').addClass('text-warning');
|
|
break;
|
|
case 'critical':
|
|
statusIcon.addClass('text-danger');
|
|
statusText.text('System Critical').removeClass('text-success text-warning').addClass('text-danger');
|
|
break;
|
|
}
|
|
}
|
|
|
|
function runHealthChecks() {
|
|
toastr.info('Running health checks...');
|
|
|
|
$.post('{% url "core:run_health_checks" %}', function(data) {
|
|
updateHealthCheckResults(data.results);
|
|
toastr.success('Health checks completed');
|
|
}).fail(function() {
|
|
toastr.error('Failed to run health checks');
|
|
});
|
|
}
|
|
|
|
function runSingleCheck(checkType) {
|
|
$.post('{% url "core:run_single_health_check" %}', {check_type: checkType}, function(data) {
|
|
updateSingleHealthCheck(checkType, data);
|
|
toastr.success('Health check completed for ' + checkType);
|
|
}).fail(function() {
|
|
toastr.error('Failed to run health check');
|
|
});
|
|
}
|
|
|
|
function updateHealthCheckResults(results) {
|
|
var tbody = $('#healthCheckResults');
|
|
tbody.empty();
|
|
|
|
results.forEach(function(result) {
|
|
var statusClass = result.status === 'healthy' ? 'success' :
|
|
result.status === 'warning' ? 'warning' : 'danger';
|
|
|
|
var row = '<tr>' +
|
|
'<td>' + result.name + '</td>' +
|
|
'<td><span class="badge bg-' + statusClass + '">' + result.status + '</span></td>' +
|
|
'<td>' + (result.response_time || '-') + '</td>' +
|
|
'<td>' + result.last_checked + '</td>' +
|
|
'<td>' + result.details + '</td>' +
|
|
'<td>' +
|
|
'<button class="btn btn-outline-primary btn-sm" onclick="runSingleCheck(\'' + result.type + '\')">' +
|
|
'<i class="fa fa-sync"></i>' +
|
|
'</button>' +
|
|
'</td>' +
|
|
'</tr>';
|
|
|
|
tbody.append(row);
|
|
});
|
|
}
|
|
|
|
function updateSingleHealthCheck(checkType, result) {
|
|
// Update specific row in health check table
|
|
var row = $('#healthCheckResults tr').filter(function() {
|
|
return $(this).find('button').attr('onclick').includes(checkType);
|
|
});
|
|
|
|
if (row.length > 0) {
|
|
var statusClass = result.status === 'healthy' ? 'success' :
|
|
result.status === 'warning' ? 'warning' : 'danger';
|
|
|
|
row.find('.badge').removeClass('bg-success bg-warning bg-danger').addClass('bg-' + statusClass).text(result.status);
|
|
row.find('td:eq(2)').text(result.response_time || '-');
|
|
row.find('td:eq(3)').text('Just now');
|
|
row.find('td:eq(4)').text(result.details);
|
|
}
|
|
}
|
|
|
|
function showAlerts() {
|
|
$.get('{% url "core:get_system_alerts" %}', function(data) {
|
|
var alertsHtml = '';
|
|
|
|
if (data.alerts.length === 0) {
|
|
alertsHtml = '<div class="text-center text-muted"><i class="fa fa-check-circle fs-48px mb-3"></i><p>No active alerts</p></div>';
|
|
} else {
|
|
data.alerts.forEach(function(alert) {
|
|
var alertClass = alert.severity === 'critical' ? 'danger' :
|
|
alert.severity === 'warning' ? 'warning' : 'info';
|
|
|
|
alertsHtml += '<div class="alert alert-' + alertClass + '">' +
|
|
'<div class="d-flex justify-content-between">' +
|
|
'<div>' +
|
|
'<h6>' + alert.title + '</h6>' +
|
|
'<p class="mb-0">' + alert.message + '</p>' +
|
|
'<small class="text-muted">' + alert.timestamp + '</small>' +
|
|
'</div>' +
|
|
'<div>' +
|
|
'<button class="btn btn-outline-secondary btn-sm" onclick="dismissAlert(\'' + alert.id + '\')">' +
|
|
'<i class="fa fa-times"></i>' +
|
|
'</button>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>';
|
|
});
|
|
}
|
|
|
|
$('#alertsContent').html(alertsHtml);
|
|
$('#alertsModal').modal('show');
|
|
});
|
|
}
|
|
|
|
function dismissAlert(alertId) {
|
|
$.post('{% url "core:dismiss_alert" %}', {alert_id: alertId}, function(data) {
|
|
if (data.success) {
|
|
showAlerts(); // Refresh alerts
|
|
toastr.success('Alert dismissed');
|
|
}
|
|
});
|
|
}
|
|
|
|
function showFullEventLog() {
|
|
$.get('{% url "core:get_system_events" %}', function(data) {
|
|
var eventsHtml = '<div class="table-responsive">' +
|
|
'<table class="table table-striped">' +
|
|
'<thead>' +
|
|
'<tr>' +
|
|
'<th>Time</th>' +
|
|
'<th>Event</th>' +
|
|
'<th>Severity</th>' +
|
|
'<th>Details</th>' +
|
|
'</tr>' +
|
|
'</thead>' +
|
|
'<tbody>';
|
|
|
|
data.events.forEach(function(event) {
|
|
var severityClass = event.severity === 'error' ? 'danger' :
|
|
event.severity === 'warning' ? 'warning' :
|
|
event.severity === 'info' ? 'info' : 'success';
|
|
|
|
eventsHtml += '<tr>' +
|
|
'<td>' + event.timestamp + '</td>' +
|
|
'<td>' + event.title + '</td>' +
|
|
'<td><span class="badge bg-' + severityClass + '">' + event.severity + '</span></td>' +
|
|
'<td>' + event.details + '</td>' +
|
|
'</tr>';
|
|
});
|
|
|
|
eventsHtml += '</tbody></table></div>';
|
|
|
|
$('#eventLogContent').html(eventsHtml);
|
|
$('#eventLogModal').modal('show');
|
|
});
|
|
}
|
|
|
|
function exportHealthReport() {
|
|
window.open('{% url "core:export_health_report" %}', '_blank');
|
|
toastr.success('Health report export started');
|
|
}
|
|
|
|
// Cleanup on page unload
|
|
$(window).on('beforeunload', function() {
|
|
if (refreshInterval) {
|
|
clearInterval(refreshInterval);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
.timeline {
|
|
position: relative;
|
|
padding-left: 30px;
|
|
}
|
|
|
|
.timeline-item {
|
|
position: relative;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.timeline-marker {
|
|
position: absolute;
|
|
left: -35px;
|
|
top: 5px;
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.timeline-item:not(:last-child)::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: -31px;
|
|
top: 15px;
|
|
width: 2px;
|
|
height: calc(100% + 10px);
|
|
background-color: #dee2e6;
|
|
}
|
|
|
|
.service-item {
|
|
padding: 10px;
|
|
border-radius: 5px;
|
|
transition: background-color 0.3s ease;
|
|
}
|
|
|
|
.service-item:hover {
|
|
background-color: #f8f9fa;
|
|
}
|
|
|
|
.progress {
|
|
height: 8px;
|
|
}
|
|
|
|
.card-tools {
|
|
margin-left: auto;
|
|
}
|
|
|
|
.fs-24px {
|
|
font-size: 24px;
|
|
}
|
|
|
|
.fs-48px {
|
|
font-size: 48px;
|
|
}
|
|
|
|
.fw-600 {
|
|
font-weight: 600;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|