First commit
This commit is contained in:
commit
978a4190a6
|
@ -0,0 +1,155 @@
|
||||||
|
// SLA Data
|
||||||
|
var sla = null;
|
||||||
|
const request = async () => {
|
||||||
|
const response = await fetch('sla');
|
||||||
|
const json = await response.json();
|
||||||
|
sla = json[0];
|
||||||
|
console.log("sla data: ");
|
||||||
|
console.log(sla);
|
||||||
|
}
|
||||||
|
request();
|
||||||
|
|
||||||
|
const chartColors = [
|
||||||
|
(a=1) => `rgba( 54, 162, 235, ${a})`,
|
||||||
|
(a=1) => `rgba( 75, 192, 192, ${a})`,
|
||||||
|
(a=1) => `rgba(201, 203, 207, ${a})`,
|
||||||
|
(a=1) => `rgba(255, 159, 64, ${a})`,
|
||||||
|
(a=1) => `rgba(153, 102, 255, ${a})`,
|
||||||
|
(a=1) => `rgba(255, 99, 132, ${a})`,
|
||||||
|
(a=1) => `rgba(255, 205, 86, ${a})`
|
||||||
|
]
|
||||||
|
|
||||||
|
fetch('top.csv') // Open log
|
||||||
|
.then(response => response.text()) // Read it
|
||||||
|
.then(data => data.split('\n').map(x => x.split(','))) // Split in lines and split lines in columns
|
||||||
|
.then(data => {
|
||||||
|
const n = 100 // Number of dots
|
||||||
|
|
||||||
|
const headers = data[0].slice(1) // Remove the first header column (timestamp)
|
||||||
|
// Remove headers line and the empty last one and grab the first 100
|
||||||
|
data = data.slice(1, -1).slice(-n)
|
||||||
|
|
||||||
|
// Time will be shown in seconds then we divide it by 1000
|
||||||
|
// before building the X axis
|
||||||
|
const start = Math.round(data[0][0]/1000)
|
||||||
|
const xAxis = data.map(row => Math.round(row[0]/1000) - start)
|
||||||
|
|
||||||
|
// We will create a chart for each header:
|
||||||
|
const charts = headers.map((header, index) => {
|
||||||
|
const canvas = document.getElementById('chart-'+header)
|
||||||
|
if (!canvas) return null
|
||||||
|
const color = chartColors[index % chartColors.length]
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
type: 'line',
|
||||||
|
responsive: true,
|
||||||
|
data: {
|
||||||
|
labels: xAxis,
|
||||||
|
datasets: [{
|
||||||
|
label: header,
|
||||||
|
data: data.map(row => row[index+1]), // Y axis
|
||||||
|
backgroundColor: color(0.5),
|
||||||
|
borderColor: color(),
|
||||||
|
borderWidth: 1,
|
||||||
|
pointRadius: 2 // Size of the dots
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
xAxes: [{
|
||||||
|
ticks: {
|
||||||
|
autoSkip: true,
|
||||||
|
maxTicksLimit: 15,
|
||||||
|
},
|
||||||
|
scaleLabel: {
|
||||||
|
display: true,
|
||||||
|
labelString: 'seconds'
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
yAxes: [{
|
||||||
|
ticks: {
|
||||||
|
autoSkip: true,
|
||||||
|
maxTicksLimit: 8
|
||||||
|
},
|
||||||
|
scaleLabel: {
|
||||||
|
display: true,
|
||||||
|
labelString: header
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
onComplete: function(animation) {
|
||||||
|
plot_lines(animation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we have more than 200 dots then we deactivate lines and animations
|
||||||
|
// to avoid slowing or crashing the dashboard
|
||||||
|
if (n > 199) {
|
||||||
|
options.options.elements = {
|
||||||
|
line: {
|
||||||
|
tension: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
options.options.animation = {
|
||||||
|
duration: 0
|
||||||
|
},
|
||||||
|
options.options.hover = {
|
||||||
|
animationDuration: 0
|
||||||
|
},
|
||||||
|
options.options.responsiveAnimationDuration = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Chart(canvas.getContext('2d'), options)
|
||||||
|
})
|
||||||
|
var charts_loaded = true;
|
||||||
|
return charts
|
||||||
|
})
|
||||||
|
.then(charts => {
|
||||||
|
console.log('done', charts)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('An error ocurred:', error)
|
||||||
|
})
|
||||||
|
|
||||||
|
function plot_lines (animation) {
|
||||||
|
var execTime_line = new Graph({
|
||||||
|
canvasId: 'chart-execTime (ms)',
|
||||||
|
minX: -10,
|
||||||
|
minY: -10,
|
||||||
|
maxX: 10,
|
||||||
|
maxY: 10,
|
||||||
|
unitsPerTick: 1
|
||||||
|
});
|
||||||
|
execTime_line.drawEquation(function(x) {
|
||||||
|
return sla.maxExecTime;
|
||||||
|
}, 'green', 1);
|
||||||
|
|
||||||
|
var accuracy_line = new Graph({
|
||||||
|
canvasId: 'chart-Accuracy (%)',
|
||||||
|
minX: -10,
|
||||||
|
minY: -10,
|
||||||
|
maxX: 10,
|
||||||
|
maxY: 10,
|
||||||
|
unitsPerTick: 1
|
||||||
|
});
|
||||||
|
accuracy_line.drawEquation(function(x) {
|
||||||
|
return sla.minAccuracy;
|
||||||
|
}, 'green', 1);
|
||||||
|
|
||||||
|
var cost_line = new Graph({
|
||||||
|
canvasId: 'chart-cost',
|
||||||
|
minX: -10,
|
||||||
|
minY: -10,
|
||||||
|
maxX: 10,
|
||||||
|
maxY: 10,
|
||||||
|
unitsPerTick: 1
|
||||||
|
});
|
||||||
|
cost_line.drawEquation(function(x) {
|
||||||
|
return sla.maxCost;
|
||||||
|
}, 'green', 1);
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
// Source: https://www.html5canvastutorials.com/labs/html5-canvas-graphing-an-equation/
|
||||||
|
|
||||||
|
function Graph(config) {
|
||||||
|
// user defined properties
|
||||||
|
this.canvas = document.getElementById(config.canvasId);
|
||||||
|
this.minX = config.minX;
|
||||||
|
this.minY = config.minY;
|
||||||
|
this.maxX = config.maxX;
|
||||||
|
this.maxY = config.maxY;
|
||||||
|
this.unitsPerTick = config.unitsPerTick;
|
||||||
|
|
||||||
|
// constants
|
||||||
|
this.axisColor = '#aaa';
|
||||||
|
this.font = '8pt Calibri';
|
||||||
|
this.tickSize = 20;
|
||||||
|
|
||||||
|
// relationships
|
||||||
|
this.context = this.canvas.getContext('2d');
|
||||||
|
this.rangeX = this.maxX - this.minX;
|
||||||
|
this.rangeY = this.maxY - this.minY;
|
||||||
|
this.unitX = this.canvas.width / this.rangeX;
|
||||||
|
this.unitY = this.canvas.height / this.rangeY;
|
||||||
|
this.centerY = Math.round(Math.abs(this.minY / this.rangeY) * this.canvas.height);
|
||||||
|
this.centerX = Math.round(Math.abs(this.minX / this.rangeX) * this.canvas.width);
|
||||||
|
this.iteration = (this.maxX - this.minX) / 1000;
|
||||||
|
this.scaleX = this.canvas.width / this.rangeX;
|
||||||
|
this.scaleY = this.canvas.height / this.rangeY;
|
||||||
|
|
||||||
|
/*/ draw x and y axis
|
||||||
|
this.drawXAxis();
|
||||||
|
this.drawYAxis();*/
|
||||||
|
}
|
||||||
|
|
||||||
|
Graph.prototype.drawXAxis = function() {
|
||||||
|
var context = this.context;
|
||||||
|
context.save();
|
||||||
|
context.beginPath();
|
||||||
|
context.moveTo(0, this.centerY);
|
||||||
|
context.lineTo(this.canvas.width, this.centerY);
|
||||||
|
context.strokeStyle = this.axisColor;
|
||||||
|
context.lineWidth = 2;
|
||||||
|
context.stroke();
|
||||||
|
|
||||||
|
// draw tick marks
|
||||||
|
var xPosIncrement = this.unitsPerTick * this.unitX;
|
||||||
|
var xPos, unit;
|
||||||
|
context.font = this.font;
|
||||||
|
context.textAlign = 'center';
|
||||||
|
context.textBaseline = 'top';
|
||||||
|
|
||||||
|
// draw left tick marks
|
||||||
|
xPos = this.centerX - xPosIncrement;
|
||||||
|
unit = -1 * this.unitsPerTick;
|
||||||
|
while (xPos > 0) {
|
||||||
|
context.moveTo(xPos, this.centerY - this.tickSize / 2);
|
||||||
|
context.lineTo(xPos, this.centerY + this.tickSize / 2);
|
||||||
|
context.stroke();
|
||||||
|
context.fillText(unit, xPos, this.centerY + this.tickSize / 2 + 3);
|
||||||
|
unit -= this.unitsPerTick;
|
||||||
|
xPos = Math.round(xPos - xPosIncrement);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw right tick marks
|
||||||
|
xPos = this.centerX + xPosIncrement;
|
||||||
|
unit = this.unitsPerTick;
|
||||||
|
while (xPos < this.canvas.width) {
|
||||||
|
context.moveTo(xPos, this.centerY - this.tickSize / 2);
|
||||||
|
context.lineTo(xPos, this.centerY + this.tickSize / 2);
|
||||||
|
context.stroke();
|
||||||
|
context.fillText(unit, xPos, this.centerY + this.tickSize / 2 + 3);
|
||||||
|
unit += this.unitsPerTick;
|
||||||
|
xPos = Math.round(xPos + xPosIncrement);
|
||||||
|
}
|
||||||
|
context.restore();
|
||||||
|
};
|
||||||
|
|
||||||
|
Graph.prototype.drawYAxis = function() {
|
||||||
|
var context = this.context;
|
||||||
|
context.save();
|
||||||
|
context.beginPath();
|
||||||
|
context.moveTo(this.centerX, 0);
|
||||||
|
context.lineTo(this.centerX, this.canvas.height);
|
||||||
|
context.strokeStyle = this.axisColor;
|
||||||
|
context.lineWidth = 2;
|
||||||
|
context.stroke();
|
||||||
|
|
||||||
|
// draw tick marks
|
||||||
|
var yPosIncrement = this.unitsPerTick * this.unitY;
|
||||||
|
var yPos, unit;
|
||||||
|
context.font = this.font;
|
||||||
|
context.textAlign = 'right';
|
||||||
|
context.textBaseline = 'middle';
|
||||||
|
|
||||||
|
// draw top tick marks
|
||||||
|
yPos = this.centerY - yPosIncrement;
|
||||||
|
unit = this.unitsPerTick;
|
||||||
|
while (yPos > 0) {
|
||||||
|
context.moveTo(this.centerX - this.tickSize / 2, yPos);
|
||||||
|
context.lineTo(this.centerX + this.tickSize / 2, yPos);
|
||||||
|
context.stroke();
|
||||||
|
context.fillText(unit, this.centerX - this.tickSize / 2 - 3, yPos);
|
||||||
|
unit += this.unitsPerTick;
|
||||||
|
yPos = Math.round(yPos - yPosIncrement);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw bottom tick marks
|
||||||
|
yPos = this.centerY + yPosIncrement;
|
||||||
|
unit = -1 * this.unitsPerTick;
|
||||||
|
while (yPos < this.canvas.height) {
|
||||||
|
context.moveTo(this.centerX - this.tickSize / 2, yPos);
|
||||||
|
context.lineTo(this.centerX + this.tickSize / 2, yPos);
|
||||||
|
context.stroke();
|
||||||
|
context.fillText(unit, this.centerX - this.tickSize / 2 - 3, yPos);
|
||||||
|
unit -= this.unitsPerTick;
|
||||||
|
yPos = Math.round(yPos + yPosIncrement);
|
||||||
|
}
|
||||||
|
context.restore();
|
||||||
|
};
|
||||||
|
|
||||||
|
Graph.prototype.drawEquation = function(equation, color, thickness) {
|
||||||
|
var context = this.context;
|
||||||
|
context.save();
|
||||||
|
context.save();
|
||||||
|
this.transformContext();
|
||||||
|
|
||||||
|
context.beginPath();
|
||||||
|
context.moveTo(this.minX, equation(this.minX));
|
||||||
|
|
||||||
|
for (var x = this.minX + this.iteration; x <= this.maxX; x += this.iteration) {
|
||||||
|
context.lineTo(x, equation(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
context.restore();
|
||||||
|
context.lineJoin = 'round';
|
||||||
|
context.lineWidth = thickness;
|
||||||
|
context.strokeStyle = color;
|
||||||
|
context.stroke();
|
||||||
|
context.restore();
|
||||||
|
};
|
||||||
|
|
||||||
|
Graph.prototype.transformContext = function() {
|
||||||
|
var context = this.context;
|
||||||
|
|
||||||
|
// move context to center of canvas
|
||||||
|
this.context.translate(this.centerX, this.centerY);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* stretch grid to fit the canvas window, and
|
||||||
|
* invert the y scale so that that increments
|
||||||
|
* as you move upwards
|
||||||
|
*/
|
||||||
|
context.scale(this.scaleX, -this.scaleY);
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
<html>
|
||||||
|
<style>
|
||||||
|
#chart-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 600px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
#chart-container > canvas {
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<div id="chart-container">
|
||||||
|
<canvas id="chart-ingestionRate"></canvas>
|
||||||
|
<canvas id="chart-Accuracy (%)"></canvas>
|
||||||
|
<canvas id="chart-cost"></canvas>
|
||||||
|
<canvas id="chart-Window (ms)"></canvas>
|
||||||
|
<canvas id="chart-Delay (ms)"></canvas>
|
||||||
|
<canvas id="chart-execTime (ms)"></canvas>
|
||||||
|
</div>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
|
||||||
|
<script src="equation-plotter.js"></script>
|
||||||
|
<script src="chart.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Reference in New Issue