adding within range support: the good, the bad, and the ugly

pull/725/head
Hunter Trujillo 2016-12-21 16:22:38 -07:00 committed by Andrew Watkins
parent 561d73ea22
commit 0da923cb97
5 changed files with 37 additions and 26 deletions

View File

@ -143,9 +143,9 @@ type TriggerValues struct {
Period string `json:"period,omitempty"` // Period length of time before deadman is alerted Period string `json:"period,omitempty"` // Period length of time before deadman is alerted
Shift string `json:"shift,omitempty"` // Shift is the amount of time to look into the past for the alert to compare to the present Shift string `json:"shift,omitempty"` // Shift is the amount of time to look into the past for the alert to compare to the present
Operator string `json:"operator,omitempty"` // Operator for alert comparison Operator string `json:"operator,omitempty"` // Operator for alert comparison
RangeOperator string `json:"range_operator,omitempty"` // RangeOperator is an optional operator for range comparisons RangeOperator string `json:"rangeOperator,omitempty"` // RangeOperator is an optional operator for range comparisons
Value string `json:"value,omitempty"` // Value is the boundary value when alert goes critical Value string `json:"value,omitempty"` // Value is the boundary value when alert goes critical
RangeValue string `json:"range_value,omitempty"` // RangeValue is an optional value for range comparisons RangeValue string `json:"rangeValue,omitempty"` // RangeValue is an optional value for range comparisons
} }
// Field represent influxql fields and functions from the UI // Field represent influxql fields and functions from the UI

View File

@ -1,10 +1,22 @@
import AJAX from 'utils/ajax'; import AJAX from 'utils/ajax';
function rangeRule(rule) {
if (rule.values.operator === 'within range') {
const {value, rangeValue} = rule.values;
rule.values.operator = 'less than';
rule.values.rangeOperator = 'greater than';
rule.values.value = Math.min(value, rangeValue).toString();
rule.values.rangeValue = Math.max(value, rangeValue).toString();
}
console.log(rule.values);
return rule;
}
export function createRule(kapacitor, rule) { export function createRule(kapacitor, rule) {
return AJAX({ return AJAX({
method: 'POST', method: 'POST',
url: kapacitor.links.rules, url: kapacitor.links.rules,
data: rule, data: rangeRule(rule),
}); });
} }
@ -26,7 +38,7 @@ export function editRule(rule) {
return AJAX({ return AJAX({
method: 'PUT', method: 'PUT',
url: rule.links.self, url: rule.links.self,
data: rule, data: rangeRule(rule),
}); });
} }

View File

