mirror of
https://github.com/yldio/copilot.git
synced 2024-11-28 14:10:04 +02:00
bar and whisker: adding min and max
This commit is contained in:
parent
dc98787e1e
commit
fe99517cb3
@ -8,7 +8,7 @@ const actions = {
|
|||||||
disk: []
|
disk: []
|
||||||
});
|
});
|
||||||
|
|
||||||
const newData = ['cpu'].reduce((sum, key) => {
|
const newData = ['cpu', 'mem'].reduce((sum, key) => {
|
||||||
const item = {
|
const item = {
|
||||||
...action.payload.stats[key],
|
...action.payload.stats[key],
|
||||||
when: action.payload.when
|
when: action.payload.when
|
||||||
|
@ -32,6 +32,8 @@ module.exports = React.createClass({
|
|||||||
options: {
|
options: {
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [{
|
xAxes: [{
|
||||||
|
barPercentage: 1.0,
|
||||||
|
categoryPercentage: 1.0,
|
||||||
}],
|
}],
|
||||||
yAxes: [{
|
yAxes: [{
|
||||||
ticks: {
|
ticks: {
|
||||||
|
@ -5,7 +5,8 @@ const React = require('react');
|
|||||||
const colors = {
|
const colors = {
|
||||||
user: 'rgb(255, 99, 132)',
|
user: 'rgb(255, 99, 132)',
|
||||||
sys: 'rgb(255, 159, 64)',
|
sys: 'rgb(255, 159, 64)',
|
||||||
perc: 'rgba(54, 74, 205, 0.2)'
|
perc: 'rgba(54, 74, 205, 0.2)',
|
||||||
|
alt: 'rgba(245, 93, 93, 0.2)'
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = ({
|
module.exports = ({
|
||||||
@ -16,6 +17,7 @@ module.exports = ({
|
|||||||
return {
|
return {
|
||||||
label: key,
|
label: key,
|
||||||
backgroundColor: colors[key],
|
backgroundColor: colors[key],
|
||||||
|
altBackgroundColor: colors['alt'],
|
||||||
data: buildArray(windowSize).map((v, i) => ((data[i] || {})[key] || { firstQuartile: 0, thirdQuartile: 0, median: 0, max: 0, min: 0 }))
|
data: buildArray(windowSize).map((v, i) => ((data[i] || {})[key] || { firstQuartile: 0, thirdQuartile: 0, median: 0, max: 0, min: 0 }))
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
221
spikes/graphs-matrix/chartjs-whiskers/client/element.whisker.js
Normal file
221
spikes/graphs-matrix/chartjs-whiskers/client/element.whisker.js
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = function(Chart) {
|
||||||
|
|
||||||
|
var globalOpts = Chart.defaults.global;
|
||||||
|
|
||||||
|
globalOpts.elements.rectangle = {
|
||||||
|
backgroundColor: globalOpts.defaultColor,
|
||||||
|
borderWidth: 0,
|
||||||
|
borderColor: globalOpts.defaultColor,
|
||||||
|
borderSkipped: 'bottom'
|
||||||
|
};
|
||||||
|
|
||||||
|
function isVertical(bar) {
|
||||||
|
return bar._view.width !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to get the bounds of the bar regardless of the orientation
|
||||||
|
* @private
|
||||||
|
* @param bar {Chart.Element.Rectangle} the bar
|
||||||
|
* @return {Bounds} bounds of the bar
|
||||||
|
*/
|
||||||
|
function getBarBounds(bar) {
|
||||||
|
var vm = bar._view;
|
||||||
|
var x1, x2, y1, y2;
|
||||||
|
|
||||||
|
if (isVertical(bar)) {
|
||||||
|
// vertical
|
||||||
|
var halfWidth = vm.width / 2;
|
||||||
|
x1 = vm.x - halfWidth;
|
||||||
|
x2 = vm.x + halfWidth;
|
||||||
|
y1 = Math.min(vm.y, vm.base);
|
||||||
|
y2 = Math.max(vm.y, vm.base);
|
||||||
|
} else {
|
||||||
|
// horizontal bar
|
||||||
|
var halfHeight = vm.height / 2;
|
||||||
|
x1 = Math.min(vm.x, vm.base);
|
||||||
|
x2 = Math.max(vm.x, vm.base);
|
||||||
|
y1 = vm.y - halfHeight;
|
||||||
|
y2 = vm.y + halfHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
left: x1,
|
||||||
|
top: y1,
|
||||||
|
right: x2,
|
||||||
|
bottom: y2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Chart.elements.Whisker = Chart.Element.extend({
|
||||||
|
draw: function() {
|
||||||
|
var ctx = this._chart.ctx;
|
||||||
|
var vm = this._view;
|
||||||
|
|
||||||
|
var halfWidth = vm.width / 2,
|
||||||
|
leftX = vm.x - halfWidth,
|
||||||
|
rightX = vm.x + halfWidth,
|
||||||
|
top = vm.base - (vm.base - vm.y),
|
||||||
|
halfStroke = vm.borderWidth / 2;
|
||||||
|
|
||||||
|
// Canvas doesn't allow us to stroke inside the width so we can
|
||||||
|
// adjust the sizes to fit if we're setting a stroke on the line
|
||||||
|
if (vm.borderWidth) {
|
||||||
|
leftX += halfStroke;
|
||||||
|
rightX -= halfStroke;
|
||||||
|
top += halfStroke;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillStyle = vm.backgroundColor;
|
||||||
|
ctx.strokeStyle = vm.borderColor;
|
||||||
|
ctx.lineWidth = vm.borderWidth;
|
||||||
|
|
||||||
|
// Corner points, from bottom-left to bottom-right clockwise
|
||||||
|
// | 1 2 |
|
||||||
|
// | 0 3 |
|
||||||
|
var corners = [
|
||||||
|
[leftX, vm.base],
|
||||||
|
[leftX, top],
|
||||||
|
[rightX, top],
|
||||||
|
[rightX, vm.base]
|
||||||
|
];
|
||||||
|
|
||||||
|
// Find first (starting) corner with fallback to 'bottom'
|
||||||
|
var borders = ['bottom', 'left', 'top', 'right'];
|
||||||
|
var startCorner = borders.indexOf(vm.borderSkipped, 0);
|
||||||
|
if (startCorner === -1) {
|
||||||
|
startCorner = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cornerAt(index) {
|
||||||
|
return corners[(startCorner + index) % 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw rectangle from 'startCorner'
|
||||||
|
var corner = cornerAt(0);
|
||||||
|
ctx.moveTo(corner[0], corner[1]);
|
||||||
|
|
||||||
|
for (var i = 1; i < 4; i++) {
|
||||||
|
corner = cornerAt(i);
|
||||||
|
ctx.lineTo(corner[0], corner[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.fill();
|
||||||
|
if (vm.borderWidth) {
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
ctx.closePath();
|
||||||
|
|
||||||
|
// Median line
|
||||||
|
ctx.beginPath();
|
||||||
|
|
||||||
|
ctx.moveTo(leftX, vm.median);
|
||||||
|
ctx.lineTo(rightX, vm.median);
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
|
||||||
|
// set line color
|
||||||
|
ctx.strokeStyle = 'rgb(54, 74, 205)';
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.closePath();
|
||||||
|
|
||||||
|
// Top Whisker
|
||||||
|
// if (smaller than 5px then do not draw)
|
||||||
|
if (vm.median - vm.maxV > 10) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo((rightX - leftX) / 2 + leftX, vm.median - 1);
|
||||||
|
ctx.lineTo((rightX - leftX) / 2 + leftX, vm.maxV);
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.strokeStyle = 'rgb(245, 93, 93)';
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc((rightX - leftX) / 2 + leftX, vm.maxV, 3, 0, 2 * Math.PI);
|
||||||
|
ctx.fillStyle = 'rgb(245, 93, 93)';
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bottom Whisker
|
||||||
|
// if (smaller than 5px then do not draw)
|
||||||
|
if (vm.minV - vm.median > 10) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo((rightX - leftX) / 2 + leftX, vm.median + 1);
|
||||||
|
ctx.lineTo((rightX - leftX) / 2 + leftX, vm.minV);
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.strokeStyle = 'rgb(245, 93, 93)';
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc((rightX - leftX) / 2 + leftX, vm.minV, 3, 0, 2 * Math.PI);
|
||||||
|
ctx.fillStyle = 'rgb(245, 93, 93)';
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
height: function() {
|
||||||
|
var vm = this._view;
|
||||||
|
return vm.base - vm.y;
|
||||||
|
},
|
||||||
|
inRange: function(mouseX, mouseY) {
|
||||||
|
var inRange = false;
|
||||||
|
|
||||||
|
if (this._view) {
|
||||||
|
var bounds = getBarBounds(this);
|
||||||
|
inRange = mouseX >= bounds.left && mouseX <= bounds.right && mouseY >= bounds.top && mouseY <= bounds.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inRange;
|
||||||
|
},
|
||||||
|
inLabelRange: function(mouseX, mouseY) {
|
||||||
|
var me = this;
|
||||||
|
if (!me._view) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var inRange = false;
|
||||||
|
var bounds = getBarBounds(me);
|
||||||
|
|
||||||
|
if (isVertical(me)) {
|
||||||
|
inRange = mouseX >= bounds.left && mouseX <= bounds.right;
|
||||||
|
} else {
|
||||||
|
inRange = mouseY >= bounds.top && mouseY <= bounds.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inRange;
|
||||||
|
},
|
||||||
|
inXRange: function(mouseX) {
|
||||||
|
var bounds = getBarBounds(this);
|
||||||
|
return mouseX >= bounds.left && mouseX <= bounds.right;
|
||||||
|
},
|
||||||
|
inYRange: function(mouseY) {
|
||||||
|
var bounds = getBarBounds(this);
|
||||||
|
return mouseY >= bounds.top && mouseY <= bounds.bottom;
|
||||||
|
},
|
||||||
|
getCenterPoint: function() {
|
||||||
|
var vm = this._view;
|
||||||
|
var x, y;
|
||||||
|
if (isVertical(this)) {
|
||||||
|
x = vm.x;
|
||||||
|
y = (vm.y + vm.base) / 2;
|
||||||
|
} else {
|
||||||
|
x = (vm.x + vm.base) / 2;
|
||||||
|
y = vm.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {x: x, y: y};
|
||||||
|
},
|
||||||
|
getArea: function() {
|
||||||
|
var vm = this._view;
|
||||||
|
return vm.width * Math.abs(vm.y - vm.base);
|
||||||
|
},
|
||||||
|
tooltipPosition: function() {
|
||||||
|
var vm = this._view;
|
||||||
|
return {
|
||||||
|
x: vm.x,
|
||||||
|
y: vm.y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
@ -1,4 +1,8 @@
|
|||||||
|
const whiskerElement = require('./element.whisker');
|
||||||
|
|
||||||
module.exports = function(Chart) {
|
module.exports = function(Chart) {
|
||||||
|
whiskerElement(Chart);
|
||||||
|
|
||||||
var helpers = Chart.helpers;
|
var helpers = Chart.helpers;
|
||||||
|
|
||||||
Chart.defaults.whisker = {
|
Chart.defaults.whisker = {
|
||||||
@ -27,7 +31,7 @@ module.exports = function(Chart) {
|
|||||||
|
|
||||||
Chart.controllers.whisker = Chart.DatasetController.extend({
|
Chart.controllers.whisker = Chart.DatasetController.extend({
|
||||||
|
|
||||||
dataElementType: Chart.Element.extend(Chart.elements.Rectangle.prototype),
|
dataElementType: Chart.elements.Whisker,
|
||||||
|
|
||||||
initialize: function(chart, datasetIndex) {
|
initialize: function(chart, datasetIndex) {
|
||||||
Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);
|
Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);
|
||||||
@ -81,9 +85,12 @@ module.exports = function(Chart) {
|
|||||||
datasetLabel: dataset.label,
|
datasetLabel: dataset.label,
|
||||||
|
|
||||||
// Appearance
|
// Appearance
|
||||||
|
median: reset ? scaleBase : me.medianValue(me.index, index),
|
||||||
|
maxV: reset ? scaleBase : me.maxValue(me.index, index),
|
||||||
|
minV: reset ? scaleBase : me.minValue(me.index, index),
|
||||||
base: reset ? scaleBase : me.boxBottomValue(me.index, index),
|
base: reset ? scaleBase : me.boxBottomValue(me.index, index),
|
||||||
width: me.calculateBarWidth(ruler),
|
width: me.calculateBarWidth(ruler),
|
||||||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
|
backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(me.stddev(me.index, index) > 3 ? dataset.altBackgroundColor : dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
|
||||||
borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
|
borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
|
||||||
borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
|
borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
|
||||||
borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
|
borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
|
||||||
@ -92,6 +99,45 @@ module.exports = function(Chart) {
|
|||||||
rectangle.pivot();
|
rectangle.pivot();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
stddev: function(datasetIndex, index) {
|
||||||
|
var me = this;
|
||||||
|
var obj = me.getDataset().data[index];
|
||||||
|
var value = Number(obj.stddev);
|
||||||
|
|
||||||
|
console.log('stddev >>', value);
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
|
||||||
|
minValue: function(datasetIndex, index) {
|
||||||
|
var me = this;
|
||||||
|
var meta = me.getMeta();
|
||||||
|
var yScale = me.getScaleForId(meta.yAxisID);
|
||||||
|
var obj = me.getDataset().data[index];
|
||||||
|
var value = Number(obj.min);
|
||||||
|
|
||||||
|
return yScale.getPixelForValue(value);
|
||||||
|
},
|
||||||
|
|
||||||
|
maxValue: function(datasetIndex, index) {
|
||||||
|
var me = this;
|
||||||
|
var meta = me.getMeta();
|
||||||
|
var yScale = me.getScaleForId(meta.yAxisID);
|
||||||
|
var obj = me.getDataset().data[index];
|
||||||
|
var value = Number(obj.max);
|
||||||
|
|
||||||
|
return yScale.getPixelForValue(value);
|
||||||
|
},
|
||||||
|
|
||||||
|
medianValue: function(datasetIndex, index) {
|
||||||
|
var me = this;
|
||||||
|
var meta = me.getMeta();
|
||||||
|
var yScale = me.getScaleForId(meta.yAxisID);
|
||||||
|
var obj = me.getDataset().data[index];
|
||||||
|
var value = Number(obj.median);
|
||||||
|
|
||||||
|
return yScale.getPixelForValue(value);
|
||||||
|
},
|
||||||
|
|
||||||
boxBottomValue: function(datasetIndex, index) {
|
boxBottomValue: function(datasetIndex, index) {
|
||||||
var me = this;
|
var me = this;
|
||||||
var meta = me.getMeta();
|
var meta = me.getMeta();
|
||||||
|
11
spikes/graphs-matrix/chartjs-whiskers/local.txt
Normal file
11
spikes/graphs-matrix/chartjs-whiskers/local.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
OldCpuSpeed=2712
|
||||||
|
NewCpuSpeedCount=0
|
||||||
|
NewCpuSpeed=0
|
||||||
|
RollingAverage=1000
|
||||||
|
RollingAverageIsFromV27=1
|
||||||
|
ComputerGUID=7fe43060180dc17e1be44afd3c056d72
|
||||||
|
CPUHours=1
|
||||||
|
RollingStartTime=0
|
||||||
|
Affinity=100
|
||||||
|
ThreadsPerTest=4
|
||||||
|
Pid=0
|
@ -15,7 +15,7 @@ const getCPU = (fn) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getPerc = (fn) => {
|
const getPerc = (fn) => {
|
||||||
async.timesSeries(10, (n, next) => {
|
async.timesSeries(20, (n, next) => {
|
||||||
osutils.cpuUsage((p) => {
|
osutils.cpuUsage((p) => {
|
||||||
const percentage = p * 100;
|
const percentage = p * 100;
|
||||||
next(null, percentage);
|
next(null, percentage);
|
||||||
@ -27,7 +27,8 @@ const getPerc = (fn) => {
|
|||||||
median: statistics.median(sample),
|
median: statistics.median(sample),
|
||||||
thirdQuartile: statistics.quantile(sample, 0.75),
|
thirdQuartile: statistics.quantile(sample, 0.75),
|
||||||
max: statistics.max(sample),
|
max: statistics.max(sample),
|
||||||
min: statistics.min(sample)
|
min: statistics.min(sample),
|
||||||
|
stddev: statistics.sampleStandardDeviation(sample)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user