Basic box plot for task processing duration
This commit is contained in:
parent
d0a9829002
commit
5462985a40
|
@ -6,38 +6,28 @@ body {
|
||||||
#app {
|
#app {
|
||||||
width: 1000px;
|
width: 1000px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
/*background-color: #eee;*/
|
/*background-color: #ccc;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.daemon {
|
.daemon {
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
|
height: 150px;
|
||||||
}
|
}
|
||||||
|
.daemon .left-block {
|
||||||
|
float: left;
|
||||||
|
width: 300px;
|
||||||
|
height: 150px;
|
||||||
|
/*background-color: #cfc;*/
|
||||||
|
}
|
||||||
|
.daemon .left-block h1 {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
.daemon h1 {
|
.daemon .boxplot {
|
||||||
padding: 0;
|
float: left;
|
||||||
margin: 0;
|
height: 150px;
|
||||||
font-weight: 400;
|
/*background-color: #fcc;*/
|
||||||
}
|
border: #ccc 1px solid;
|
||||||
|
}
|
||||||
.daemon .stats {
|
|
||||||
width: 305px;
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
.daemon dt, .daemon dd {
|
|
||||||
margin: 0;
|
|
||||||
float: left;
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
.daemon dt {
|
|
||||||
width: 75px;
|
|
||||||
color: #aaa;
|
|
||||||
}
|
|
||||||
.daemon dt.narrow {
|
|
||||||
width: 50px;
|
|
||||||
}
|
|
||||||
.daemon dd {
|
|
||||||
width: 80px;
|
|
||||||
margin-right: 10px;
|
|
||||||
font-family: monospace;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,8 +9,25 @@ var Dashboard = React.createClass({
|
||||||
|
|
||||||
reload: function() {
|
reload: function() {
|
||||||
getURL("http://127.0.0.1:6464/stats.json", {}, function(resp) {
|
getURL("http://127.0.0.1:6464/stats.json", {}, function(resp) {
|
||||||
this.setState(resp);
|
var newState = {};
|
||||||
setTimeout(this.reload, 5000);
|
var decode = function(point) {
|
||||||
|
return {
|
||||||
|
timestamp: point[0],
|
||||||
|
processed: point[1],
|
||||||
|
errors: point[2],
|
||||||
|
min: point[3],
|
||||||
|
p25: point[4],
|
||||||
|
mean: point[5],
|
||||||
|
median: point[6],
|
||||||
|
p75: point[7],
|
||||||
|
max: point[8],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (name in resp) {
|
||||||
|
newState[name] = resp[name].map(decode);
|
||||||
|
}
|
||||||
|
this.setState(newState);
|
||||||
|
setTimeout(this.reload, 3000);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -31,32 +48,105 @@ var Dashboard = React.createClass({
|
||||||
});
|
});
|
||||||
|
|
||||||
var Daemon = React.createClass({
|
var Daemon = React.createClass({
|
||||||
decode: function(point) {
|
|
||||||
return {
|
|
||||||
timestamp: point[0],
|
|
||||||
processed: point[1],
|
|
||||||
errors: point[2],
|
|
||||||
min: point[3],
|
|
||||||
mean: point[4],
|
|
||||||
p95: point[5],
|
|
||||||
max: point[6],
|
|
||||||
stddev: point[7],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var last = this.decode(this.props.points[this.props.points.length - 1]);
|
var last = this.props.points[this.props.points.length - 1];
|
||||||
return (
|
return (
|
||||||
<div className="daemon">
|
<div className="daemon">
|
||||||
<h1>{this.props.name}</h1>
|
<div className="left-block">
|
||||||
<dl className="stats">
|
<h1>{this.props.name}</h1>
|
||||||
<dt>processed:</dt><dd>{last.processed}</dd>
|
</div>
|
||||||
<dt className="narrow">errors:</dt><dd>{last.errors} </dd>
|
<BoxPlot points={this.props.points} />
|
||||||
<dt>min:</dt><dd>{formatDuration(last.min)}</dd>
|
</div>
|
||||||
<dt className="narrow">max:</dt><dd>{formatDuration(last.max)}</dd>
|
);
|
||||||
<dt>mean:</dt><dd>{formatDuration(last.mean)}</dd>
|
}
|
||||||
<dt className="narrow">95%:</dt><dd>{formatDuration(last.p95)}</dd>
|
});
|
||||||
</dl>
|
|
||||||
|
var BoxPlot = React.createClass({
|
||||||
|
render: function(){
|
||||||
|
var points = this.props.points,
|
||||||
|
maxHeight = 140,
|
||||||
|
padding = 5;
|
||||||
|
|
||||||
|
var min, max;
|
||||||
|
points.map(function(point) {
|
||||||
|
if (min === undefined || point.min < min) {
|
||||||
|
min = point.min;
|
||||||
|
}
|
||||||
|
if (max === undefined || point.max > max) {
|
||||||
|
max = point.max;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var renderBox = function(point, i) {
|
||||||
|
var relativeY = function(val) {
|
||||||
|
return maxHeight - Math.round((val-min)/(max-min) * maxHeight) + padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
var width = 10;
|
||||||
|
var padding = 5;
|
||||||
|
|
||||||
|
var x1 = (width + padding) * i + padding;
|
||||||
|
var x2 = x1 + width;
|
||||||
|
var minY = relativeY(point.min);
|
||||||
|
var p25Y = relativeY(point.p25);
|
||||||
|
var medianY = relativeY(point.median);
|
||||||
|
var p75Y = relativeY(point.p75);
|
||||||
|
var maxY = relativeY(point.max);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<g key={i}>
|
||||||
|
<line key="max"
|
||||||
|
x1={x1}
|
||||||
|
x2={x2}
|
||||||
|
y1={maxY}
|
||||||
|
y2={maxY}
|
||||||
|
strokeWidth={1}
|
||||||
|
style={{stroke: "#444"}} />
|
||||||
|
<line key="max-bar"
|
||||||
|
x1={x1+width/2}
|
||||||
|
x2={x1+width/2}
|
||||||
|
y1={maxY}
|
||||||
|
y2={p75Y}
|
||||||
|
strokeDasharray="4,2"
|
||||||
|
strokeWidth={1}
|
||||||
|
style={{stroke: "#444"}} />
|
||||||
|
<rect key="iqr"
|
||||||
|
x={x1}
|
||||||
|
y={p75Y}
|
||||||
|
width={width}
|
||||||
|
height={p25Y - p75Y}
|
||||||
|
strokeWidth={1}
|
||||||
|
style={{fill: "transparent", stroke: "#444"}} />
|
||||||
|
<line key="median"
|
||||||
|
x1={x1}
|
||||||
|
x2={x2}
|
||||||
|
y1={medianY}
|
||||||
|
y2={medianY}
|
||||||
|
strokeWidth={1}
|
||||||
|
style={{stroke: "#444"}} />
|
||||||
|
<line key="min-bar"
|
||||||
|
x1={x1+width/2}
|
||||||
|
x2={x1+width/2}
|
||||||
|
y1={minY}
|
||||||
|
y2={p25Y}
|
||||||
|
strokeDasharray="4,2"
|
||||||
|
strokeWidth={1}
|
||||||
|
style={{stroke: "#444"}} />
|
||||||
|
<line key="min"
|
||||||
|
x1={x1}
|
||||||
|
x2={x2}
|
||||||
|
y1={minY}
|
||||||
|
y2={minY}
|
||||||
|
strokeWidth={1}
|
||||||
|
style={{stroke: "#444"}} />
|
||||||
|
</g>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="boxplot">
|
||||||
|
<svg width="455" height="150">
|
||||||
|
{this.props.points.map(renderBox)}
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue