resource usage graphs

This commit is contained in:
usmannasir
2025-05-02 15:44:36 +05:00
parent 4e70b379c2
commit 12ba18bac0
6 changed files with 432 additions and 3 deletions

View File

@@ -0,0 +1,52 @@
import psutil
import os
from plogical.processUtilities import ProcessUtilities
from plogical.acl import ACLManager
import plogical.CyberCPLogFileWriter as logging
def get_website_resource_usage(externalApp):
try:
user = externalApp
if not user:
return {'status': 0, 'error_message': 'User not found'}
# Get CPU and Memory usage using ps command
command = f"ps -u {user} -o pcpu,pmem | grep -v CPU | awk '{{cpu += $1; mem += $2}} END {{print cpu, mem}}'"
result = ProcessUtilities.outputExecutioner(command)
try:
cpu_percent, memory_percent = map(float, result.split())
except:
cpu_percent = 0
memory_percent = 0
# Get disk usage using du command
website_path = f"/home/{user}/public_html"
if os.path.exists(website_path):
# Get disk usage in MB
command = f"du -sm {website_path} | cut -f1"
disk_used = float(ProcessUtilities.outputExecutioner(command))
# Get total disk space
command = f"df -m {website_path} | tail -1 | awk '{{print $2}}'"
disk_total = float(ProcessUtilities.outputExecutioner(command))
# Calculate percentage
disk_percent = (disk_used / disk_total) * 100 if disk_total > 0 else 0
else:
disk_used = 0
disk_total = 0
disk_percent = 0
return {
'status': 1,
'cpu_usage': round(cpu_percent, 2),
'memory_usage': round(memory_percent, 2),
'disk_used': round(disk_used, 2),
'disk_total': round(disk_total, 2),
'disk_percent': round(disk_percent, 2)
}
except BaseException as msg:
logging.CyberCPLogFileWriter.writeToFile(f'Error in get_website_resource_usage: {str(msg)}')
return {'status': 0, 'error_message': str(msg)}

View File

@@ -0,0 +1,143 @@
// Resource Monitoring
let cpuChart, memoryChart, diskChart;
let cpuData = [], memoryData = [], diskData = [];
const maxDataPoints = 30;
function initializeCharts() {
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
callback: function(value) {
return value + '%';
}
}
}
},
animation: {
duration: 750
}
};
// CPU Chart
const cpuCtx = document.getElementById('cpuChart').getContext('2d');
cpuChart = new Chart(cpuCtx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'CPU Usage (%)',
data: [],
borderColor: '#2563eb',
backgroundColor: 'rgba(37, 99, 235, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.4
}]
},
options: chartOptions
});
// Memory Chart
const memoryCtx = document.getElementById('memoryChart').getContext('2d');
memoryChart = new Chart(memoryCtx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'Memory Usage (%)',
data: [],
borderColor: '#00b894',
backgroundColor: 'rgba(0, 184, 148, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.4
}]
},
options: chartOptions
});
// Disk Chart
const diskCtx = document.getElementById('diskChart').getContext('2d');
diskChart = new Chart(diskCtx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'Disk Usage (%)',
data: [],
borderColor: '#ff9800',
backgroundColor: 'rgba(255, 152, 0, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.4
}]
},
options: chartOptions
});
}
function updateCharts(data) {
const now = new Date();
const timeLabel = now.toLocaleTimeString();
// Update CPU Chart
cpuData.push(data.cpu_usage);
if (cpuData.length > maxDataPoints) cpuData.shift();
cpuChart.data.labels.push(timeLabel);
if (cpuChart.data.labels.length > maxDataPoints) cpuChart.data.labels.shift();
cpuChart.data.datasets[0].data = cpuData;
cpuChart.update('none'); // Use 'none' mode for better performance
// Update Memory Chart
memoryData.push(data.memory_usage);
if (memoryData.length > maxDataPoints) memoryData.shift();
memoryChart.data.labels.push(timeLabel);
if (memoryChart.data.labels.length > maxDataPoints) memoryChart.data.labels.shift();
memoryChart.data.datasets[0].data = memoryData;
memoryChart.update('none');
// Update Disk Chart
diskData.push(data.disk_percent);
if (diskData.length > maxDataPoints) diskData.shift();
diskChart.data.labels.push(timeLabel);
if (diskChart.data.labels.length > maxDataPoints) diskChart.data.labels.shift();
diskChart.data.datasets[0].data = diskData;
diskChart.update('none');
}
function fetchResourceUsage() {
$.ajax({
url: '/websites/get_website_resources/',
type: 'POST',
data: JSON.stringify({
'domain': $('#domainNamePage').text().trim()
}),
contentType: 'application/json',
success: function(data) {
if (data.status === 1) {
updateCharts(data);
} else {
console.error('Error fetching resource data:', data.error_message);
}
},
error: function(xhr, status, error) {
console.error('Failed to fetch resource usage:', error);
}
});
}
// Initialize charts when the page loads
$(document).ready(function() {
if (document.getElementById('cpuChart')) {
initializeCharts();
// Fetch resource usage every 5 seconds
setInterval(fetchResourceUsage, 5000);
// Initial fetch
fetchResourceUsage();
}
});

