From 173b3898d0756310eedf4375a8d1d1650459b8f5 Mon Sep 17 00:00:00 2001 From: Matthew Colegate Date: Wed, 8 Feb 2017 15:48:11 +0000 Subject: [PATCH 1/2] Mirror AppMetrics Dashboard Layout --- public/css/style.css | 153 ++++++++++-------- public/css/style2.css | 122 +++++++++----- public/index.html | 55 ++++--- public/js/cpuChart.js | 138 ++++++++-------- public/js/envTable.js | 109 ++++++++----- public/js/httpRequestsChart.js | 137 ++++++++-------- public/js/httpThroughPutChart.js | 53 +++--- public/js/httpTop5.js | 53 +++--- public/js/memChart.js | 266 ++++++++++++++++--------------- 9 files changed, 610 insertions(+), 476 deletions(-) diff --git a/public/css/style.css b/public/css/style.css index 130fa50..f6d53f4 100755 --- a/public/css/style.css +++ b/public/css/style.css @@ -1,89 +1,118 @@ @viewport { - width: 320; + width: 320; } html { - background-color: #3b4b54; + background-color: #3b4b54; } body { - font: 12px Arial; - fill: white; - background-color: #3b4b54; + font: 12px Arial; + fill: white; } - h1 { - font: 26px Arial; - font-weight: bold; - text-align: center; - color: white; + .container-fluid { + background-color: #3b4b54; } - p { - font: 18px; - color: white; + h1 { + font: 26px Arial; + font-weight: bold; + text-align: center; + color: white; } svg { - margin: 3px; - background-color: #3f505a; + margin: 3px; + border: 1px solid #dfe6eb; } - #envDiv { - background-color: #3f505a; + .col-md-2, + .col-md-3, + .col-md-4, + .col-md-5, + .col-md-6 { + padding-right: 1px; + padding-left: 1px; + padding-top: 0px; + padding-bottom: 0px } .cpuChart path, .memChart path, .httpThroughPutChart path, .httpChart path { - stroke: #6decd7; - stroke-width: 2; - fill: none; + stroke: #00b4a0; + stroke-width: 2; + fill: none; + } + + path.line1 { + stroke: #00b4a0; + stroke-width: 2; + fill: none; + } + + path.line2, + path.processLine { + stroke: #95d13c; + stroke-width: 2; + fill: none; } + path.line3, + path.httpline { + stroke: #5aaafa; + stroke-width: 2; + fill: none; + } - .axis path, - .axis line { - fill: none; - stroke: grey; - stroke-width: 1; - shape-rendering: crispEdges; + g.xAxis path, + g.xAxis line, + g.yAxis path, + g.yAxis line { + fill: none; + stroke: white; + stroke-width: 1; + shape-rendering: crispEdges; + } + + g.tick line { + stroke: white; } .axis2 path, .axis2 line { - fill: none; - stroke: grey; - stroke-width: 1; - shape-rendering: crispEdges; + fill: none; + stroke: white; + stroke-width: 1; + shape-rendering: crispEdges; } - .legend { - font: 12px Arial; - font-weight: bold; - text-anchor: left; + .lineLabel, + .lineLabel2, + .avglatestlabel, + .minlatestlabel { + font: 14px Arial; + text-anchor: left; } - .grid .tick { - stroke: lightgrey; - stroke-opacity: 0.7; - shape-rendering: crispEdges; + .colourbox1 { + fill: #00b4a0; + stroke: #dbe6e9; + stroke-width: 1px; } - .grid path { - stroke-width: 0; + .colourbox2 { + fill: #95d13c; + stroke: #dbe6e9; + stroke-width: 1px; } - div.tooltip { - position: absolute; - text-align: center; - padding: 3px; - font: 12px sans-serif; - background: #b0f4e8; - border: 0px; - border-radius: 8px; - pointer-events: none; + .colourbox3 { + fill: #5aaafa; + stroke: #dbe6e9; + stroke-width: 1px; } .container { @@ -96,29 +125,27 @@ text-align: center; } - g.arc { - fill: #6decd7; + fill: #6decd7; } g.pointer { - fill: #959f9f; - stroke: #000000; + fill: #959f9f; + stroke: #000000; } g.label text { - text-anchor: middle; - text-align: center; - font-size: 12px; + text-anchor: middle; + text-align: center; + font-size: 12px; } - .urlChart rect { - fill: #6decd7; + .httpTop5Chart .bar { + fill: #5aaafa; } - th, td { - padding: 5px; - border-bottom: 1px solid #696969; - color: white; + .titlebox { + fill: #949394; + stroke: #dbe6e9; + stroke-width: 1px; } - diff --git a/public/css/style2.css b/public/css/style2.css index aad930f..cb469cd 100755 --- a/public/css/style2.css +++ b/public/css/style2.css @@ -1,5 +1,5 @@ @viewport { - width: 320; + width: 320; } html { @@ -7,36 +7,62 @@ } body { - font: 14px Arial; - fill: #3b4b54; + font: 12px Arial; + fill: #3b4b54; + } + + .container-fluid { + background-color: white; } h1 { - font: 26px Arial; - font-weight: bold; - text-align: center; - color: #3b4b54; + font: 26px Arial; + font-weight: bold; + text-align: center; + color: #3b4b54; } svg { - margin: 2px; - background-color: #f7f7f7; + margin: 3px; + border: 1px solid #dfe6eb; } - - #envDiv { - background-color: #f7f7f7; + + .col-md-2, + .col-md-3, + .col-md-4, + .col-md-5, + .col-md-6 { + padding-right: 1px; + padding-left: 1px; + padding-top: 0px; + padding-bottom: 0px } .cpuChart path, - .memChart path { - stroke: #6eedd8; + .memChart path, + .httpThroughPutChart path, + .httpChart path { + stroke: #00b4a0; + stroke-width: 2; + fill: none; + } + + path.line1 { + stroke: #00b4a0; + stroke-width: 2; + fill: none; + } + + path.line2, + path.processLine { + stroke: #734098; stroke-width: 2; fill: none; } - .httpChart path, - .httpThroughPutChart path { - stroke: #7cc7ff; + path.line3, + path.httpline { + stroke: #5aaafa; stroke-width: 2; fill: none; } @@ -45,10 +71,10 @@ g.xAxis line, g.yAxis path, g.yAxis line { - fill: none; - stroke: #42535c; - stroke-width: 1; - shape-rendering: crispEdges; + fill: none; + stroke: #42535c; + stroke-width: 1; + shape-rendering: crispEdges; } g.tick line { @@ -64,10 +90,29 @@ } .lineLabel, - .processlatestlabel { - font: 12px Arial; - font-weight: bold; - text-anchor: left; + .lineLabel2, + .avglatestlabel, + .minlatestlabel { + font: 14px Arial; + text-anchor: left; + } + + .colourbox1 { + fill: #00b4a0; + stroke: #dbe6e9; + stroke-width: 1px; + } + + .colourbox2 { + fill: #734098; + stroke: #dbe6e9; + stroke-width: 1px; + } + + .colourbox3 { + fill: #5aaafa; + stroke: #dbe6e9; + stroke-width: 1px; } .container { @@ -81,29 +126,26 @@ } g.arc { - fill: #6decd7; + fill: #6decd7; } g.pointer { - fill: #959f9f; - stroke: #000000; + fill: #959f9f; + stroke: #000000; } g.label text { - text-anchor: middle; - text-align: center; - font-size: 12px; + text-anchor: middle; + text-align: center; + font-size: 12px; } - .httpTop5Chart rect { - fill: #5aaafa; + .httpTop5Chart .bar { + fill: #5aaafa; } - table, th, td { - background-color: #f7f7f7; - } - th, td { - padding: 5px; - border-bottom: 1px solid #ddd; + .titlebox { + fill: #eff3f5; + stroke: #dbe6e9; + stroke-width: 1px; } - diff --git a/public/index.html b/public/index.html index a658c92..bc6f53a 100755 --- a/public/index.html +++ b/public/index.html @@ -10,19 +10,18 @@ -

Application Metrics Dashboard for Swift (Tech Preview)

+ - -
-
+
-
-
-
+
+
+
+
@@ -30,34 +29,41 @@

Application Metrics Dashboard for Swift (Tech Preview)

-
-
+ function getTimeFormat() { + var currentTime = new Date() + if(currentTime.getMinutes() - monitoringStartTime.getMinutes() >= 3 + || currentTime.getHours() > monitoringStartTime.getHours()) { + return d3.time.format("%H:%M"); + } else { + return d3.time.format("%H:%M:%S"); + } + } + @@ -71,17 +77,16 @@

Application Metrics Dashboard for Swift (Tech Preview)

window.addEventListener('resize', resize); function resize() { - canvasWidth = $("#cpuDiv1").width(), - httpCanvasWidth = $("#httpDiv1").width(), + canvasWidth = $("#cpuDiv1").width() - 8, + httpCanvasWidth = $("#httpDiv1").width() -8, graphWidth = canvasWidth - margin.left - margin.right, httpGraphWidth = httpCanvasWidth - margin.left - margin.right; resizeCPUChart(); resizeHttpChart(); resizeHttpThroughputChart(); - updateThroughPutData(); resizeHttpTop5Chart(); resizeMemChart(); - updateMemData(); + resizeEnvTable(); } diff --git a/public/js/cpuChart.js b/public/js/cpuChart.js index 4abe510..cb4e640 100644 --- a/public/js/cpuChart.js +++ b/public/js/cpuChart.js @@ -28,7 +28,7 @@ var cpu_xAxis = d3.svg.axis() .scale(cpu_xScale) .orient("bottom") .ticks(3) - .tickFormat(d3.time.format("%H:%M:%S")); + .tickFormat(getTimeFormat()); var cpu_yAxis = d3.svg.axis() .scale(cpu_yScale) @@ -45,9 +45,6 @@ var cpuProcessLatest = 0; var cpuSystemLatest = 0; -// Set input domain for y scale only (no data yet) -cpu_yScale.domain([0, 100]); - // Define the system CPU usage line var systemline = d3.svg.line().interpolate("basis") .x(function(d) { @@ -67,76 +64,84 @@ var processline = d3.svg.line().interpolate("basis") }); // Define the cpuChart -var cpuChart = d3.select("#cpuDiv1") - .append("svg") - .attr("width", canvasWidth) - .attr("height", canvasHeight) - .attr("class", "cpuChart") - .append("g") - .attr("class", "cpuGroup") - .attr("transform", - "translate(" + margin.left + "," + margin.top + ")"); +var cpuSVG = d3.select("#cpuDiv1") + .append("svg") + .attr("width", canvasWidth) + .attr("height", canvasHeight) + .attr("class", "cpuChart") + +var cpuTitleBox = cpuSVG.append("rect") + .attr("width", canvasWidth) + .attr("height", 30) + .attr("class", "titlebox") + +var cpuChart = cpuSVG.append("g") + .attr("class", "cpuGroup") + .attr("transform", + "translate(" + margin.left + "," + margin.top + ")"); + +// Set the input domain for the y axis (fixed) +cpu_yScale.domain([0, 100]); // Add the systemline path. cpuChart.append("path") - .attr("class", "systemLine") - .attr("d", systemline(cpuData)); + .attr("class", "systemLine") + .attr("d", systemline(cpuData)); // Add the processline path. cpuChart.append("path") - .attr("class", "processLine") - .style("stroke", "#8cd211") - .attr("d", processline(cpuData)); + .attr("class", "processLine") + .attr("d", processline(cpuData)); // Add the X Axis cpuChart.append("g") - .attr("class", "xAxis") - .attr("transform", "translate(0," + graphHeight + ")") - .call(cpu_xAxis); + .attr("class", "xAxis") + .attr("transform", "translate(0," + graphHeight + ")") + .call(cpu_xAxis); // Add the Y Axis cpuChart.append("g") - .attr("class", "yAxis") - .call(cpu_yAxis); + .attr("class", "yAxis") + .call(cpu_yAxis); // Add the title cpuChart.append("text") - .attr("x", -20) - .attr("y", 0 - (margin.top * 0.75)) - .attr("text-anchor", "left") - .style("font-size", "18px") - .text("CPU Usage"); + .attr("x", 7 - margin.left) + .attr("y", 15 - margin.top) + .attr("dominant-baseline", "central") + .style("font-size", "18px") + .text("CPU"); + +// Add the system colour box +cpuChart.append("rect") + .attr("x", 0) + .attr("y", graphHeight + margin.bottom - 15) + .attr("class", "colourbox1") + .attr("width", 10) + .attr("height", 10) // Add the SYSTEM label -cpuChart.append("text") - .attr("x", 0) - .attr("y", 0 - (margin.top / 8)) - .attr("class", "lineLabel") - .style("fill", "#6eedd8") - .text("SYSTEM"); +var cpuSystemLabel = cpuChart.append("text") + .attr("x", 15) + .attr("y", graphHeight + margin.bottom - 5) + .attr("text-anchor", "start") + .attr("class", "lineLabel") + .text("System"); + +// Add the process colour box +cpuChart.append("rect") + .attr("x", cpuSystemLabel.node().getBBox().width + 45) + .attr("y", graphHeight + margin.bottom - 15) + .attr("width", 10) + .attr("height", 10) + .attr("class", "colourbox2") // Add the PROCESS label cpuChart.append("text") - .attr("x", graphWidth / 2) - .attr("y", 0 - (margin.top / 8)) - .style("fill", "#8cd211") - .attr("class", "processlatestlabel") - .text("SWIFT PROCESS"); - -// Add the text element for systemlatest -cpuChart.append("text") - .attr("x", 0) - .attr("y", 0 - (margin.top * 3 / 8)) - .attr("class", "systemlatest") - .style("font-size", "32px"); - -// Add the text element for processlatest -cpuChart.append("text") - .attr("x", graphWidth / 2) - .attr("y", 0 - (margin.top * 3 / 8)) - .attr("class", "processlatest") - .style("font-size", "32px"); - + .attr("x", cpuSystemLabel.node().getBBox().width + 60) + .attr("y", graphHeight + margin.bottom - 5) + .attr("class", "lineLabel2") + .text("Node Process"); function resizeCPUChart() { var chart = d3.select(".cpuChart"); @@ -146,10 +151,10 @@ function resizeCPUChart() { .scale(cpu_xScale) .orient("bottom") .ticks(3) - .tickFormat(d3.time.format("%H:%M:%S")); + .tickFormat(getTimeFormat()); cpu_yAxis.tickSize(-graphWidth, 0, 0); - chart.select(".processlatest").attr("x", graphWidth / 2) - chart.select(".processlatestlabel").attr("x", graphWidth / 2) + + cpuTitleBox.attr("width", canvasWidth) // Redraw lines and axes cpu_xScale.domain(d3.extent(cpuData, function(d) { @@ -188,25 +193,28 @@ function updateCPUData() { cpuProcessLatest = _processLatest; cpuSystemLatest = Math.round(d.system); } - cpuData.push(d) + cpuData.push(d); } } // Only keep 30 minutes of data - var currentTime = Date.now() - var d = cpuData[0] + var currentTime = Date.now(); + var d = cpuData[0]; if (d === null) return while (d.hasOwnProperty('date') && d.date.valueOf() + 1800000 < currentTime) { - cpuData.shift() - d = cpuData[0] + cpuData.shift(); + d = cpuData[0]; } - // Set the input domain for the x axis (y is fixed) + // Set the input domain for the x axis cpu_xScale.domain(d3.extent(cpuData, function(d) { return d.date; })); + cpu_xAxis.tickFormat(getTimeFormat()); + + // Select the CPU chart svg element to apply changes var selection = d3.select(".cpuChart"); selection.select(".systemLine") .attr("d", systemline(cpuData)); @@ -216,10 +224,6 @@ function updateCPUData() { .call(cpu_xAxis); selection.select(".yAxis") .call(cpu_yAxis); - selection.select(".processlatest") - .text(cpuProcessLatest + "%"); - selection.select(".systemlatest") - .text(cpuSystemLatest + "%"); }); } diff --git a/public/js/envTable.js b/public/js/envTable.js index f8407e9..811df13 100644 --- a/public/js/envTable.js +++ b/public/js/envTable.js @@ -18,53 +18,76 @@ var request = "http://" + myurl + "/envRequest"; -d3.select('#envDiv').append('p') - .style("font-size", "18px") - .style("padding-left", "45px") - .style("padding-top", "20px") - .style("padding-bottom", "5px") - .text("Environment"); -var paragraph = d3.select('#envDiv').append('p') - .style("padding-left", "40px") -var table = paragraph.append('table') - .style("font-size", "14px"); -var thead = table.append('thead') -var tbody = table.append('tbody'); - - + +var tableRowHeight = 30; +var tableRowWidth = 170; + +// Define the environment chart space +var envSVG = d3.select("#envDiv") + .append("svg") + .attr("width", canvasWidth) + .attr("height", canvasHeight) + .attr("class", "envData") + +var envTitleBox = envSVG.append("rect") + .attr("width", canvasWidth) + .attr("height", 30) + .attr("class", "titlebox") + +envSVG.append("text") + .attr("x", 7) + .attr("y", 15) + .attr("dominant-baseline", "central") + .style("font-size", "18px") + .text("Environment"); + +var paragraph = envSVG.append("g") + .attr("class", "envGroup") + .attr("transform", + "translate(" + 20 + "," + (margin.top + 10) + ")"); function populateEnvTable() { - d3.json(request, function (error,data) { - if (error) return console.warn(error); - - if (data == null) - return - function tabulate(data) { - - // create a row for each object in the data - var rows = tbody.selectAll('tr') - .data(data) - .enter() - .append('tr'); - - // create a cell in each row for each column - var cells = rows.selectAll('td') - .data(function (row) { - return ['Parameter', 'Value'].map(function (column) { - return {column: column, value: row[column]}; - }); - }) - .enter() - .append('td') - .text(function (d) { return d.value; }); - - return table; - } + d3.json(request, function (error,data) { + + if (error) return console.warn(error); + if (data == null) return + + function tabulate(data) { + + // create a row for each object in the data + var rows = paragraph.selectAll('text') + .data(data) + .enter() + .append('text') + .style('font-size', '14px') + .attr("transform", function(d, i) { + return "translate(0," + (i * tableRowHeight) + ")"; + }); + + // create a cell in each row for each column + var cells = rows.selectAll('tspan') + .data(function (row) { + return ['Parameter', 'Value'].map(function (column) { + return {column: column, value: row[column]}; + }); + }) + .enter() + .append('tspan') + .attr("x", function(d, i) { + return i * tableRowWidth; // indent second element for each row + }) + .text(function (d) { return d.value; }); + } - // render the table(s) - tabulate(data); // 2 column table + // render the table(s) + tabulate(data); // 2 column table + + }); +} - }); +function resizeEnvTable() { + envSVG.attr("width", canvasWidth); + envTitleBox.attr("width", canvasWidth) } setTimeout(setInterval(populateEnvTable(), 1200000), 3000); diff --git a/public/js/httpRequestsChart.js b/public/js/httpRequestsChart.js index 5494055..de660b1 100755 --- a/public/js/httpRequestsChart.js +++ b/public/js/httpRequestsChart.js @@ -25,7 +25,7 @@ var http_xAxis = d3.svg.axis() .scale(http_xScale) .orient("bottom") .ticks(3) - .tickFormat(d3.time.format("%H:%M:%S"));; + .tickFormat(getTimeFormat()); var http_yAxis = d3.svg.axis() .scale(http_yScale) @@ -46,24 +46,30 @@ var httpline = d3.svg.line() return http_yScale(d.duration); }); -var httpChart = d3.select("#httpDiv1") +var httpSVG = d3.select("#httpDiv1") .append("svg") .attr("width", httpCanvasWidth) .attr("height", canvasHeight) - .attr("class", "httpChart").on("mouseover", function() { + .attr("class", "httpChart") + .on("mouseover", function() { mouseOverHttpGraph = true; - }) + }) .on("mouseout", function() { mouseOverHttpGraph = false; }) - .append("g") + +var httpTitleBox = httpSVG.append("rect") + .attr("width", httpCanvasWidth) + .attr("height", 30) + .attr("class", "titlebox") + +var httpChart = httpSVG.append("g") .attr("transform", - "translate(" + margin.left + "," + margin.shortTop + ")"); + "translate(" + margin.left + "," + margin.top + ")"); // Create the line httpChart.append("path") .attr("class", "httpline") - .style("stroke", "#7cc7ff") .attr("d", httpline(httpData)); // Define the axes @@ -78,76 +84,70 @@ httpChart.append("g") // Add the title httpChart.append("text") - .attr("x", -20) - .attr("y", 0 - (margin.shortTop * 0.5)) - .attr("text-anchor", "left") + .attr("x", 7 - margin.left) + .attr("y", 15 - margin.top) .attr("dominant-baseline", "central") .style("font-size", "18px") - .text("HTTP Response Time"); + .text("HTTP Incoming Requests"); function updateHttpData() { - if(!mouseOverHttpGraph) { - request = "http://" + myurl + "/httpRequest"; - d3.json(request, function(error, data) { - if (error) return console.warn(error); - - if (data == null) - return - - for (var i = 0, len = data.length; i < len; i++) { - var d = data[i]; - if (d != null && d.hasOwnProperty('time')) { - d.date = new Date(+d.time); - d.responseTime = Math.round(+d.duration) - httpData.push(d) - var urlStats = httpAverages[d.url] - if(urlStats != null) { - var averageResponseTime = urlStats[0] - var hits = urlStats[1] - // Recalculate the average - httpAverages[d.url] = [(averageResponseTime * hits + parseFloat(d.duration))/(hits + 1), hits + 1] - } else { - httpAverages[d.url] = [parseFloat(d.duration), 1] - } - } - } - - // Only keep 30 minutes or 2000 items of data - var currentTime = Date.now() - var d = httpData[0] - var needToRecaulcateMa - while (httpData.length > 2000 || (d.hasOwnProperty('date') && d.date.valueOf() + 1800000 < currentTime)) { - // - httpData.shift() - d = httpData[0] + request = "http://" + myurl + "/httpRequest"; + d3.json(request, function(error, data) { + + if (error) return console.warn(error); + if (data == null) return; + + for (var i = 0, len = data.length; i < len; i++) { + var d = data[i]; + if (d != null && d.hasOwnProperty('time')) { + d.date = new Date(+d.time); + d.responseTime = Math.round(+d.duration) + httpData.push(d) + var urlStats = httpAverages[d.url] + if(urlStats != null) { + var averageResponseTime = urlStats[0] + var hits = urlStats[1] + // Recalculate the average + httpAverages[d.url] = [(averageResponseTime * hits + parseFloat(d.duration))/(hits + 1), hits + 1] + } else { + httpAverages[d.url] = [parseFloat(d.duration), 1] + } } - - - //calculate the new http rate - var timeDifference = httpData[httpData.length -1].date - httpData[0].date; - if (timeDifference > 0) { - var averageRate = httpData.length * 1000 / timeDifference - httpRate.push({httpRate:averageRate, time:httpData[httpData.length -1].date}) - } - + } + + // Only keep 30 minutes or 2000 items of data + var currentTime = Date.now() + var d = httpData[0] + while (httpData.length > 2000 || (d.hasOwnProperty('date') && d.date.valueOf() + 1800000 < currentTime)) { + httpData.shift() + d = httpData[0] + } + + //calculate the new http rate + var timeDifference = httpData[httpData.length -1].date - httpData[0].date; + if (timeDifference > 0) { + var averageRate = httpData.length * 1000 / timeDifference + httpRate.push({httpRate:averageRate, time:httpData[httpData.length -1].date}) + } + + d = httpRate[0] + while (httpRate.length > 2000 || (d.hasOwnProperty('time') && d.time.valueOf() + 1800000 < currentTime)) { + httpRate.shift() d = httpRate[0] - while (httpRate.length > 2000 || (d.hasOwnProperty('time') && d.time.valueOf() + 1800000 < currentTime)) { - httpRate.shift() - d = httpRate[0] - } - + } + // Don't redraw graph if mouse is over it (keeps it still for tooltips) + if(!mouseOverHttpGraph) { // Set the input domain for x and y axes http_xScale.domain(d3.extent(httpData, function(d) { return d.date; })); http_yScale.domain([0, d3.max(httpData, function(d) { - return d.responseTime; + return d.duration; })]); - + http_xAxis.tickFormat(getTimeFormat()); var selection = d3.select(".httpChart"); selection.selectAll("circle").remove(); - selection.select(".httpline") .attr("d", httpline(httpData)); selection.select(".xAxis") @@ -162,13 +162,12 @@ function updateHttpData() { .style("fill", "#5aaafa") .style("stroke", "white") .attr("transform", - "translate(" + margin.left + "," + margin.shortTop + ")") + "translate(" + margin.left + "," + margin.top + ")") .attr("cx", function(d) { return http_xScale(d.date); }) .attr("cy", function(d) { return http_yScale(d.duration); }) .append("svg:title").text(function(d) { return d.url; }); // tooltip - - }); - } + } + }); } function resizeHttpChart() { @@ -180,7 +179,9 @@ function resizeHttpChart() { .scale(http_xScale) .orient("bottom") .ticks(3) - .tickFormat(d3.time.format("%H:%M:%S")); + .tickFormat(getTimeFormat()); + + httpTitleBox.attr("width", httpCanvasWidth) http_xScale.domain(d3.extent(httpData, function(d) { return d.date; @@ -201,7 +202,7 @@ function resizeHttpChart() { .style("fill", "#5aaafa") .style("stroke", "white") .attr("transform", - "translate(" + margin.left + "," + margin.shortTop + ")") + "translate(" + margin.left + "," + margin.top + ")") .attr("cx", function(d) { return http_xScale(d.date); }) .attr("cy", function(d) { return http_yScale(d.duration); }) .append("svg:title").text(function(d) { return d.url; }); diff --git a/public/js/httpThroughPutChart.js b/public/js/httpThroughPutChart.js index 8151b01..5052dd8 100755 --- a/public/js/httpThroughPutChart.js +++ b/public/js/httpThroughPutChart.js @@ -16,13 +16,19 @@ // Line chart for displaying average http request response time at a given point in time -//set the scale dimensions to the size of the graph -var httpTP_xScale = d3.time.scale().range([0, graphWidth]); +var httpDiv2CanvasWidth = $("#httpDiv2").width() - 8; // minus 8 for margin + // and border +var httpDiv2GraphWidth = httpDiv2CanvasWidth - margin.left - margin.right; + +// set the scale dimensions to the size of the graph +var httpTP_xScale = d3.time.scale().range([0, httpDiv2GraphWidth]); var httpTP_yScale = d3.scale.linear().range([tallerGraphHeight, 0]); // x axis format var httpTP_xAxis = d3.svg.axis().scale(httpTP_xScale) - .orient("bottom").ticks(3).tickFormat(d3.time.format("%H:%M:%S")); + .orient("bottom") + .ticks(3) + .tickFormat(d3.time.format("%H:%M:%S")); // y axis format, in requests per second var httpTP_yAxis = d3.svg.axis().scale(httpTP_yScale) @@ -40,28 +46,34 @@ var httpThroughPutline = d3.svg.line() }); // create the chart canvas -var httpThroughPutChart = d3.select("#httpDiv2") +var httpThroughPutSVG = d3.select("#httpDiv2") .append("svg") - .attr("width", canvasWidth) + .attr("width", httpDiv2CanvasWidth) .attr("height", canvasHeight) .attr("class", "httpThroughPutChart") - .append("g") + +var httpThroughPutTitleBox = httpThroughPutSVG.append("rect") + .attr("width", canvasWidth) + .attr("height", 30) + .attr("class", "titlebox") + +var httpThroughPutChart = httpThroughPutSVG.append("g") .attr("transform", - "translate(" + margin.left + "," + margin.shortTop + ")"); + "translate(" + margin.left + "," + margin.top + ")"); // Scale the X range to the time period we have data for httpTP_xScale.domain(d3.extent(httpRate, function(d) { return d.time; })); -//Scale the Y range from 0 to the maximum http rate +// Scale the Y range from 0 to the maximum http rate httpTP_yScale.domain([0, d3.max(httpRate, function(d) { return d.httpRate; })]); -//The data line +// The data line httpThroughPutChart.append("path") - .attr("class", "line") + .attr("class", "httpline") .attr("d", httpThroughPutline(httpRate)); // X axis line @@ -77,9 +89,9 @@ httpThroughPutChart.append("g") // Chart title httpThroughPutChart.append("text") - .attr("x", -20) - .attr("y", 0 - (margin.shortTop * 0.5)) - .attr("text-anchor", "left") + .attr("x", 7 - margin.left) + .attr("y", 15 - margin.top) + .attr("dominant-baseline", "central") .style("font-size", "18px") .text("HTTP Throughput"); @@ -96,7 +108,7 @@ function updateThroughPutData() { // update the data and axes lines to the new data values var selection = d3.select(".httpThroughPutChart"); - selection.select(".line") + selection.select(".httpline") .attr("d", httpThroughPutline(httpRate)); selection.select(".xAxis") .call(httpTP_xAxis); @@ -106,13 +118,18 @@ function updateThroughPutData() { } function resizeHttpThroughputChart() { - //only altering the horizontal for the moment + httpDiv2CanvasWidth = $("#httpDiv2").width() - 8; + httpDiv2GraphWidth = httpDiv2CanvasWidth - margin.left - margin.right; + + // only altering the horizontal for the moment var chart = d3.select(".httpThroughPutChart") - chart.attr("width", canvasWidth); - httpTP_xScale = d3.time.scale().range([0, graphWidth]); + chart.attr("width", httpDiv2CanvasWidth); + httpTP_xScale = d3.time.scale().range([0, httpDiv2GraphWidth]); httpTP_xAxis = d3.svg.axis().scale(httpTP_xScale) .orient("bottom").ticks(3).tickFormat(d3.time.format("%H:%M:%S")); + httpThroughPutTitleBox.attr("width", httpDiv2CanvasWidth) + // Re-scale the x range to the new time interval httpTP_xScale.domain(d3.extent(httpRate, function(d) { return d.time; @@ -125,7 +142,7 @@ function resizeHttpThroughputChart() { // update the data and axes lines to the new data values var selection = d3.select(".httpThroughPutChart"); - selection.select(".line") + selection.select(".httpline") .attr("d", httpThroughPutline(httpRate)); selection.select(".xAxis") .call(httpTP_xAxis); diff --git a/public/js/httpTop5.js b/public/js/httpTop5.js index af7ff08..44c7906 100644 --- a/public/js/httpTop5.js +++ b/public/js/httpTop5.js @@ -16,52 +16,59 @@ // Bar chart for top 5 URLs by average request time -var data = []; +var httpTop5Data = []; var httpTop5_barHeight = tallerGraphHeight / 5; -var httpDiv3CanvasWidth = $("#httpDiv3").width(); +var httpDiv3CanvasWidth = $("#httpDiv3").width() - 8; // -8 for margin and border var httpDiv3GraphWidth = httpDiv3CanvasWidth - margin.left - margin.right; var httpTop5_xScale = d3.scale.linear().range([0, httpDiv3GraphWidth]); - -var httpTop5Chart = d3.select("#httpDiv3") +var httpTop5SVG = d3.select("#httpDiv3") .append("svg") .attr("width", httpDiv3CanvasWidth) .attr("height", canvasHeight) .attr("class", "httpTop5Chart") - .append("g") - .attr("transform", - "translate(" + margin.left + "," + margin.shortTop + ")"); + +var httpTop5TitleBox = httpTop5SVG.append("rect") + .attr("width", httpDiv3CanvasWidth) + .attr("height", 30) + .attr("class", "titlebox") + +var httpTop5Chart = httpTop5SVG.append("g") + .attr("transform", + "translate(" + margin.left + "," + margin.top + ")"); // Add the title httpTop5Chart.append("text") - .attr("x", -20) - .attr("y", 0 - (margin.shortTop * 0.5)) - .attr("text-anchor", "left") + .attr("x", 7 - margin.left) + .attr("y", 15 - margin.top) + .attr("dominant-baseline", "central") .style("font-size", "18px") .text("Average Response Times (top 5)"); function convertURL(url) { if (url.toString().startsWith("http://" + myurl)) { return url.toString().substring(myurl.length + 7) + } else { + return url.toString() } } function updateChart() { - httpTop5_xScale.domain([0, d3.max(data, function(d) { + httpTop5_xScale.domain([0, d3.max(httpTop5Data, function(d) { return d.averageResponseTime; })]) var bars = d3.select(".httpTop5Chart").selectAll(".bar").remove(); var bar = d3.select(".httpTop5Chart").selectAll(".bar") - .data(data) + .data(httpTop5Data) .enter().append("g").attr("class", "bar") .attr("transform", function(d, i) { - return "translate(50," + (margin.shortTop + i * httpTop5_barHeight) + ")"; + return "translate(50," + (margin.top + i * httpTop5_barHeight) + ")"; }); // Background @@ -102,7 +109,7 @@ function updateChart() { updateChart(); function updateHttpAverages(workingData) { - data = workingData.sort(function(a, b) { + httpTop5Data = workingData.sort(function(a, b) { if (a.averageResponseTime > b.averageResponseTime) { return -1; } @@ -112,28 +119,28 @@ function updateHttpAverages(workingData) { // a must be equal to b return 0; }); - if (data.length > 5) { - data = data.slice(0, 5); + if (httpTop5Data.length > 5) { + httpTop5Data = httpTop5Data.slice(0, 5); } updateChart(); } function updateURLData() { - var workingData = [] - for (urlValue in httpAverages) { - workingData.push({url:urlValue, averageResponseTime:httpAverages[urlValue][0]}) - } - updateHttpAverages(workingData); + var workingData = [] + for (urlValue in httpAverages) { + workingData.push({url:urlValue, averageResponseTime:httpAverages[urlValue][0]}) + } + updateHttpAverages(workingData); } function resizeHttpTop5Chart() { - httpDiv3CanvasWidth = $("#httpDiv3").width(); + httpDiv3CanvasWidth = $("#httpDiv3").width() - 8; httpDiv3GraphWidth = httpDiv3CanvasWidth - margin.left - margin.right; httpTop5_xScale = d3.scale.linear().range([0, httpDiv3GraphWidth]); var chart = d3.select(".httpTop5Chart") chart.attr("width", httpDiv3CanvasWidth); + httpTop5TitleBox.attr("width", httpDiv3CanvasWidth) updateChart(); } - setInterval(updateURLData, 2000); diff --git a/public/js/memChart.js b/public/js/memChart.js index 58f4059..3216012 100644 --- a/public/js/memChart.js +++ b/public/js/memChart.js @@ -22,12 +22,14 @@ var mem_xScale = d3.time.scale().range([0, graphWidth]); var mem_yScale = d3.scale.linear().range([graphHeight, 0]); var mem_xAxis = d3.svg.axis().scale(mem_xScale) - .orient("bottom").ticks(3).tickFormat(d3.time.format("%H:%M:%S")); + .orient("bottom") + .ticks(3) + .tickFormat(getTimeFormat()); var mem_yAxis = d3.svg.axis().scale(mem_yScale) - .orient("left").ticks(8).tickFormat(function(d) { - return d + "MB"; - }); + .orient("left").ticks(8).tickFormat(function(d) { + return d + "MB"; + }); // Memory data storage var memData = []; @@ -36,111 +38,119 @@ var memSystemLatest = 0; // Set input domain for both x and y scales mem_xScale.domain(d3.extent(memData, function(d) { - return d.date; + return d.date; })); mem_yScale.domain([0, Math.ceil(d3.extent(memData, function(d) { - return d.system; + return d.system; })[1] / 100) * 100]); // Define the process memory line var mem_processLine = d3.svg.line() - .x(function(d) { - return mem_xScale(d.date); - }) - .y(function(d) { - return mem_yScale(d.process); - }); + .x(function(d) { + return mem_xScale(d.date); + }) + .y(function(d) { + return mem_yScale(d.process); + }); // Define the system memory line var mem_systemLine = d3.svg.line() - .x(function(d) { - return mem_xScale(d.date); - }) - .y(function(d) { - return mem_yScale(d.system); - }); - -// Define the memChart -var memChart = d3.select("#memDiv1") - .append("svg") - .attr("width", canvasWidth) - .attr("height", canvasHeight) - .attr("class", "memChart") - .append("g") - .attr("class", "memGroup") - .attr("transform", - "translate(" + margin.left + "," + margin.top + ")"); + .x(function(d) { + return mem_xScale(d.date); + }) + .y(function(d) { + return mem_yScale(d.system); + }); + +// Define the memory SVG +var memSVG = d3.select("#memDiv1") + .append("svg") + .attr("width", canvasWidth) + .attr("height", canvasHeight) + .attr("class", "memChart") + +var memTitleBox = memSVG.append("rect") + .attr("width", canvasWidth) + .attr("height", 30) + .attr("class", "titlebox") + +// Define the memory Chart +var memChart = memSVG.append("g") + .attr("class", "memGroup") + .attr("transform", + "translate(" + margin.left + "," + margin.top + ")"); // Add the system line path. memChart.append("path") - .attr("class", "systemLine") - .attr("d", mem_systemLine(memData)); + .attr("class", "systemLine") + .attr("d", mem_systemLine(memData)); // Add the process line path. memChart.append("path") - .attr("class", "processLine") - .style("stroke", "#8cd211") - .attr("d", mem_processLine(memData)); + .attr("class", "processLine") + .attr("d", mem_processLine(memData)); // Add the X Axis memChart.append("g") - .attr("class", "xAxis") - .attr("transform", "translate(0," + graphHeight + ")") - .call(mem_xAxis); + .attr("class", "xAxis") + .attr("transform", "translate(0," + graphHeight + ")") + .call(mem_xAxis); // Add the Y Axis memChart.append("g") - .attr("class", "yAxis") - .call(mem_yAxis); + .attr("class", "yAxis") + .call(mem_yAxis); // Add the title memChart.append("text") - .attr("x", -20) - .attr("y", 0 - (margin.top * 0.75)) - .style("font-size", "18px") - .text("Memory Usage"); + .attr("x", 7 - margin.left) + .attr("y", 15 - margin.top) + .attr("dominant-baseline", "central") + .style("font-size", "18px") + .text("Memory"); + +// Add the system colour box +memChart.append("rect") + .attr("x", 0) + .attr("y", graphHeight + margin.bottom - 15) + .attr("class", "colourbox1") + .attr("width", 10) + .attr("height", 10) // Add the SYSTEM label -memChart.append("text") - .attr("x", 0) - .attr("y", 0 - (margin.top / 8)) - .attr("class", "lineLabel") - .style("fill", "#6eedd8") - .text("SYSTEM"); +var memSystemLabel = memChart.append("text") + .attr("x", 15) + .attr("y", graphHeight + margin.bottom - 5) + .attr("text-anchor", "start") + .attr("class", "lineLabel") + .text("System"); + +// Add the process colour box +memChart.append("rect") + .attr("x", memSystemLabel.node().getBBox().width + 45) + .attr("y", graphHeight + margin.bottom - 15) + .attr("width", 10) + .attr("height", 10) + .attr("class", "colourbox2") // Add the PROCESS label memChart.append("text") - .attr("x", graphWidth / 2) - .attr("y", 0 - (margin.top / 8)) - .style("fill", "#8cd211") - .attr("class", "processlatestlabel") - .text("PROCESS"); - -// Add the text element for systemLatest -memChart.append("text") - .attr("x", 0) - .attr("y", 0 - (margin.top * 3 / 8)) - .attr("class", "systemLatest") - .style("font-size", "32px"); - -// Add the text element for processLatest -memChart.append("text") - .attr("x", graphWidth / 2) // spacing - .attr("y", 0 - (margin.top * 3 / 8)) - .attr("class", "processLatest") - .style("font-size", "32px"); + .attr("x", memSystemLabel.node().getBBox().width + 60) + .attr("y", graphHeight + margin.bottom - 5) + .attr("class", "lineLabel2") + .text("Node Process"); function resizeMemChart() { var chart = d3.select(".memChart") - chart.attr("width", canvasWidth); + chart.attr("width", canvasWidth); mem_xScale = d3.time.scale().range([0, graphWidth]); mem_xAxis = d3.svg.axis().scale(mem_xScale) - .orient("bottom").ticks(3).tickFormat(d3.time.format("%H:%M:%S")); - chart.select(".processLatest").attr("x", graphWidth / 2) - chart.select(".processlatestlabel").attr("x", graphWidth / 2) + .orient("bottom").ticks(3).tickFormat(getTimeFormat()); + memTitleBox.attr("width", canvasWidth) + // Redraw lines and axes mem_xScale.domain(d3.extent(memData, function(d) { return d.date; @@ -154,68 +164,66 @@ function resizeMemChart() { } function updateMemData() { - var memRequest = "http://" + myurl + "/memRequest"; - d3.json(memRequest, function(error, memRequestData) { - if (error) return console.warn(error); - if (!memRequestData || memRequestData.length === 0) - return - - - for (var i = 0, len = memRequestData.length; i < len; i++) { - var d = memRequestData[i]; - if (d != null && d.hasOwnProperty('time')) { - d.date = new Date(+d.time); - d.system = +d.physical_used / (1024 * 1024); - d.process = +d.physical / (1024 * 1024); - if (i == len - 1) { + var memRequest = "http://" + myurl + "/memRequest"; + d3.json(memRequest, function(error, memRequestData) { + if (error) return console.warn(error); + if (!memRequestData || memRequestData.length === 0) return; + for (var i = 0, len = memRequestData.length; i < len; i++) { + var d = memRequestData[i]; + if (d != null && d.hasOwnProperty('time')) { + d.date = new Date(+d.time); + d.system = +d.physical_used / (1024 * 1024); + d.process = +d.physical / (1024 * 1024); + if (i == len - 1) { var _memProcessLatest = Math.round(d.process); // Update gauge if loaded if(typeof(updateMemProcessGauge) === 'function' && _memProcessLatest != memProcessLatest) { - updateMemProcessGauge(d.process); + updateMemProcessGauge(d.process); } - memProcessLatest = _memProcessLatest; - memSystemLatest = Math.round(d.system); - } - memData.push(d) - } - } - - // Only keep 30 minutes of data - var currentTime = Date.now() - var d = memData[0] - if (d === null) - return + memProcessLatest = _memProcessLatest; + memSystemLatest = Math.round(d.system); + } + memData.push(d) + } + } + + // Only keep 30 minutes of data + var currentTime = Date.now() + var d = memData[0] + if (d === null) return; - while (d.hasOwnProperty('date') && d.date.valueOf() + 1800000 < currentTime) { - memData.shift() - d = memData[0] - } - - // Scale the range of the data again - mem_xScale.domain(d3.extent(memData, function(d) { - return d.date; - })); - mem_yScale.domain([0, Math.ceil(d3.extent(memData, function(d) { - return d.system; - })[1] / 100) * 100]); - - // Select the section we want to apply our changes to - var selection = d3.select(".memChart"); - - // Make the changes - selection.select(".systemLine") - .attr("d", mem_systemLine(memData)); - selection.select(".processLine") - .attr("d", mem_processLine(memData)); - selection.select(".xAxis") - .call(mem_xAxis); - selection.select(".yAxis") - .call(mem_yAxis); - selection.select(".processLatest") - .text(memProcessLatest + "MB"); - selection.select(".systemLatest") - .text(memSystemLatest + "MB"); - }); + while (d.hasOwnProperty('date') && d.date.valueOf() + 1800000 < currentTime) { + memData.shift() + d = memData[0] + } + + // Set the input domain for the axes + mem_xScale.domain(d3.extent(memData, function(d) { + return d.date; + })); + mem_yScale.domain([0, Math.ceil(d3.extent(memData, function(d) { + return d.system; + })[1] / 100) * 100]); + + mem_xAxis.tickFormat(getTimeFormat()); + + // Select the section we want to apply our changes to + var selection = d3.select(".memChart"); + + // Make the changes + selection.select(".systemLine") + .attr("d", mem_systemLine(memData)); + selection.select(".processLine") + .attr("d", mem_processLine(memData)); + selection.select(".xAxis") + .call(mem_xAxis); + selection.select(".yAxis") + .call(mem_yAxis); +// selection.select(".processLatest") +// .text(memProcessLatest + "MB"); +// selection.select(".systemLatest") +// .text(memSystemLatest + "MB"); + }); } From 616cc8890452b839c6abb09f82587376bdbd3ca4 Mon Sep 17 00:00:00 2001 From: Matthew Colegate Date: Wed, 8 Feb 2017 19:02:59 +0000 Subject: [PATCH 2/2] Code layout and whitespace improvements --- public/index.html | 3 +-- public/js/cpuChart.js | 9 ++++----- public/js/cpuProcessGauge.js | 20 ++++++++++---------- public/js/envTable.js | 1 - public/js/httpRequestsChart.js | 4 ++-- public/js/httpThroughPutChart.js | 4 ++-- public/js/httpTop5.js | 2 +- public/js/memChart.js | 21 +++++++++++---------- public/js/memProcessGauge.js | 22 +++++++++++----------- 9 files changed, 42 insertions(+), 44 deletions(-) diff --git a/public/index.html b/public/index.html index bc6f53a..da3a308 100755 --- a/public/index.html +++ b/public/index.html @@ -72,13 +72,12 @@ -