feat: add ability to customize alert frequency (#4697)

This commit is contained in:
Srikanth Chekuri 2024-03-26 12:40:53 +05:30 committed by GitHub
parent 994814864c
commit 83f68f13db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 90 additions and 39 deletions

View File

@ -112,6 +112,7 @@
"exceptions_based_alert_desc": "Send a notification when a condition occurs in the exceptions data.", "exceptions_based_alert_desc": "Send a notification when a condition occurs in the exceptions data.",
"field_unit": "Threshold unit", "field_unit": "Threshold unit",
"text_alert_on_absent": "Send a notification if data is missing for", "text_alert_on_absent": "Send a notification if data is missing for",
"text_alert_frequency": "Run alert every",
"text_for": "minutes", "text_for": "minutes",
"selected_query_placeholder": "Select query" "selected_query_placeholder": "Select query"
} }

View File

@ -112,6 +112,7 @@
"exceptions_based_alert_desc": "Send a notification when a condition occurs in the exceptions data.", "exceptions_based_alert_desc": "Send a notification when a condition occurs in the exceptions data.",
"field_unit": "Threshold unit", "field_unit": "Threshold unit",
"text_alert_on_absent": "Send a notification if data is missing for", "text_alert_on_absent": "Send a notification if data is missing for",
"text_alert_frequency": "Run alert every",
"text_for": "minutes", "text_for": "minutes",
"selected_query_placeholder": "Select query" "selected_query_placeholder": "Select query"
} }

View File

