Merge pull request #1762 from influxdata/feature/kapa_alert_props-1755
Restore and add all supported Kapacitor alert services; fix Kapa alert state bugpull/1770/head
commit
d1b08ae7f2
|
@ -13,6 +13,7 @@
|
|||
1. [#1752](https://github.com/influxdata/chronograf/pull/1752): Clarify BoltPath server flag help text by making example the default path
|
||||
1. [#1738](https://github.com/influxdata/chronograf/pull/1738): Add shared secret JWT authorization to InfluxDB
|
||||
1. [#1724](https://github.com/influxdata/chronograf/pull/1724): Add Pushover alert support
|
||||
1. [#1762](https://github.com/influxdata/chronograf/pull/1762): Restore all supported Kapacitor services when creating rules, and add most optional message parameters
|
||||
|
||||
### UI Improvements
|
||||
1. [#1707](https://github.com/influxdata/chronograf/pull/1707): Polish alerts table in status page to wrap text less
|
||||
|
|
|
@ -752,6 +752,7 @@ func extractSlack(node *pipeline.AlertNode, rule *chronograf.AlertRule) {
|
|||
}
|
||||
rule.AlertNodes = append(rule.AlertNodes, alert)
|
||||
}
|
||||
|
||||
func extractTalk(node *pipeline.AlertNode, rule *chronograf.AlertRule) {
|
||||
if len(node.TalkHandlers) == 0 {
|
||||
return
|
||||
|
@ -763,6 +764,7 @@ func extractTalk(node *pipeline.AlertNode, rule *chronograf.AlertRule) {
|
|||
|
||||
rule.AlertNodes = append(rule.AlertNodes, alert)
|
||||
}
|
||||
|
||||
func extractTelegram(node *pipeline.AlertNode, rule *chronograf.AlertRule) {
|
||||
if len(node.TelegramHandlers) == 0 {
|
||||
return
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import _ from 'lodash'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import RuleMessageOptions from 'src/kapacitor/components/RuleMessageOptions'
|
||||
|
@ -55,9 +56,7 @@ class RuleMessage extends Component {
|
|||
<ul className="nav nav-tablist nav-tablist-sm nav-tablist-malachite">
|
||||
{alerts
|
||||
// only display alert endpoints that have rule alert options configured
|
||||
.filter(alert =>
|
||||
Object.keys(RULE_ALERT_OPTIONS).includes(alert.text)
|
||||
)
|
||||
.filter(alert => _.get(RULE_ALERT_OPTIONS, alert.text, false))
|
||||
.map(alert =>
|
||||
<li
|
||||
key={alert.text}
|
||||
|
|
|
@ -35,19 +35,6 @@ export const OPERATORS = [
|
|||
export const PERIODS = ['1m', '5m', '10m', '30m', '1h', '2h', '24h']
|
||||
export const CHANGES = ['change', '% change']
|
||||
export const SHIFTS = ['1m', '5m', '10m', '30m', '1h', '2h', '24h']
|
||||
export const ALERTS = [
|
||||
'alerta',
|
||||
'hipchat',
|
||||
'opsgenie',
|
||||
'pagerduty',
|
||||
'pushover',
|
||||
'sensu',
|
||||
'slack',
|
||||
'smtp',
|
||||
'talk',
|
||||
'telegram',
|
||||
'victorops',
|
||||
]
|
||||
|
||||
export const DEFAULT_RULE_ID = 'DEFAULT_RULE_ID'
|
||||
|
||||
|
@ -89,6 +76,10 @@ export const RULE_ALERT_OPTIONS = {
|
|||
label: 'URL:',
|
||||
placeholder: 'Ex: http://example.com/api/alert',
|
||||
},
|
||||
// properties: [
|
||||
// {name: 'endpoint', label: 'Endpoint:', placeholder: 'Endpoint'},
|
||||
// {name: 'header', label: 'Headers:', placeholder: 'Headers (Delimited)'}, // TODO: determine how to delimit
|
||||
// ],
|
||||
},
|
||||
tcp: {
|
||||
args: {
|
||||
|
@ -98,7 +89,7 @@ export const RULE_ALERT_OPTIONS = {
|
|||
},
|
||||
exec: {
|
||||
args: {
|
||||
label: 'Add Command (Arguments separated by Spaces):',
|
||||
label: 'Command (Arguments separated by Spaces):',
|
||||
placeholder: 'Ex: woogie boogie',
|
||||
},
|
||||
},
|
||||
|
@ -108,6 +99,66 @@ export const RULE_ALERT_OPTIONS = {
|
|||
placeholder: 'Ex: /tmp/alerts.log',
|
||||
},
|
||||
},
|
||||
alerta: {
|
||||
args: {
|
||||
label: 'Paste Alerta TICKscript:', // TODO: remove this
|
||||
placeholder: 'alerta()',
|
||||
},
|
||||
// properties: [
|
||||
// {name: 'token', label: 'Token:', placeholder: 'Token'},
|
||||
// {name: 'resource', label: 'Resource:', placeholder: 'Resource'},
|
||||
// {name: 'event', label: 'Event:', placeholder: 'Event'},
|
||||
// {name: 'environment', label: 'Environment:', placeholder: 'Environment'},
|
||||
// {name: 'group', label: 'Group:', placeholder: 'Group'},
|
||||
// {name: 'value', label: 'Value:', placeholder: 'Value'},
|
||||
// {name: 'origin', label: 'Origin:', placeholder: 'Origin'},
|
||||
// {name: 'services', label: 'Services:', placeholder: 'Services'}, // TODO: what format?
|
||||
// ],
|
||||
},
|
||||
hipchat: {
|
||||
properties: [
|
||||
{name: 'room', label: 'Room:', placeholder: 'happy_place'},
|
||||
{name: 'token', label: 'Token:', placeholder: 'a_gilded_token'},
|
||||
],
|
||||
},
|
||||
opsgenie: {
|
||||
// properties: [
|
||||
// {name: 'recipients', label: 'Recipients:', placeholder: 'happy_place'}, // TODO: what format?
|
||||
// {name: 'teams', label: 'Teams:', placeholder: 'blue,yellow,maroon'}, // TODO: what format?
|
||||
// ],
|
||||
},
|
||||
pagerduty: {
|
||||
properties: [
|
||||
{
|
||||
name: 'serviceKey',
|
||||
label: 'Service Key:',
|
||||
placeholder: 'one_rad_key',
|
||||
},
|
||||
],
|
||||
},
|
||||
pushover: {
|
||||
properties: [
|
||||
{
|
||||
name: 'device',
|
||||
label: 'Device:',
|
||||
placeholder: 'dv1,dv2 (Comma Separated)', // TODO: do these need to be parsed before sent?
|
||||
},
|
||||
{name: 'title', label: 'Title:', placeholder: 'Important Message'},
|
||||
{name: 'URL', label: 'URL:', placeholder: 'https://influxdata.com'},
|
||||
{name: 'URLTitle', label: 'URL Title:', placeholder: 'InfluxData'},
|
||||
{name: 'sound', label: 'Sound:', placeholder: 'alien'},
|
||||
],
|
||||
},
|
||||
sensu: {
|
||||
// TODO: apparently no args or properties, according to kapacitor/ast.go ?
|
||||
},
|
||||
slack: {
|
||||
properties: [
|
||||
{name: 'channel', label: 'Channel:', placeholder: '#cubeoctohedron'},
|
||||
{name: 'iconEmoji', label: 'Emoji:', placeholder: ':cubeapple:'},
|
||||
{name: 'username', label: 'Username:', placeholder: 'pineapple'},
|
||||
],
|
||||
},
|
||||
smtp: {
|
||||
args: {
|
||||
label: 'Email Addresses (Separated by Spaces):',
|
||||
|
@ -116,29 +167,26 @@ export const RULE_ALERT_OPTIONS = {
|
|||
},
|
||||
details: {placeholder: 'Email body text goes here'},
|
||||
},
|
||||
slack: {
|
||||
args: {
|
||||
label: 'Send alerts to Slack channel:',
|
||||
placeholder: '#alerts',
|
||||
},
|
||||
},
|
||||
alerta: {
|
||||
args: {
|
||||
label: 'Paste Alerta TICKscript:',
|
||||
placeholder: 'alerta()',
|
||||
},
|
||||
},
|
||||
pushover: {
|
||||
talk: {},
|
||||
telegram: {
|
||||
properties: [
|
||||
{
|
||||
name: 'device',
|
||||
label: 'Device:',
|
||||
placeholder: 'dv1,dv2 (Comma Separated)',
|
||||
},
|
||||
{name: 'title', label: 'Title:', placeholder: 'Important Message'},
|
||||
{name: 'URL', label: 'URL:', placeholder: 'https://influxdata.com'},
|
||||
{name: 'URLTitle', label: 'URL Title:', placeholder: 'InfluxData'},
|
||||
{name: 'sound', label: 'Sound:', placeholder: 'alien'},
|
||||
{name: 'chatId', label: 'Chat ID:', placeholder: 'xxxxxxxxx'},
|
||||
{name: 'parseMode', label: 'Emoji:', placeholder: 'Markdown'},
|
||||
// {
|
||||
// name: 'disableWebPagePreview',
|
||||
// label: 'Disable Web Page Preview:',
|
||||
// placeholder: 'true', // TODO: format to bool
|
||||
// },
|
||||
// {
|
||||
// name: 'disableNotification',
|
||||
// label: 'Disable Notification:',
|
||||
// placeholder: 'false', // TODO: format to bool
|
||||
// },
|
||||
],
|
||||
},
|
||||
victorops: {
|
||||
properties: [
|
||||
{name: 'routingKey', label: 'Channel:', placeholder: 'team_rocket'},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
@ -149,7 +197,6 @@ export const ALERT_NODES_ACCESSORS = {
|
|||
exec: rule => _.get(rule, 'alertNodes[0].args', []).join(' '),
|
||||
log: rule => _.get(rule, 'alertNodes[0].args[0]', ''),
|
||||
smtp: rule => _.get(rule, 'alertNodes[0].args', []).join(' '),
|
||||
slack: rule => _.get(rule, 'alertNodes[0].properties[0].args', ''),
|
||||
alerta: rule =>
|
||||
_.get(rule, 'alertNodes[0].properties', [])
|
||||
.reduce(
|
||||
|
|
|
@ -7,7 +7,7 @@ import * as queryActionCreators from 'src/data_explorer/actions/view'
|
|||
|
||||
import {bindActionCreators} from 'redux'
|
||||
import {getActiveKapacitor, getKapacitorConfig} from 'shared/apis/index'
|
||||
import {ALERTS, DEFAULT_RULE_ID} from 'src/kapacitor/constants'
|
||||
import {RULE_ALERT_OPTIONS, DEFAULT_RULE_ID} from 'src/kapacitor/constants'
|
||||
import KapacitorRule from 'src/kapacitor/components/KapacitorRule'
|
||||
|
||||
class KapacitorRulePage extends Component {
|
||||
|
@ -40,15 +40,14 @@ class KapacitorRulePage extends Component {
|
|||
|
||||
try {
|
||||
const {data: {sections}} = await getKapacitorConfig(kapacitor)
|
||||
const enabledAlerts = Object.keys(sections).filter(section => {
|
||||
return (
|
||||
const enabledAlerts = Object.keys(sections).filter(
|
||||
section =>
|
||||
_.get(
|
||||
sections,
|
||||
[section, 'elements', '0', 'options', 'enabled'],
|
||||
false
|
||||
) && ALERTS.includes(section)
|
||||
)
|
||||
})
|
||||
) && _.get(RULE_ALERT_OPTIONS, section, false)
|
||||
)
|
||||
|
||||
this.setState({kapacitor, enabledAlerts})
|
||||
} catch (error) {
|
||||
|
|
|
@ -114,19 +114,6 @@ export default function rules(state = {}, action) {
|
|||
},
|
||||
]
|
||||
break
|
||||
case 'slack':
|
||||
alertNodesByType = [
|
||||
{
|
||||
name: alertNodeName,
|
||||
properties: [
|
||||
{
|
||||
name: 'channel',
|
||||
args: [alertNodesText],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
break
|
||||
case 'alerta':
|
||||
alertNodesByType = [
|
||||
{
|
||||
|
@ -136,6 +123,12 @@ export default function rules(state = {}, action) {
|
|||
},
|
||||
]
|
||||
break
|
||||
case 'hipchat':
|
||||
case 'opsgenie':
|
||||
case 'pagerduty':
|
||||
case 'slack':
|
||||
case 'telegram':
|
||||
case 'victorops':
|
||||
case 'pushover':
|
||||
default:
|
||||
alertNodesByType = [
|
||||
|
@ -146,7 +139,6 @@ export default function rules(state = {}, action) {
|
|||
},
|
||||
]
|
||||
}
|
||||
|
||||
return Object.assign({}, state, {
|
||||
[ruleID]: Object.assign({}, state[ruleID], {
|
||||
alertNodes: alertNodesByType,
|
||||
|
@ -156,7 +148,6 @@ export default function rules(state = {}, action) {
|
|||
|
||||
case 'UPDATE_RULE_ALERT_PROPERTY': {
|
||||
const {ruleID, alertNodeName, alertProperty} = action.payload
|
||||
|
||||
const newAlertNodes = state[ruleID].alertNodes.map(alertNode => {
|
||||
if (alertNode.name !== alertNodeName) {
|
||||
return alertNode
|
||||
|
@ -181,8 +172,10 @@ export default function rules(state = {}, action) {
|
|||
|
||||
return {
|
||||
...state,
|
||||
[ruleID]: {...state[ruleID]},
|
||||
alertNodes: newAlertNodes,
|
||||
[ruleID]: {
|
||||
...state[ruleID],
|
||||
alertNodes: newAlertNodes,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue