dashboard stats

This commit is contained in:
usmannasir
2025-05-24 16:15:24 +05:00
parent 57499f4d12
commit e92a7892d8
4 changed files with 304 additions and 2 deletions

View File

@@ -647,7 +647,7 @@ app.controller('versionManagment', function ($scope, $http, $timeout) {
} else {
$scope.upgradelogBox = false;
$scope.upgradeLog = response.data.upgradeLog;
$timeout(getUpgradeStatus, 2000);
timeout(getUpgradeStatus, 2000);
}
}
@@ -866,4 +866,170 @@ app.controller('OnboardingCP', function ($scope, $http, $timeout, $window) {
}
};
});
app.controller('dashboardStatsController', function ($scope, $http, $timeout) {
// Card values
$scope.totalSites = 0;
$scope.totalWPSites = 0;
// Chart.js chart objects
var trafficChart, diskIOChart, cpuChart;
// Data arrays for live graphs
var trafficLabels = [], rxData = [], txData = [];
var diskLabels = [], readData = [], writeData = [];
var cpuLabels = [], cpuUsageData = [];
// For rate calculation
var lastRx = null, lastTx = null, lastDiskRead = null, lastDiskWrite = null, lastCPU = null;
var lastCPUTimes = null;
var pollInterval = 2000; // ms
var maxPoints = 30;
function pollDashboardStats() {
$http.get('/base/getDashboardStats').then(function(response) {
if (response.data.status === 1) {
$scope.totalSites = response.data.total_sites;
$scope.totalWPSites = response.data.total_wp_sites;
}
});
}
function pollTraffic() {
$http.get('/base/getTrafficStats').then(function(response) {
if (response.data.status === 1) {
var now = new Date();
var rx = response.data.rx_bytes;
var tx = response.data.tx_bytes;
if (lastRx !== null && lastTx !== null) {
var rxRate = (rx - lastRx) / (pollInterval / 1000); // bytes/sec
var txRate = (tx - lastTx) / (pollInterval / 1000);
trafficLabels.push(now.toLocaleTimeString());
rxData.push(rxRate);
txData.push(txRate);
if (trafficLabels.length > maxPoints) {
trafficLabels.shift(); rxData.shift(); txData.shift();
}
if (trafficChart) {
trafficChart.data.labels = trafficLabels.slice();
trafficChart.data.datasets[0].data = rxData.slice();
trafficChart.data.datasets[1].data = txData.slice();
trafficChart.update();
}
}
lastRx = rx; lastTx = tx;
}
});
}
function pollDiskIO() {
$http.get('/base/getDiskIOStats').then(function(response) {
if (response.data.status === 1) {
var now = new Date();
var read = response.data.read_bytes;
var write = response.data.write_bytes;
if (lastDiskRead !== null && lastDiskWrite !== null) {
var readRate = (read - lastDiskRead) / (pollInterval / 1000); // bytes/sec
var writeRate = (write - lastDiskWrite) / (pollInterval / 1000);
diskLabels.push(now.toLocaleTimeString());
readData.push(readRate);
writeData.push(writeRate);
if (diskLabels.length > maxPoints) {
diskLabels.shift(); readData.shift(); writeData.shift();
}
if (diskIOChart) {
diskIOChart.data.labels = diskLabels.slice();
diskIOChart.data.datasets[0].data = readData.slice();
diskIOChart.data.datasets[1].data = writeData.slice();
diskIOChart.update();
}
}
lastDiskRead = read; lastDiskWrite = write;
}
});
}
function pollCPU() {
$http.get('/base/getCPULoadGraph').then(function(response) {
if (response.data.status === 1 && response.data.cpu_times && response.data.cpu_times.length >= 4) {
var now = new Date();
var cpuTimes = response.data.cpu_times;
if (lastCPUTimes) {
var idle = cpuTimes[3];
var total = cpuTimes.reduce(function(a, b) { return a + b; }, 0);
var lastIdle = lastCPUTimes[3];
var lastTotal = lastCPUTimes.reduce(function(a, b) { return a + b; }, 0);
var idleDiff = idle - lastIdle;
var totalDiff = total - lastTotal;
var usage = totalDiff > 0 ? (100 * (1 - idleDiff / totalDiff)) : 0;
cpuLabels.push(now.toLocaleTimeString());
cpuUsageData.push(usage);
if (cpuLabels.length > maxPoints) {
cpuLabels.shift(); cpuUsageData.shift();
}
if (cpuChart) {
cpuChart.data.labels = cpuLabels.slice();
cpuChart.data.datasets[0].data = cpuUsageData.slice();
cpuChart.update();
}
}
lastCPUTimes = cpuTimes;
}
});
}
function setupCharts() {
var trafficCtx = document.getElementById('trafficChart').getContext('2d');
trafficChart = new Chart(trafficCtx, {
type: 'line',
data: {
labels: [],
datasets: [
{ label: 'RX (Bytes/sec)', data: [], borderColor: '#007bff', fill: false },
{ label: 'TX (Bytes/sec)', data: [], borderColor: '#28a745', fill: false }
]
},
options: { responsive: true, animation: false, scales: { y: { beginAtZero: true } } }
});
var diskCtx = document.getElementById('diskIOChart').getContext('2d');
diskIOChart = new Chart(diskCtx, {
type: 'line',
data: {
labels: [],
datasets: [
{ label: 'Read (Bytes/sec)', data: [], borderColor: '#17a2b8', fill: false },
{ label: 'Write (Bytes/sec)', data: [], borderColor: '#ffc107', fill: false }
]
},
options: { responsive: true, animation: false, scales: { y: { beginAtZero: true } } }
});
var cpuCtx = document.getElementById('cpuChart').getContext('2d');
cpuChart = new Chart(cpuCtx, {
type: 'line',
data: {
labels: [],
datasets: [
{ label: 'CPU Usage (%)', data: [], borderColor: '#dc3545', fill: false }
]
},
options: { responsive: true, animation: false, scales: { y: { beginAtZero: true, max: 100 } } }
});
}
// Initial setup
$timeout(function() {
setupCharts();
pollDashboardStats();
pollTraffic();
pollDiskIO();
pollCPU();
// Start polling
function pollAll() {
pollDashboardStats();
pollTraffic();
pollDiskIO();
pollCPU();
$timeout(pollAll, pollInterval);
}
pollAll();
}, 500);
});