@ -1,5 +1,6 @@
import { import {
Checkbox, Checkbox,
Collapse,
Form, Form,
InputNumber, InputNumber,
InputNumberProps, InputNumberProps,
@ -24,7 +25,12 @@ import {
import { EQueryType } from 'types/common/dashboard'; import { EQueryType } from 'types/common/dashboard';
import { popupContainer } from 'utils/selectPopupContainer'; import { popupContainer } from 'utils/selectPopupContainer';
import { FormContainer, InlineSelect, StepHeading } from './styles'; import {
FormContainer,
InlineSelect,
StepHeading,
VerticalLine,
} from './styles';
function RuleOptions({ function RuleOptions({
alertDef, alertDef,
@ -238,42 +244,72 @@ function RuleOptions({
/> />
</Form.Item> </Form.Item>
</Space> </Space>
<Space direction="horizontal" align="center"> <Collapse>
<Form.Item noStyle name={['condition', 'alertOnAbsent']}> <Collapse.Panel header={t('More options')} key="1">
<Checkbox <Space direction="vertical" size="large">
checked={alertDef?.condition?.alertOnAbsent} <VerticalLine>
onChange={(e): void => { <Space direction="horizontal" align="center">
setAlertDef({ <Typography.Text>{t('text_alert_frequency')}</Typography.Text>
...alertDef, <Form.Item noStyle name={['condition', 'frequency']}>
condition: { <InputNumber
...alertDef.condition, defaultValue={1}
alertOnAbsent: e.target.checked, min={1}
}, value={alertDef?.frequency}
}); onChange={(value): void => {
}} setAlertDef({
/> ...alertDef,
</Form.Item> frequency: Number(value) || 0,
<Typography.Text>{t('text_alert_on_absent')}</Typography.Text> });
}}
type="number"
onWheel={(e): void => e.currentTarget.blur()}
/>
</Form.Item>
<Typography.Text>{t('text_for')}</Typography.Text>
</Space>
</VerticalLine>
<Form.Item noStyle name={['condition', 'absentFor']}> <VerticalLine>
<InputNumber <Space direction="horizontal" align="center">
min={1} <Form.Item noStyle name={['condition', 'alertOnAbsent']}>
value={alertDef?.condition?.absentFor} <Checkbox
onChange={(value): void => { checked={alertDef?.condition?.alertOnAbsent}
setAlertDef({ onChange={(e): void => {
...alertDef, setAlertDef({
condition: { ...alertDef,
...alertDef.condition, condition: {
absentFor: Number(value) || 0, ...alertDef.condition,
}, alertOnAbsent: e.target.checked,
}); },
}} });
type="number" }}
onWheel={(e): void => e.currentTarget.blur()} />
/> </Form.Item>
</Form.Item> <Typography.Text>{t('text_alert_on_absent')}</Typography.Text>
<Typography.Text>{t('text_for')}</Typography.Text>
</Space> <Form.Item noStyle name={['condition', 'absentFor']}>
<InputNumber
min={1}
value={alertDef?.condition?.absentFor}
onChange={(value): void => {
setAlertDef({
...alertDef,
condition: {
...alertDef.condition,
absentFor: Number(value) || 0,
},
});
}}
type="number"
onWheel={(e): void => e.currentTarget.blur()}
/>
</Form.Item>
<Typography.Text>{t('text_for')}</Typography.Text>
</Space>
</VerticalLine>
</Space>
</Collapse.Panel>
</Collapse>
</Space> </Space>
</FormContainer> </FormContainer>
</> </>

View File

@ -67,6 +67,13 @@ export const SeveritySelect = styled(Select)`
width: 25% !important; width: 25% !important;
`; `;
export const VerticalLine = styled.div`
border-left: 2px solid #e8e8e8; /* Adjust color and thickness as desired */
padding-left: 20px; /* Adjust spacing to content as needed */
margin-left: 20px; /* Adjust margin as desired */
height: 100%; /* Adjust based on your layout needs */
`;
export const InputSmall = styled(Input)` export const InputSmall = styled(Input)`
width: 40% !important; width: 40% !important;
`; `;

View File

@ -12,6 +12,11 @@ function AllAlertList(): JSX.Element {
children: <TriggeredAlerts />, children: <TriggeredAlerts />,
}, },
// { // {
// label: 'Planned Downtime',
// key: 'Planned Downtime',
// // children: <PlannedDowntime />,
// },
// {
// label: 'Map Alert Channels', // label: 'Map Alert Channels',
// key = 'Map Alert Channels', // key = 'Map Alert Channels',
// children: <MapAlertChannels />, // children: <MapAlertChannels />,

View File

@ -14,6 +14,7 @@ export interface AlertDef {
alertType?: string; alertType?: string;
alert?: string; alert?: string;
ruleType?: string; ruleType?: string;
frequency?: number | undefined;
condition: RuleCondition; condition: RuleCondition;
labels?: Labels; labels?: Labels;
annotations?: Labels; annotations?: Labels;

View File

@ -525,7 +525,7 @@ func (m *Manager) prepareTask(acquireLock bool, r *PostableRule, taskName string
rules = append(rules, tr) rules = append(rules, tr)
// create ch rule task for evalution // create ch rule task for evalution
task = newTask(TaskTypeCh, taskName, taskNamesuffix, time.Duration(r.Frequency), rules, m.opts, m.prepareNotifyFunc()) task = newTask(TaskTypeCh, taskName, taskNamesuffix, time.Duration(r.Frequency*Duration(time.Minute)), rules, m.opts, m.prepareNotifyFunc())
// add rule to memory // add rule to memory
m.rules[ruleId] = tr m.rules[ruleId] = tr
@ -547,7 +547,7 @@ func (m *Manager) prepareTask(acquireLock bool, r *PostableRule, taskName string
rules = append(rules, pr) rules = append(rules, pr)
// create promql rule task for evalution // create promql rule task for evalution
task = newTask(TaskTypeProm, taskName, taskNamesuffix, time.Duration(r.Frequency), rules, m.opts, m.prepareNotifyFunc()) task = newTask(TaskTypeProm, taskName, taskNamesuffix, time.Duration(r.Frequency*Duration(time.Minute)), rules, m.opts, m.prepareNotifyFunc())
// add rule to memory // add rule to memory
m.rules[ruleId] = pr m.rules[ruleId] = pr

View File

@ -713,7 +713,7 @@ func (r *ThresholdRule) runChQuery(ctx context.Context, db clickhouse.Conn, quer
zap.S().Debugf("ruleid:", r.ID(), "\t resultmap(potential alerts):", len(resultMap)) zap.S().Debugf("ruleid:", r.ID(), "\t resultmap(potential alerts):", len(resultMap))
// if the data is missing for `For` duration then we should send alert // if the data is missing for `For` duration then we should send alert
if r.ruleCondition.AlertOnAbsent && r.lastTimestampWithDatapoints.Add(r.Condition().AbsentFor).Before(time.Now()) { if r.ruleCondition.AlertOnAbsent && r.lastTimestampWithDatapoints.Add(r.Condition().AbsentFor*time.Minute).Before(time.Now()) {
zap.S().Debugf("ruleid:", r.ID(), "\t msg: no data found for rule condition") zap.S().Debugf("ruleid:", r.ID(), "\t msg: no data found for rule condition")
lbls := labels.NewBuilder(labels.Labels{}) lbls := labels.NewBuilder(labels.Labels{})
if !r.lastTimestampWithDatapoints.IsZero() { if !r.lastTimestampWithDatapoints.IsZero() {