How to Build a Django Server Performance Dashboard for CPU, Memory, and Process Monitoring
This guide walks through creating a Django‑based monitoring system that collects CPU, memory, and process metrics from MySQL, defines models, runs migrations, implements views that format data for Highcharts, builds HTML templates with interactive charts, configures URLs, and runs the server to display real‑time performance dashboards.
Monitoring System Overview
The article explains how to build a Django application that monitors server CPU, memory, and process information, stores the data in MySQL, and visualizes it with Highcharts.
1. Environment and Project Structure
Django 2.0.7, Python 3.7, and pymysql 0.9.3 are used. The project follows the standard Django layout with an app named web.
2. Settings Configuration
# Author: Allan
# Datetime: 2019-05-21
import pymysql
pymysql.install_as_MySQLdb()
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'database',
'USER': 'username',
'PASSWORD': 'password',
'HOST': 'ip',
'PORT': 3306,
}
}
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'web',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware', # disabled to avoid 403 errors
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'monitor.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
DEBUG = True
ALLOWED_HOSTS = ['*']
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False3. Models for CPU, Memory, and Process Data
from django.db import models
class CpuInfo(models.Model):
time = models.DateTimeField()
host = models.CharField(max_length=40)
usage_system = models.FloatField(null=True)
usage_user = models.FloatField(null=True)
usage_softirq = models.FloatField(null=True)
usage_iowait = models.FloatField(null=True)
class MemoryInfo(models.Model):
time = models.DateTimeField()
host = models.CharField(max_length=40)
used_percent = models.FloatField(null=True)
class ProcstatInfo(models.Model):
time = models.DateTimeField()
host = models.CharField(max_length=100)
exe = models.CharField(max_length=40)
pid = models.FloatField()
cpu_usage = models.FloatField(null=True)
memory_rss = models.FloatField(null=True)4. Database Migration
# python3 manager.py makemigrations web
# python3 manager.py migrate5. Views
# Author: Allan
# Datetime: 2019-05-21
import time, json
from django.shortcuts import render
from web import models
def show_procstat(request):
servers = ['rotestZone01', 'rotestZone02']
procstat_ret = {}
for server in servers:
procstat_info = models.ProcstatInfo.objects.filter(host=server)
procstat_exe = {}
for row in procstat_info:
temp_time = int(time.mktime(row.time.timetuple())) * 1000
key = f"{row.exe}_{int(row.pid)}"
if key not in procstat_exe:
procstat_exe[key] = {'cpu_usage': [], 'memory_rss': []}
procstat_exe[key]['cpu_usage'].append([temp_time, row.cpu_usage])
procstat_exe[key]['memory_rss'].append([temp_time, row.memory_rss])
procstat_ret[server] = procstat_exe
return render(request, 'show_procstat.html', {"procstat_ret": json.dumps(procstat_ret)})
def show_servers(request):
servers = ['rotestZone01', 'rotestZone02']
server_res = {}
cpu_res = {}
mem_res = {}
for server in servers:
cpu_info = models.CpuInfo.objects.filter(host=server)
cpu_ret = {'usage_system': [], 'usage_user': [], 'usage_softirq': [], 'usage_iowait': []}
for row in cpu_info:
temp_time = int(time.mktime(row.time.timetuple())) * 1000
cpu_ret['usage_system'].append([temp_time, row.usage_system])
cpu_ret['usage_user'].append([temp_time, row.usage_user])
cpu_ret['usage_softirq'].append([temp_time, row.usage_softirq])
cpu_ret['usage_iowait'].append([temp_time, row.usage_iowait])
cpu_res[server] = cpu_ret
mem_info = models.MemoryInfo.objects.filter(host=server)
mem_ret = []
for row in mem_info:
temp_time = int(time.mktime(row.time.timetuple())) * 1000
mem_ret.append([temp_time, row.used_percent])
mem_res[server] = mem_ret
server_res['cpu_res'] = cpu_res
server_res['mem_res'] = mem_res
return render(request, 'show_servers.html', {"server_res": json.dumps(server_res)})6. HTML Templates
<html>
<head>
<meta charset="UTF-8"/>
<title>Server Monitoring</title>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script>
$(document).ready(function () {
$("#servers").change(function () {
var selected = $(this).children('option:selected').val();
var server_res = jQuery.parseJSON('{{ server_res|safe }}');
var cpu_res = server_res['cpu_res'];
var cpu_info = cpu_res[selected];
Highcharts.setOptions({global:{useUTC:false}});
Highcharts.chart('cpu', {
chart:{zoomType:'x'},
title:{text:selected + ': CPU 信息'},
xAxis:{type:'datetime'},
yAxis:{title:{text:'使用率 (%)'}},
legend:{enabled:false},
plotOptions:{area:{fillColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,Highcharts.getOptions().colors[0]],[1,Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]]},marker:{radius:2},lineWidth:1,threshold:null}},
series:[
{type:'area',name:'usage_system',data:cpu_info['usage_system']},
{type:'area',name:'usage_user',data:cpu_info['usage_user']},
{type:'area',name:'usage_softirq',data:cpu_info['usage_softirq']},
{type:'area',name:'usage_iowait',data:cpu_info['usage_iowait']}
]
});
var mem_res = server_res['mem_res'];
var mem_info = mem_res[selected];
Highcharts.chart('mem', {
chart:{zoomType:'x'},
title:{text:selected + ': 内存信息'},
xAxis:{type:'datetime'},
yAxis:{title:{text:'使用率 (%)'}},
legend:{enabled:false},
plotOptions:{area:{fillColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,Highcharts.getOptions().colors[0]],[1,Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]]},marker:{radius:2},lineWidth:1,threshold:null}},
series:[{type:'area',name:'used_percent',data:mem_info}]
});
});
});
</script>
</head>
<body>
<div><h2>服务器监控信息</h2></div>
<select id="servers">
<option value="servers">请选择要监控的服务器</option>
<option value="rotestZone01">rotestZone01</option>
<option value="rotestZone02">rotestZone02</option>
</select>
<div id="cpu" style="width:1560px;height:400px;margin:0 auto"></div>
<div id="mem" style="width:1560px;height:400px;margin:0 auto"></div>
</body>
</html>7. URL Routing
# Author: Allan
# Datetime: 2019-05-21
from django.contrib import admin
from django.urls import path
from web import views
urlpatterns = [
# path('admin/', admin.site.urls),
path('show_servers', views.show_servers),
path('show_procstat', views.show_procstat),
]8. Running the Application
# python3 manager.py runserverAfter launching the server, open the URLs in a browser; the page displays interactive Highcharts graphs for CPU usage, memory usage, and per‑process statistics.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Full-Stack DevOps & Kubernetes
Focused on sharing DevOps, Kubernetes, Linux, Docker, Istio, microservices, Spring Cloud, Python, Go, databases, Nginx, Tomcat, cloud computing, and related technologies.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
