From f3d886c451ceb0390eb52ce7a679ed88b3c35bf8 Mon Sep 17 00:00:00 2001 From: Ziya SARIKAYA Date: Tue, 23 Aug 2016 18:53:40 +0200 Subject: [PATCH] code refactoring --- app.js | 385 ++++++++++++++++++++++++++++++++++++++++++++ index.html | 379 ++++++++----------------------------------- index.js | 12 +- package.json | 2 +- sample/package.json | 2 +- style.css | 65 ++++++++ 6 files changed, 524 insertions(+), 321 deletions(-) create mode 100644 app.js create mode 100644 style.css diff --git a/app.js b/app.js new file mode 100644 index 0000000..ae205cf --- /dev/null +++ b/app.js @@ -0,0 +1,385 @@ +// Chart.defaults.global.defaultFontSize = 8; +// Chart.defaults.global.animation.duration = 500; +// Chart.defaults.global.legend.display = false; +// Chart.defaults.global.elements.line.backgroundColor = "rgba(0,0,0,0)"; +// Chart.defaults.global.elements.line.borderColor = "rgba(0,0,0,0.9)"; +// Chart.defaults.global.elements.line.borderWidth = 2; + +// var socket = io(location.protocol + '//' + location.hostname + ':' + location.port); +// var defaultSpan = 0; +// var spans = []; + +// var defaultDataset = { +// label: '', +// data: [], +// lineTension: 0.2, +// pointRadius: 0 +// }; + +// var defaultOptions = { +// scales: { +// yAxes: [{ +// ticks: { +// beginAtZero: true +// } +// }], +// xAxes: [{ +// type: 'time', +// time: { +// unitStepSize: 30 +// }, +// gridLines: { +// display: false +// } +// }] +// }, +// tooltips: { +// enabled: false +// }, +// responsive: true, +// maintainAspectRatio: false, +// animation: false +// }; + +// var createChart = function (ctx, dataset) { +// return new Chart(ctx, { +// type: 'line', +// data: { +// labels: [], +// datasets: dataset +// }, +// options: defaultOptions +// }); +// }; + +// var addTimestamp = function (point) { +// return point.timestamp; +// }; + +// var cpuDataset = [Object.create(defaultDataset)]; +// var memDataset = [Object.create(defaultDataset)]; +// var loadDataset = [Object.create(defaultDataset)]; +// var responseTimeDataset = [Object.create(defaultDataset)]; +// var rpsDataset = [Object.create(defaultDataset)]; + +// var cpuStat = document.getElementById('cpuStat'); +// var memStat = document.getElementById('memStat'); +// var loadStat = document.getElementById('loadStat'); +// var responseTimeStat = document.getElementById('responseTimeStat'); +// var rpsStat = document.getElementById('rpsStat'); + +// var cpuChartCtx = document.getElementById("cpuChart"); +// var memChartCtx = document.getElementById("memChart"); +// var loadChartCtx = document.getElementById("loadChart"); +// var responseTimeChartCtx = document.getElementById("responseTimeChart"); +// var rpsChartCtx = document.getElementById("rpsChart"); + +// var cpuChart = createChart(cpuChartCtx, cpuDataset); +// var memChart = createChart(memChartCtx, memDataset); +// var loadChart = createChart(loadChartCtx, loadDataset); +// var responseTimeChart = createChart(responseTimeChartCtx, responseTimeDataset); +// var rpsChart = createChart(rpsChartCtx, rpsDataset); + +// var charts = [cpuChart, memChart, loadChart, responseTimeChart, rpsChart]; + +// var onSpanChange = function (e) { +// e.target.classList.add('active'); +// defaultSpan = parseInt(e.target.id); + +// var otherSpans = document.getElementsByTagName('span'); +// for (var i = 0; i < otherSpans.length; i++) { +// if (otherSpans[i] !== e.target) otherSpans[i].classList.remove('active'); +// } + +// socket.emit('change'); +// }; + +// socket.on('start', function (data) { +// // Remove last element of Array because it contains malformed responses data. +// // To keep consistency we also remove os data. +// data[defaultSpan].responses.pop(); +// data[defaultSpan].os.pop(); + +// cpuStat.textContent = data[defaultSpan].os[data[defaultSpan].os.length - 1].cpu.toFixed(1) + '%'; +// cpuChart.data.datasets[0].data = data[defaultSpan].os.map(function (point) { +// return point.cpu; +// }); +// cpuChart.data.labels = data[defaultSpan].os.map(addTimestamp); + +// memStat.textContent = data[defaultSpan].os[data[defaultSpan].os.length - 1].memory.toFixed(1) + 'MB'; +// memChart.data.datasets[0].data = data[defaultSpan].os.map(function (point) { +// return point.memory; +// }); +// memChart.data.labels = data[defaultSpan].os.map(addTimestamp); + +// loadStat.textContent = data[defaultSpan].os[data[defaultSpan].os.length - 1].load[defaultSpan].toFixed(2); +// loadChart.data.datasets[0].data = data[defaultSpan].os.map(function (point) { +// return point.load[0]; +// }); +// loadChart.data.labels = data[defaultSpan].os.map(addTimestamp); + +// responseTimeStat.textContent = data[defaultSpan].responses[data[defaultSpan].responses.length - 1].mean.toFixed(2) + 'ms'; +// responseTimeChart.data.datasets[0].data = data[defaultSpan].responses.map(function (point) { +// return point.mean; +// }); +// responseTimeChart.data.labels = data[defaultSpan].responses.map(addTimestamp); + +// if (data[defaultSpan].responses.length >= 2) { +// var deltaTime = data[defaultSpan].responses[data[defaultSpan].responses.length - 1].timestamp - data[defaultSpan].responses[data[defaultSpan].responses.length - 2].timestamp; +// rpsStat.textContent = (data[defaultSpan].responses[data[defaultSpan].responses.length - 1].count / deltaTime * 1000).toFixed(2); +// rpsChart.data.datasets[0].data = data[defaultSpan].responses.map(function (point) { +// return point.count / deltaTime * 1000; +// }); +// rpsChart.data.labels = data[defaultSpan].responses.map(addTimestamp); +// } + +// charts.forEach(function (chart) { +// chart.update(); +// }); + +// var spanControls = document.getElementById('span-controls'); +// if (data.length !== spans.length) { +// data.forEach(function (span, index) { +// spans.push({ +// retention: span.retention, +// interval: span.interval +// }); + +// var spanNode = document.createElement('span'); +// var textNode = document.createTextNode((span.retention * span.interval) / 60 + "M"); +// spanNode.appendChild(textNode); +// spanNode.setAttribute('id', index); +// spanNode.onclick = onSpanChange; +// spanControls.appendChild(spanNode); +// }); +// document.getElementsByTagName('span')[0].classList.add('active'); +// } +// }); + +// socket.on('stats', function (data) { +// if (data.retention === spans[defaultSpan].retention && data.interval === spans[defaultSpan].interval) { +// cpuStat.textContent = data.os.cpu.toFixed(1) + '%'; +// cpuChart.data.datasets[0].data.push(data.os.cpu); +// cpuChart.data.labels.push(data.os.timestamp); + +// memStat.textContent = data.os.memory.toFixed(1) + 'MB'; +// memChart.data.datasets[0].data.push(data.os.memory); +// memChart.data.labels.push(data.os.timestamp); + +// loadStat.textContent = data.os.load[0].toFixed(2); +// loadChart.data.datasets[0].data.push(data.os.load[0]); +// loadChart.data.labels.push(data.os.timestamp); + +// responseTimeStat.textContent = data.responses.mean.toFixed(2) + 'ms'; +// responseTimeChart.data.datasets[0].data.push(data.responses.mean); +// responseTimeChart.data.labels.push(data.responses.timestamp); + +// var deltaTime = data.responses.timestamp - rpsChart.data.labels[rpsChart.data.labels.length - 1]; +// rpsStat.textContent = (data.responses.count / deltaTime * 1000).toFixed(2); +// rpsChart.data.datasets[0].data.push(data.responses.count / deltaTime * 1000); +// rpsChart.data.labels.push(data.responses.timestamp); + +// charts.forEach(function (chart) { +// if (spans[defaultSpan].retention < chart.data.labels.length) { +// chart.data.datasets[0].data.shift(); +// chart.data.labels.shift(); +// } + +// chart.update(); +// }); +// } +// }); + +'use strict'; + +Chart.defaults.global.defaultFontSize = 8; +Chart.defaults.global.animation.duration = 500; +Chart.defaults.global.legend.display = false; +Chart.defaults.global.elements.line.backgroundColor = "rgba(0,0,0,0)"; +Chart.defaults.global.elements.line.borderColor = "rgba(0,0,0,0.9)"; +Chart.defaults.global.elements.line.borderWidth = 2; + +var socket = io(location.protocol + '//' + location.hostname + ':' + location.port); +var defaultSpan = 0; +var spans = []; + +var defaultDataset = { + label: '', + data: [], + lineTension: 0.2, + pointRadius: 0 +}; + +var defaultOptions = { + scales: { + yAxes: [{ + ticks: { + beginAtZero: true + } + }], + xAxes: [{ + type: 'time', + time: { + unitStepSize: 30 + }, + gridLines: { + display: false + } + }] + }, + tooltips: { + enabled: false + }, + responsive: true, + maintainAspectRatio: false, + animation: false +}; + +var createChart = function (ctx, dataset) { + return new Chart(ctx, { + type: 'line', + data: { + labels: [], + datasets: dataset + }, + options: defaultOptions + }); +}; + +var addTimestamp = function(point) { + return point.timestamp; +}; + +var cpuDataset = [Object.create(defaultDataset)]; +var memDataset = [Object.create(defaultDataset)]; +var loadDataset = [Object.create(defaultDataset)]; +var responseTimeDataset = [Object.create(defaultDataset)]; +var rpsDataset = [Object.create(defaultDataset)]; + +var cpuStat = document.getElementById('cpuStat'); +var memStat = document.getElementById('memStat'); +var loadStat = document.getElementById('loadStat'); +var responseTimeStat = document.getElementById('responseTimeStat'); +var rpsStat = document.getElementById('rpsStat'); + +var cpuChartCtx = document.getElementById("cpuChart"); +var memChartCtx = document.getElementById("memChart"); +var loadChartCtx = document.getElementById("loadChart"); +var responseTimeChartCtx = document.getElementById("responseTimeChart"); +var rpsChartCtx = document.getElementById("rpsChart"); + +var cpuChart = createChart(cpuChartCtx, cpuDataset); +var memChart = createChart(memChartCtx, memDataset); +var loadChart = createChart(loadChartCtx, loadDataset); +var responseTimeChart = createChart(responseTimeChartCtx, responseTimeDataset); +var rpsChart = createChart(rpsChartCtx, rpsDataset); + +var charts = [cpuChart, memChart, loadChart, responseTimeChart, rpsChart]; + +var onSpanChange = function (e) { + e.target.classList.add('active'); + defaultSpan = parseInt(e.target.id); + + var otherSpans = document.getElementsByTagName('span'); + for (var i = 0; i < otherSpans.length; i++) { + if (otherSpans[i] !== e.target) otherSpans[i].classList.remove('active'); + } + + socket.emit('change'); +}; + +socket.on('start', function (data) { + // Remove last element of Array because it contains malformed responses data. + // To keep consistency we also remove os data. + data[defaultSpan].responses.pop(); + data[defaultSpan].os.pop(); + + cpuStat.textContent = data[defaultSpan].os[data[defaultSpan].os.length - 1].cpu.toFixed(1) + '%'; + cpuChart.data.datasets[0].data = data[defaultSpan].os.map(function (point) { + return point.cpu; + }); + cpuChart.data.labels = data[defaultSpan].os.map(addTimestamp); + + memStat.textContent = data[defaultSpan].os[data[defaultSpan].os.length - 1].memory.toFixed(1) + 'MB'; + memChart.data.datasets[0].data = data[defaultSpan].os.map(function (point) { + return point.memory; + }); + memChart.data.labels = data[defaultSpan].os.map(addTimestamp); + + loadStat.textContent = data[defaultSpan].os[data[defaultSpan].os.length - 1].load[defaultSpan].toFixed(2); + loadChart.data.datasets[0].data = data[defaultSpan].os.map(function (point) { + return point.load[0]; + }); + loadChart.data.labels = data[defaultSpan].os.map(addTimestamp); + + responseTimeStat.textContent = data[defaultSpan].responses[data[defaultSpan].responses.length - 1].mean.toFixed(2) + 'ms'; + responseTimeChart.data.datasets[0].data = data[defaultSpan].responses.map(function (point) { + return point.mean; + }); + responseTimeChart.data.labels = data[defaultSpan].responses.map(addTimestamp); + + if (data[defaultSpan].responses.length >= 2) { + var deltaTime = data[defaultSpan].responses[data[defaultSpan].responses.length - 1].timestamp - data[defaultSpan].responses[data[defaultSpan].responses.length - 2].timestamp; + rpsStat.textContent = (data[defaultSpan].responses[data[defaultSpan].responses.length - 1].count / deltaTime * 1000).toFixed(2); + rpsChart.data.datasets[0].data = data[defaultSpan].responses.map(function (point) { + return point.count / deltaTime * 1000; + }); + rpsChart.data.labels = data[defaultSpan].responses.map(addTimestamp); + } + + charts.forEach(function(chart) { + chart.update(); + }); + + var spanControls = document.getElementById('span-controls'); + if (data.length !== spans.length) { + data.forEach(function (span, index) { + spans.push({ + retention: span.retention, + interval: span.interval + }); + + var spanNode = document.createElement('span'); + var textNode = document.createTextNode((span.retention * span.interval) / 60 + "M"); + spanNode.appendChild(textNode); + spanNode.setAttribute('id', index); + spanNode.onclick = onSpanChange; + spanControls.appendChild(spanNode); + }); + document.getElementsByTagName('span')[0].classList.add('active'); + } +}); + +socket.on('stats', function (data) { + if (data.retention === spans[defaultSpan].retention && data.interval === spans[defaultSpan].interval) { + cpuStat.textContent = data.os.cpu.toFixed(1) + '%'; + cpuChart.data.datasets[0].data.push(data.os.cpu); + cpuChart.data.labels.push(data.os.timestamp); + + memStat.textContent = data.os.memory.toFixed(1) + 'MB'; + memChart.data.datasets[0].data.push(data.os.memory); + memChart.data.labels.push(data.os.timestamp); + + loadStat.textContent = data.os.load[0].toFixed(2); + loadChart.data.datasets[0].data.push(data.os.load[0]); + loadChart.data.labels.push(data.os.timestamp); + + responseTimeStat.textContent = data.responses.mean.toFixed(2) + 'ms'; + responseTimeChart.data.datasets[0].data.push(data.responses.mean); + responseTimeChart.data.labels.push(data.responses.timestamp); + + var deltaTime = data.responses.timestamp - rpsChart.data.labels[rpsChart.data.labels.length - 1]; + rpsStat.textContent = (data.responses.count / deltaTime * 1000).toFixed(2); + rpsChart.data.datasets[0].data.push(data.responses.count / deltaTime * 1000); + rpsChart.data.labels.push(data.responses.timestamp); + + charts.forEach(function (chart) { + if (spans[defaultSpan].retention < chart.data.labels.length) { + chart.data.datasets[0].data.shift(); + chart.data.labels.shift(); + } + + chart.update(); + }); + } +}); \ No newline at end of file diff --git a/index.html b/index.html index cae59b7..e9a432a 100644 --- a/index.html +++ b/index.html @@ -1,325 +1,72 @@ - - Hapi.js Status - - - + + {{title}} + + + + -
-
- Hapi.js Status -
-
-
-
-
-
CPU Usage
-