@ -5,6 +5,8 @@ import {OPERATORS, PERIODS, CHANGES, SHIFTS} from 'src/kapacitor/constants';
import _ from 'lodash'; import _ from 'lodash';
const TABS = ['Threshold', 'Relative', 'Deadman']; const TABS = ['Threshold', 'Relative', 'Deadman'];
const mapToItems = (arr, type) => arr.map((text) => ({text, type}));
export const ValuesSection = React.createClass({ export const ValuesSection = React.createClass({
propTypes: { propTypes: {
rule: PropTypes.shape({ rule: PropTypes.shape({
@ -65,7 +67,9 @@ const Threshold = React.createClass({
rule: PropTypes.shape({ rule: PropTypes.shape({
values: PropTypes.shape({ values: PropTypes.shape({
operator: PropTypes.string, operator: PropTypes.string,
rangeOperator: PropTypes.string,
value: PropTypes.string, value: PropTypes.string,
rangeValue: PropTypes.string,
}), }),
}), }),
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
@ -74,26 +78,21 @@ const Threshold = React.createClass({
handleDropdownChange(item) { handleDropdownChange(item) {
const newValues = Object.assign({}, this.props.rule.values, {[item.type]: item.text}); this.props.onChange({...this.props.rule.values, [item.type]: item.text});
this.props.onChange(newValues);
}, },
handleInputChange() { handleInputChange() {
this.props.onChange(Object.assign({}, this.props.rule.values, { this.props.onChange({
...this.props.rule.values,
value: this.valueInput.value, value: this.valueInput.value,
})); rangeValue: this.valueRangeInput ? this.valueRangeInput.value : '',
});
}, },
render() { render() {
const {operator, value} = this.props.rule.values; const {operator, value, rangeValue} = this.props.rule.values;
const {query} = this.props; const {query} = this.props;
function mapToItems(arr, type) {
return arr.map((text) => {
return {text, type};
});
}
const operators = mapToItems(OPERATORS, 'operator'); const operators = mapToItems(OPERATORS, 'operator');
return ( return (
@ -102,7 +101,10 @@ const Threshold = React.createClass({
<span>{query.fields.length ? query.fields[0].field : 'Select a Metric'}</span> <span>{query.fields.length ? query.fields[0].field : 'Select a Metric'}</span>
<p>is</p> <p>is</p>
<Dropdown className="size-176 dropdown-kapacitor" items={operators} selected={operator} onChoose={this.handleDropdownChange} /> <Dropdown className="size-176 dropdown-kapacitor" items={operators} selected={operator} onChoose={this.handleDropdownChange} />
<input className="form-control input-sm size-166 form-control--green" type="text" ref={(r) => this.valueInput = r} defaultValue={value} onKeyUp={this.handleInputChange}></input> <input className="form-control input-sm size-166 form-control--green" type="text" ref={(r) => this.valueInput = r} defaultValue={value} onKeyUp={this.handleInputChange} />
{ operator === 'within range' &&
<input className="form-control input-sm size-166 form-control--green" type="text" ref={(r) => this.valueRangeInput = r} defaultValue={rangeValue} onKeyUp={this.handleInputChange} />
}
</div> </div>
); );
}, },
@ -122,22 +124,16 @@ const Relative = React.createClass({
}, },
handleDropdownChange(item) { handleDropdownChange(item) {
this.props.onChange(Object.assign({}, this.props.rule.values, {[item.type]: item.text})); this.props.onChange({...this.props.rule.values, [item.type]: item.text});
}, },
handleInputChange() { handleInputChange() {
this.props.onChange(Object.assign({}, this.props.rule.values, {value: this.input.value})); this.props.onChange({...this.props.rule.values, value: this.input.value});
}, },
render() { render() {
const {change, shift, operator, value} = this.props.rule.values; const {change, shift, operator, value} = this.props.rule.values;
function mapToItems(arr, type) {
return arr.map((text) => {
return {text, type};
});
}
const changes = mapToItems(CHANGES, 'change'); const changes = mapToItems(CHANGES, 'change');
const shifts = mapToItems(SHIFTS, 'shift'); const shifts = mapToItems(SHIFTS, 'shift');
const operators = mapToItems(OPERATORS, 'operator'); const operators = mapToItems(OPERATORS, 'operator');

View File

@ -11,12 +11,13 @@ export const defaultRuleConfigs = {
threshold: { threshold: {
operator: 'greater than', operator: 'greater than',
value: '', value: '',
rangeValue: '',
relation: 'once', relation: 'once',
percentile: '90', percentile: '90',
}, },
}; };
export const OPERATORS = ['greater than', 'equal to or greater', 'equal to or less than', 'less than', 'equal to', 'not equal to']; export const OPERATORS = ['greater than', 'equal to or greater', 'equal to or less than', 'less than', 'equal to', 'not equal to', 'within range'];
// export const RELATIONS = ['once', 'more than ', 'less than']; // export const RELATIONS = ['once', 'more than ', 'less than'];
export const PERIODS = ['1m', '5m', '10m', '30m', '1h', '2h', '24h']; export const PERIODS = ['1m', '5m', '10m', '30m', '1h', '2h', '24h'];
export const CHANGES = ['change', '% change']; export const CHANGES = ['change', '% change'];

View File

@ -13,8 +13,10 @@ const rootReducer = combineReducers({
rules: rulesReducer, rules: rulesReducer,
}); });
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export default function configureStore(initialState) { export default function configureStore(initialState) {
const createPersistentStore = compose( const createPersistentStore = composeEnhancers(
persistStateEnhancer(), persistStateEnhancer(),
applyMiddleware(thunkMiddleware, makeQueryExecuter()), applyMiddleware(thunkMiddleware, makeQueryExecuter()),
)(createStore); )(createStore);