View File

@@ -0,0 +1,162 @@
// Resource Monitoring
let cpuChart, memoryChart, diskChart;
let cpuData = [], memoryData = [], diskData = [];
const maxDataPoints = 30;
function initializeCharts() {
// CPU Chart
const cpuCtx = document.getElementById('cpuChart').getContext('2d');
cpuChart = new Chart(cpuCtx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'CPU Usage (%)',
data: [],
borderColor: '#2563eb',
backgroundColor: 'rgba(37, 99, 235, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
callback: function(value) {
return value + '%';
}
}
}
}
}
});
// Memory Chart
const memoryCtx = document.getElementById('memoryChart').getContext('2d');
memoryChart = new Chart(memoryCtx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'Memory Usage (%)',
data: [],
borderColor: '#00b894',
backgroundColor: 'rgba(0, 184, 148, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
callback: function(value) {
return value + '%';
}
}
}
}
}
});
// Disk Chart
const diskCtx = document.getElementById('diskChart').getContext('2d');
diskChart = new Chart(diskCtx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'Disk Usage (%)',
data: [],
borderColor: '#ff9800',
backgroundColor: 'rgba(255, 152, 0, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
callback: function(value) {
return value + '%';
}
}
}
}
}
});
}
function updateCharts(data) {
const now = new Date();
const timeLabel = now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds();
// Update CPU Chart
cpuData.push(data.cpu_usage);
if (cpuData.length > maxDataPoints) cpuData.shift();
cpuChart.data.labels.push(timeLabel);
if (cpuChart.data.labels.length > maxDataPoints) cpuChart.data.labels.shift();
cpuChart.data.datasets[0].data = cpuData;
cpuChart.update();
// Update Memory Chart
memoryData.push(data.memory_usage);
if (memoryData.length > maxDataPoints) memoryData.shift();
memoryChart.data.labels.push(timeLabel);
if (memoryChart.data.labels.length > maxDataPoints) memoryChart.data.labels.shift();
memoryChart.data.datasets[0].data = memoryData;
memoryChart.update();
// Update Disk Chart
diskData.push(data.disk_percent);
if (diskData.length > maxDataPoints) diskData.shift();
diskChart.data.labels.push(timeLabel);
if (diskChart.data.labels.length > maxDataPoints) diskChart.data.labels.shift();
diskChart.data.datasets[0].data = diskData;
diskChart.update();
}
function fetchResourceUsage() {
$.ajax({
url: '/website/get_website_resources/',
type: 'POST',
data: JSON.stringify({
'domain': $('#domainNamePage').text()
}),
contentType: 'application/json',
success: function(data) {
if (data.status === 1) {
updateCharts(data);
}
},
error: function() {
console.error('Error fetching resource usage data');
}
});
}
// Initialize charts when the page loads
$(document).ready(function() {
initializeCharts();
// Fetch resource usage every 5 seconds
setInterval(fetchResourceUsage, 5000);
// Initial fetch
fetchResourceUsage();
});

View File