- %

+
+
+ {{title}} +
+
+
+
+
+
CPU Usage
+

- %

+
+
+ +
+
+
+
+
Memory Usage
+

- %

+
+
+ +
+
+
+
+
One Minute Load Avg
+

-

+
+
+ +
+
+
+
+
Response Time
+

-

+
+
+ +
+
+
+
+
Requests per Second
+

-

+
+
+ +
+
+
-
- -
-
-
-
-
Memory Usage
-

- %

-
-
- -
-
-
-
-
One Minute Load Avg
-

-

-
-
- -
-
-
-
-
Response Time
-

-

-
-
- -
-
-
-
-
Requests per Second
-

-

-
-
- -
-
- -
- + \ No newline at end of file diff --git a/index.js b/index.js index 35b1c97..b103ccf 100644 --- a/index.js +++ b/index.js @@ -11,6 +11,7 @@ const pidusage = require('pidusage'); let io; const defaults = { + title: 'Hapi.js Status', path: '/status', spans: [{ interval: 1, @@ -92,14 +93,19 @@ var register = function (server, options, next) { handler: (request, reply) => { fs.readFile(path.join(__dirname + '/index.html'), (err, statusView) => { if (err) throw err; - reply(statusView).header('Content-Type', 'text/html').code(200) + let renderedHtml = statusView.toString() + .replace(/{{title}}/g, options.title) + .replace(/{{script}}/g, fs.readFileSync(path.join(__dirname, '/app.js'))) + .replace(/{{style}}/g, fs.readFileSync(path.join(__dirname, '/style.css'))); + + reply(renderedHtml).header('Content-Type', 'text/html').code(200) }); } }); /* hook into the middle of processing */ - server.ext("onPreResponse", (request, reply) => { - let resp = request.response; + server.ext('onPreResponse', (request, reply) => { + const resp = request.response; let statusCode = resp.statusCode; const startTime = process.hrtime(); diff --git a/package.json b/package.json index 641b92a..187ecfb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hapijs-status-monitor", - "version": "0.2.0", + "version": "0.3.0", "description": "Monitoring plugin for Hapi.js applications", "main": "index.js", "keywords": [ diff --git a/sample/package.json b/sample/package.json index b3164dc..3501829 100644 --- a/sample/package.json +++ b/sample/package.json @@ -10,6 +10,6 @@ "author": "", "license": "ISC", "dependencies": { - "hapijs-status-monitor": "^0.1.0" + "hapijs-status-monitor": "^0.3.0" } } diff --git a/style.css b/style.css new file mode 100644 index 0000000..09d694b --- /dev/null +++ b/style.css @@ -0,0 +1,65 @@ + * { + font-family: Helvetica Neue, Helvetica, Arial, sans-serif; + } + + h1 { + font-size: 3em; + color: #222222; + margin: 0; + } + + h5 { + margin: 0; + color: #888888; + } + + p { + font-size: 0.7em; + color: #888888; + } + + span { + cursor: pointer; + font-size: 10px; + margin-left: 5px; + border: 1px solid #DDD; + padding: 3px 10px 4px 10px; + } + + canvas { + width: 400px; + height: 100px; + } + + .active { + background: #eeeeee; + } + + .stats-column { + flex: 0 0 200px; + } + + .container { + display: flex; + flex-direction: row; + margin-top: 20px; + height: 100px; + } + + .chart-container { + width: 400px; + height: 100px; + } + + .footer { + position: fixed; + margin: auto; + text-align: center; + left: 0; + right: 0; + bottom: 0; + } + + .span-controls { + float: right; + } \ No newline at end of file