View File

@@ -3,7 +3,6 @@
{% block title %}{% trans "Home - CyberPanel" %}{% endblock %}
{% block content %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
@@ -13,6 +12,57 @@
<p>{% trans "Use the tabs to navigate through the control panel." %}</p>
</div>
<!-- Dashboard Stats Section -->
<div ng-controller="dashboardStatsController" class="row" style="margin-bottom: 30px;">
<!-- Info Cards -->
<div class="col-md-3">
<div class="card text-white bg-primary mb-3" style="max-width: 18rem;">
<div class="card-header">Total Sites</div>
<div class="card-body">
<h5 class="card-title" style="font-size:2.5rem;">{$ totalSites $}</h5>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-info mb-3" style="max-width: 18rem;">
<div class="card-header">WordPress Sites</div>
<div class="card-body">
<h5 class="card-title" style="font-size:2.5rem;">{$ totalWPSites $}</h5>
</div>
</div>
</div>
<!-- Traffic Graph -->
<div class="col-md-6">
<div class="card mb-3">
<div class="card-header">Traffic (Bytes)</div>
<div class="card-body">
<canvas id="trafficChart" height="80"></canvas>
</div>
</div>
</div>
<!-- Disk IO Graph -->
<div class="col-md-6">
<div class="card mb-3">
<div class="card-header">Disk IO (Bytes)</div>
<div class="card-body">
<canvas id="diskIOChart" height="80"></canvas>
</div>
</div>
</div>
<!-- CPU Usage Graph -->
<div class="col-md-6">
<div class="card mb-3">
<div class="card-header">CPU Usage (%)</div>
<div class="card-body">
<canvas id="cpuChart" height="80"></canvas>
</div>
</div>
</div>
</div>
<!-- End Dashboard Stats Section -->
<!-- Chart.js CDN -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!--- Hide statistics for non-admins--->
<div class="mx-10 col-lg-9 panel col-md-push-50">

View File

@@ -15,4 +15,8 @@ urlpatterns = [
re_path(r'^runonboarding$', views.runonboarding, name='runonboarding'),
re_path(r'^UpgradeStatus$', views.upgradeStatus, name='UpgradeStatus'),
re_path(r'^upgradeVersion$', views.upgradeVersion, name='upgradeVersion'),
re_path(r'^getDashboardStats$', views.getDashboardStats, name='getDashboardStats'),
re_path(r'^getTrafficStats$', views.getTrafficStats, name='getTrafficStats'),
re_path(r'^getDiskIOStats$', views.getDiskIOStats, name='getDiskIOStats'),
re_path(r'^getCPULoadGraph$', views.getCPULoadGraph, name='getCPULoadGraph'),
]

View File

@@ -17,6 +17,7 @@ from manageServices.models import PDNSStatus
from django.views.decorators.csrf import ensure_csrf_cookie
from plogical.processUtilities import ProcessUtilities
from plogical.httpProc import httpProc
from websiteFunctions.models import Websites, WPSites
# Create your views here.
@@ -420,3 +421,84 @@ def RestartCyberPanel(request):
dic = {'status': 0, 'error_message': str(msg)}
json_data = json.dumps(dic)
return HttpResponse(json_data)
def getDashboardStats(request):
try:
total_sites = Websites.objects.count()
total_wp_sites = WPSites.objects.count()
data = {
'total_sites': total_sites,
'total_wp_sites': total_wp_sites,
'status': 1
}
return HttpResponse(json.dumps(data), content_type='application/json')
except Exception as e:
return HttpResponse(json.dumps({'status': 0, 'error_message': str(e)}), content_type='application/json')
def getTrafficStats(request):
try:
# Get network stats from /proc/net/dev (Linux)
rx = tx = 0
with open('/proc/net/dev', 'r') as f:
for line in f.readlines():
if 'lo:' in line:
continue
if ':' in line:
parts = line.split()
rx += int(parts[1])
tx += int(parts[9])
data = {
'rx_bytes': rx,
'tx_bytes': tx,
'status': 1
}
return HttpResponse(json.dumps(data), content_type='application/json')
except Exception as e:
return HttpResponse(json.dumps({'status': 0, 'error_message': str(e)}), content_type='application/json')
def getDiskIOStats(request):
try:
# Parse /proc/diskstats for all disks
read_sectors = 0
write_sectors = 0
sector_size = 512 # Most Linux systems use 512 bytes per sector
with open('/proc/diskstats', 'r') as f:
for line in f:
parts = line.split()
if len(parts) < 14:
continue
# parts[2] is device name, skip loopback/ram devices
dev = parts[2]
if dev.startswith('loop') or dev.startswith('ram'):
continue
# 6th and 10th columns: sectors read/written
read_sectors += int(parts[5])
write_sectors += int(parts[9])
data = {
'read_bytes': read_sectors * sector_size,
'write_bytes': write_sectors * sector_size,
'status': 1
}
return HttpResponse(json.dumps(data), content_type='application/json')
except Exception as e:
return HttpResponse(json.dumps({'status': 0, 'error_message': str(e)}), content_type='application/json')
def getCPULoadGraph(request):
try:
# Parse /proc/stat for the 'cpu' line
with open('/proc/stat', 'r') as f:
for line in f:
if line.startswith('cpu '):
parts = line.strip().split()
# parts[1:] are user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice
cpu_times = [float(x) for x in parts[1:]]
break
else:
cpu_times = []
data = {
'cpu_times': cpu_times,
'status': 1
}
return HttpResponse(json.dumps(data), content_type='application/json')
except Exception as e:
return HttpResponse(json.dumps({'status': 0, 'error_message': str(e)}), content_type='application/json')