DEV Community

alexpaper
alexpaper

Posted on

NodeJs Socket.io Sys Monitor

I realized this simple system monitor project

Alt Text

I used Nodejs as backend server, ejs to render the frontend single page app, I also utilized socket.io for backend frontend comunication.

This is a simple step by step guide.

If you are interested you can check the youtube links bellow.
CPU-RAM-MON-part-1
CPU-RAM-MON-part-2
CPU-RAM-MON-part-3

First create the project folder:

mkdir nodejs-socket-io-sys-mon
cd nodejs-socket-io-sys-mon

Npm init

npm init

then create the folders structure

mkdir views public public/css public/js

then create the files

touch main.js views/index.ejs public/css/main.css public/js/main.js

Install dependencies

npm i express socket.io node-os-utils ejs

Run Visual studio code

code .

Change/add package.json start scripts

{
    "name": "nodejs-socket-io-sys-mon",
    "version": "1.0.0",
    "description": "",
    "main": "main.js",
    "scripts": {
        "start": "node main.js",
        "dev": "nodemon main.js"
    },
    "author": "",
    "license": "ISC",
    "dependencies": {
        "ejs": "^3.1.5",
        "express": "^4.17.1",
        "node-os-utils": "^1.3.0",
        "os": "^0.1.1",
        "socket.io": "^2.3.0"
    }
}

Start writing the backend code, open main.js

// REQUIRE NPM PACKAGES
const http = require('http');
const express = require('express');
const app = express();
const httpServer = http.createServer(app);
const osUtils = require('node-os-utils');
const os = require('os');
const io = require('socket.io')(httpServer);
// View Engine and static public folder
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/public'));
// Root Route
app.get('/', (req, res) => {
    res.render('index.ejs');
});
// CPU USAGE
const cpu = osUtils.cpu;
// USER and OS
const username = os.userInfo([{ encoding: 'buffer' }]).username;
const osInfo = os.type();
// SOCKET IO
io.on('connection', socket => {
    console.log(`${socket.id} connected`);
    // USE SET INTERVAL TO CHECK RAM USAGE EVERY SECOND
    setInterval(() => {
        // RAM USED tot - free
        let ramUsed = Math.round(os.totalmem()) - Math.round(os.freemem());
        // RAM percentage
        let ram = (ramUsed * 100 / Math.round(os.totalmem())).toFixed(0);
        // console.log(ram + '%')
        // CPU USAGE PERCENTAGE
        cpu.usage().then(cpu => socket.emit('ram-usage', { ram, cpu, username, osInfo }))
    }, 1000);
});

// Run the server
let PORT = 3001;
httpServer.listen(PORT, () => {
    console.log(`Server beating 💓 on port: ${PORT}`)
});

then the frontend index.ejs

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Notification</title>
    <link rel="stylesheet" href="./css/main.css">
    <link rel="icon" type="image/svg" href="./imgs/resources.svg">
</head>

<body>
    <a href="/catalog" class="home"><img class="home-svg" src="./imgs/home.svg" alt=""></a>
    <div class="content">
        <h1>OS Resurces Monitor</h1>
        <div class="user">Hello</div>
        <div class="os">OS Type</div>
        <!-- CPU  -->
        <label class="cpu-label" for="cpu">CPU 0%</label>
        <progress class="cpu-bar" id="cpu" value="10" min='0' max='100'></progress>
        <!-- RAM  -->
        <label class="ram-label" for="ram">RAM 0%</label>
        <progress class="ram-bar" id="ram" value="10" min='0' max='100'></progress>

    </div>

    <footer>width 💙 @gd</footer>
    <!-- SOCKET IO  -->
    <script src="/socket.io/socket.io.js" defer></script>
    <script src="./js/main.js" defer></script>
</body>

</html>

Now edit frontend main.js, add this code

// SOCKET IO
const socket = io();
// SELECT ELEMENTS
const labelRam = document.querySelector('.ram-label');
const progRam = document.querySelector('.ram-bar');
const labelCpu = document.querySelector('.cpu-label');
const progCpu = document.querySelector('.cpu-bar');
const user = document.querySelector('.user');
const os = document.querySelector('.os');

// ON CONNECT EVENT
socket.on('connect', () => {
    console.log('Connected');
});
// ON RAM USAGE EVENT
socket.on('ram-usage', ({ ram, cpu, username, osInfo }) => {
    // SHOW OS USER INFO
    user.innerHTML = `<span>Hello ${username}</span>`;
    os.innerHTML = `<span>OS type: ${osInfo === 'Windows_NT' ? 'Microsoft Windows' : osInfo}</span>`
        // Set ram label
    labelRam.innerHTML = `<span>RAM ${ram} % </span>`;
    // Set Ram bar
    progRam.value = ram;
    // Set cpu label
    labelCpu.innerHTML = `<span>CPU ${cpu} %</span>`
        // Set cpu bar
    progCpu.value = cpu;
    // Check
    if (cpu > 90) {
        notify(cpu)
    }
});

// NOTIFICATION FUNCTION
let notify = (info) => {
    // If granted
    if (Notification.permission === 'granted') {
        new Notification('Title', {
            body: `CPU over ${info} %`
        });
    }
    // If denied
    if (Notification.permission !== 'denied') {
        Notification.requestPermission()
            .then((permission) => {
                if (permission === 'granted') {
                    new Notification('Title', {
                        body: `CPU over ${info} %`
                    });
                };
            });
    };

};

It's almost done, just a little bit of styles...

@import url('https://fonts.googleapis.com/css2?family=Oswald&display=swap');
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Oswald', sans-serif;
    color: #808080;
}

h1 {
    font-size: 4rem;
    padding: 10px;
    margin: 10px auto;
}

.content {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
}

.user,
.os {
    font-size: 1.1rem;
    height: 30px;
}

label {
    margin: 5px auto;
}

progress {
    margin: 10px auto;
}

progress[value] {
    appearance: none;
}

progress[value]::-webkit-progress-value {
    background-image: -webkit-linear-gradient(-45deg, transparent 33%, rgba(0, 0, 0, .1) 33%, rgba(0, 0, 0, .1) 66%, transparent 66%), -webkit-linear-gradient(top, rgba(255, 255, 255, .25), rgba(0, 0, 0, .25)), -webkit-linear-gradient(left, #09c, #f44);
}

footer {
    position: fixed;
    bottom: 10px;
    text-align: center;
    padding: 10px;
    left: 50%;
    transform: translate(-50%);
}

.home {
    text-decoration: none;
    position: sticky;
    top: 10px;
    left: 50%;
    transform: translate(-50%);
}

.home .home-svg {
    width: 20px;
    display: inline-block;
}

@media (max-width: 768px) {
    h1 {
        font-size: 3rem;
    }
}

Done.👍
🖖

If you are intrested you can check the youtube links bellow.
CPU-RAM-MON-part-1
CPU-RAM-MON-part-2
CPU-RAM-MON-part-3

Latest comments (0)