Basic box plot for task processing duration
This commit is contained in:
		
							parent
							
								
									d0a9829002
								
							
						
					
					
						commit
						5462985a40
					
				@ -6,38 +6,28 @@ body {
 | 
			
		||||
#app {
 | 
			
		||||
    width: 1000px;
 | 
			
		||||
    margin: 0 auto;
 | 
			
		||||
    /*background-color: #eee;*/
 | 
			
		||||
    /*background-color: #ccc;*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.daemon {
 | 
			
		||||
    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 {
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    font-weight: 400;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.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;
 | 
			
		||||
}
 | 
			
		||||
    .daemon .boxplot {
 | 
			
		||||
        float: left;
 | 
			
		||||
        height: 150px;
 | 
			
		||||
        /*background-color: #fcc;*/
 | 
			
		||||
        border: #ccc 1px solid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -9,8 +9,25 @@ var Dashboard = React.createClass({
 | 
			
		||||
 | 
			
		||||
    reload: function() {
 | 
			
		||||
        getURL("http://127.0.0.1:6464/stats.json", {}, function(resp) {
 | 
			
		||||
            this.setState(resp);
 | 
			
		||||
            setTimeout(this.reload, 5000);
 | 
			
		||||
            var newState = {};
 | 
			
		||||
            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));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@ -31,32 +48,105 @@ var Dashboard = 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() {
 | 
			
		||||
        var last = this.decode(this.props.points[this.props.points.length - 1]);
 | 
			
		||||
        var last = this.props.points[this.props.points.length - 1];
 | 
			
		||||
        return (
 | 
			
		||||
            <div className="daemon">
 | 
			
		||||
                <h1>{this.props.name}</h1>
 | 
			
		||||
                <dl className="stats">
 | 
			
		||||
                    <dt>processed:</dt><dd>{last.processed}</dd>
 | 
			
		||||
                    <dt className="narrow">errors:</dt><dd>{last.errors}  </dd>
 | 
			
		||||
                    <dt>min:</dt><dd>{formatDuration(last.min)}</dd>
 | 
			
		||||
                    <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>
 | 
			
		||||
                <div className="left-block">
 | 
			
		||||
                    <h1>{this.props.name}</h1>
 | 
			
		||||
                </div>
 | 
			
		||||
                <BoxPlot points={this.props.points} />
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
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>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user