Update visualization for out of range rule

pull/725/head
Andrew Watkins 2017-01-03 15:51:51 -08:00
parent 11c8351adf
commit 25b54fb106
3 changed files with 39 additions and 7 deletions

View File

@ -4,6 +4,7 @@ import AutoRefresh from 'shared/components/AutoRefresh';
import LineGraph from 'shared/components/LineGraph'; import LineGraph from 'shared/components/LineGraph';
const RefreshingLineGraph = AutoRefresh(LineGraph); const RefreshingLineGraph = AutoRefresh(LineGraph);
const OUT_OF_RANGE = "out of range";
export const RuleGraph = React.createClass({ export const RuleGraph = React.createClass({
propTypes: { propTypes: {
source: PropTypes.shape({ source: PropTypes.shape({
@ -25,7 +26,7 @@ export const RuleGraph = React.createClass({
}, },
renderGraph() { renderGraph() {
const {query, source, timeRange} = this.props; const {query, source, timeRange, rule} = this.props;
const autoRefreshMs = 30000; const autoRefreshMs = 30000;
const queryText = selectStatement({lower: timeRange.queryValue}, query); const queryText = selectStatement({lower: timeRange.queryValue}, query);
const queries = [{host: source.links.proxy, text: queryText}]; const queries = [{host: source.links.proxy, text: queryText}];
@ -39,8 +40,27 @@ export const RuleGraph = React.createClass({
); );
} }
const {value, rangeValue, operator} = rule.values;
const tenPercent = 0.1;
let lower, upper;
let upperRange, lowerRange;
if (value !== "" && operator === OUT_OF_RANGE) {
lower = Math.min(+rule.values.rangeValue, +rule.values.value);
lowerRange = lower ? lower + lower * tenPercent : null;
}
if (rangeValue !== "" && operator === OUT_OF_RANGE) {
upper = Math.max(+rule.values.rangeValue, +rule.values.value);
upperRange = upper ? upper + upper * tenPercent : null;
}
// if either value is null, Dygraph will choose a sensible default
const range = {y: [lowerRange, upperRange]};
return ( return (
<RefreshingLineGraph <RefreshingLineGraph
ranges={range}
queries={queries} queries={queries}
autoRefresh={autoRefreshMs} autoRefresh={autoRefreshMs}
underlayCallback={this.createUnderlayCallback()} underlayCallback={this.createUnderlayCallback()}
@ -84,7 +104,15 @@ export const RuleGraph = React.createClass({
break; break;
} }
case 'out of range': case 'out of range': {
const {rangeValue, value} = rule.values;
highlightStart = Math.min(+value, +rangeValue);
highlightEnd = Math.max(+value, +rangeValue);
canvas.fillStyle = 'rgba(78, 216, 160, 0.3)';
canvas.fillRect(area.x, area.y, area.w, area.h);
break;
}
case 'within range': { case 'within range': {
const {rangeValue, value} = rule.values; const {rangeValue, value} = rule.values;
highlightStart = Math.min(+value, +rangeValue); highlightStart = Math.min(+value, +rangeValue);
@ -96,7 +124,7 @@ export const RuleGraph = React.createClass({
const bottom = dygraph.toDomYCoord(highlightStart); const bottom = dygraph.toDomYCoord(highlightStart);
const top = dygraph.toDomYCoord(highlightEnd); const top = dygraph.toDomYCoord(highlightEnd);
canvas.fillStyle = 'rgba(78,216,160,0.3)'; canvas.fillStyle = rule.values.operator === 'out of range' ? 'rgba(41, 41, 51, 1)' : 'rgba(78, 216, 160, 0.3)';
canvas.fillRect(area.x, top, area.w, bottom - top); canvas.fillRect(area.x, top, area.w, bottom - top);
}; };
}, },

View File

@ -25,8 +25,8 @@ export default React.createClass({
propTypes: { propTypes: {
ranges: shape({ ranges: shape({
y: arrayOf(number.isRequired), y: arrayOf(number),
y2: arrayOf(number.isRequired), y2: arrayOf(number),
}), }),
timeSeries: array.isRequired, // eslint-disable-line react/forbid-prop-types timeSeries: array.isRequired, // eslint-disable-line react/forbid-prop-types
labels: array.isRequired, // eslint-disable-line react/forbid-prop-types labels: array.isRequired, // eslint-disable-line react/forbid-prop-types

View File

@ -11,6 +11,10 @@ export default React.createClass({
displayName: 'LineGraph', displayName: 'LineGraph',
propTypes: { propTypes: {
data: PropTypes.arrayOf(PropTypes.shape({}).isRequired).isRequired, data: PropTypes.arrayOf(PropTypes.shape({}).isRequired).isRequired,
ranges: PropTypes.shape({
y: PropTypes.arrayOf(PropTypes.number),
y2: PropTypes.arrayOf(PropTypes.number),
}),
title: PropTypes.string, title: PropTypes.string,
isFetchingInitially: PropTypes.bool, isFetchingInitially: PropTypes.bool,
isRefreshing: PropTypes.bool, isRefreshing: PropTypes.bool,
@ -46,7 +50,7 @@ export default React.createClass({
}, },
render() { render() {
const {data, isFetchingInitially, isRefreshing, isGraphFilled, overrideLineColors, title, underlayCallback, queries, showSingleStat} = this.props; const {data, ranges, isFetchingInitially, isRefreshing, isGraphFilled, overrideLineColors, title, underlayCallback, queries, showSingleStat} = this.props;
const {labels, timeSeries, dygraphSeries} = this._timeSeries; const {labels, timeSeries, dygraphSeries} = this._timeSeries;
// If data for this graph is being fetched for the first time, show a graph-wide spinner. // If data for this graph is being fetched for the first time, show a graph-wide spinner.
@ -94,7 +98,7 @@ export default React.createClass({
labels={labels} labels={labels}
options={options} options={options}
dygraphSeries={dygraphSeries} dygraphSeries={dygraphSeries}
ranges={this.getRanges()} ranges={ranges || this.getRanges()}
/> />
{showSingleStat ? <div className="graph-single-stat single-stat">{roundedValue}</div> : null} {showSingleStat ? <div className="graph-single-stat single-stat">{roundedValue}</div> : null}
</div> </div>