@@ -1,9 +1,9 @@
{% extends "baseTemplate/index.html" %} {% extends "baseTemplate/index.html" %}
{% load i18n %} {% load i18n %}
{% load static %}
{% block title %}{{ domain }} - CyberPanel{% endblock %} {% block title %}{{ domain }} - CyberPanel{% endblock %}
{% block content %} {% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} --> <!-- Current language: {{ LANGUAGE_CODE }} -->
@@ -222,6 +222,29 @@
</div> </div>
</div> </div>
<!-- Add Resource Usage Graphs -->
<div class="cyber-card">
<div class="cyber-section-title" style="margin-bottom:28px;">
<span style="display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border:1.5px solid #dbeafe;border-radius:8px;margin-right:12px;background:#f6faff;">
<svg width="26" height="26" viewBox="0 0 26 26" fill="none"><path d="M3 3V21H23" stroke="#222b38" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 16L9 10L13 14L23 4" stroke="#222b38" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</span>
<span>{% trans "Real-time Resource Usage" %}</span>
</div>
<div class="cyber-resource-row">
<div class="cyber-resource-col">
<canvas id="cpuChart" style="width:100%;height:200px;"></canvas>
</div>
<div class="cyber-resource-col">
<canvas id="memoryChart" style="width:100%;height:200px;"></canvas>
</div>
</div>
<div class="cyber-resource-row" style="margin-top:20px;">
<div class="cyber-resource-col">
<canvas id="diskChart" style="width:100%;height:200px;"></canvas>
</div>
</div>
</div>
<div class="example-box-wrapper my-10"> <div class="example-box-wrapper my-10">
<div class="panel panel-body"> <div class="panel panel-body">
<h3 class="content-box-header"> <h3 class="content-box-header">
@@ -1196,3 +1219,10 @@
{% endblock %} {% endblock %}
{% block footer_scripts %}
{{ block.super }}
<!-- Add Chart.js and resource monitoring script -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="{% static 'websiteFunctions/js/resource-monitoring.js' %}"></script>
{% endblock %}

View File

@@ -200,4 +200,6 @@ urlpatterns = [
# Catch all for domains # Catch all for domains
path('<domain>/<childDomain>', views.launchChild, name='launchChild'), path('<domain>/<childDomain>', views.launchChild, name='launchChild'),
path('<domain>', views.domain, name='domain'), path('<domain>', views.domain, name='domain'),
path('get_website_resources/', views.get_website_resources, name='get_website_resources'),
] ]

View File

@@ -2,11 +2,12 @@
from django.shortcuts import redirect from django.shortcuts import redirect
from django.http import HttpResponse from django.http import HttpResponse, JsonResponse
from loginSystem.models import Administrator from loginSystem.models import Administrator
from loginSystem.views import loadLoginPage from loginSystem.views import loadLoginPage
import json import json
import plogical.CyberCPLogFileWriter as logging import plogical.CyberCPLogFileWriter as logging
from plogical.acl import ACLManager
from plogical.httpProc import httpProc from plogical.httpProc import httpProc
@@ -17,6 +18,7 @@ from django.views.decorators.csrf import csrf_exempt
from .dockerviews import startContainer as docker_startContainer from .dockerviews import startContainer as docker_startContainer
from .dockerviews import stopContainer as docker_stopContainer from .dockerviews import stopContainer as docker_stopContainer
from .dockerviews import restartContainer as docker_restartContainer from .dockerviews import restartContainer as docker_restartContainer
from .resource_monitoring import get_website_resource_usage
def loadWebsitesHome(request): def loadWebsitesHome(request):
val = request.session['userID'] val = request.session['userID']
@@ -1882,4 +1884,42 @@ def restartContainer(request):
return docker_restartContainer(request) return docker_restartContainer(request)
return HttpResponse('Not allowed') return HttpResponse('Not allowed')
except KeyError: except KeyError:
return redirect(loadLoginPage) return redirect(loadLoginPage)
@csrf_exempt
def get_website_resources(request):
try:
data = json.loads(request.body)
domain = data['domain']
# Get userID from session
try:
userID = request.session['userID']
admin = Administrator.objects.get(pk=userID)
except:
return JsonResponse({'status': 0, 'error_message': 'Unauthorized access'})
# Verify domain ownership
currentACL = ACLManager.loadedACL(userID)
from websiteFunctions.models import Websites
try:
website = Websites.objects.get(domain=domain)
except Websites.DoesNotExist:
return JsonResponse({'status': 0, 'error_message': 'Website not found'})
if ACLManager.checkOwnership(domain, admin, currentACL) == 1:
pass
else:
return ACLManager.loadError()
# Get resource usage data using externalApp
resource_data = get_website_resource_usage(website.externalApp)
if resource_data['status'] == 0:
return JsonResponse(resource_data)
return JsonResponse(resource_data)
except BaseException as msg:
logging.CyberCPLogFileWriter.writeToFile(f'Error in get_website_resources: {str(msg)}')
return JsonResponse({'status': 0, 'error_message': str(msg)})