From 83f68f13db3dbedf692f7d2b0eb25c4ea99410cb Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Tue, 26 Mar 2024 12:40:53 +0530 Subject: [PATCH] feat: add ability to customize alert frequency (#4697) --- frontend/public/locales/en-GB/alerts.json | 1 + frontend/public/locales/en/alerts.json | 1 + .../container/FormAlertRules/RuleOptions.tsx | 108 ++++++++++++------ .../src/container/FormAlertRules/styles.ts | 7 ++ frontend/src/pages/AlertList/index.tsx | 5 + frontend/src/types/api/alerts/def.ts | 1 + pkg/query-service/rules/manager.go | 4 +- pkg/query-service/rules/thresholdRule.go | 2 +- 8 files changed, 90 insertions(+), 39 deletions(-) diff --git a/frontend/public/locales/en-GB/alerts.json b/frontend/public/locales/en-GB/alerts.json index fb360e579b..4dffb641d3 100644 --- a/frontend/public/locales/en-GB/alerts.json +++ b/frontend/public/locales/en-GB/alerts.json @@ -112,6 +112,7 @@ "exceptions_based_alert_desc": "Send a notification when a condition occurs in the exceptions data.", "field_unit": "Threshold unit", "text_alert_on_absent": "Send a notification if data is missing for", + "text_alert_frequency": "Run alert every", "text_for": "minutes", "selected_query_placeholder": "Select query" } diff --git a/frontend/public/locales/en/alerts.json b/frontend/public/locales/en/alerts.json index 0349568c70..33714d4429 100644 --- a/frontend/public/locales/en/alerts.json +++ b/frontend/public/locales/en/alerts.json @@ -112,6 +112,7 @@ "exceptions_based_alert_desc": "Send a notification when a condition occurs in the exceptions data.", "field_unit": "Threshold unit", "text_alert_on_absent": "Send a notification if data is missing for", + "text_alert_frequency": "Run alert every", "text_for": "minutes", "selected_query_placeholder": "Select query" } diff --git a/frontend/src/container/FormAlertRules/RuleOptions.tsx b/frontend/src/container/FormAlertRules/RuleOptions.tsx index 88e7c83979..d62b39f30f 100644 --- a/frontend/src/container/FormAlertRules/RuleOptions.tsx +++ b/frontend/src/container/FormAlertRules/RuleOptions.tsx @@ -1,5 +1,6 @@ import { Checkbox, + Collapse, Form, InputNumber, InputNumberProps, @@ -24,7 +25,12 @@ import { import { EQueryType } from 'types/common/dashboard'; import { popupContainer } from 'utils/selectPopupContainer'; -import { FormContainer, InlineSelect, StepHeading } from './styles'; +import { + FormContainer, + InlineSelect, + StepHeading, + VerticalLine, +} from './styles'; function RuleOptions({ alertDef, @@ -238,42 +244,72 @@ function RuleOptions({ /> - - - { - setAlertDef({ - ...alertDef, - condition: { - ...alertDef.condition, - alertOnAbsent: e.target.checked, - }, - }); - }} - /> - - {t('text_alert_on_absent')} + + + + + + {t('text_alert_frequency')} + + { + setAlertDef({ + ...alertDef, + frequency: Number(value) || 0, + }); + }} + type="number" + onWheel={(e): void => e.currentTarget.blur()} + /> + + {t('text_for')} + + - - { - setAlertDef({ - ...alertDef, - condition: { - ...alertDef.condition, - absentFor: Number(value) || 0, - }, - }); - }} - type="number" - onWheel={(e): void => e.currentTarget.blur()} - /> - - {t('text_for')} - + + + + { + setAlertDef({ + ...alertDef, + condition: { + ...alertDef.condition, + alertOnAbsent: e.target.checked, + }, + }); + }} + /> + + {t('text_alert_on_absent')} + + + { + setAlertDef({ + ...alertDef, + condition: { + ...alertDef.condition, + absentFor: Number(value) || 0, + }, + }); + }} + type="number" + onWheel={(e): void => e.currentTarget.blur()} + /> + + {t('text_for')} + + + + + diff --git a/frontend/src/container/FormAlertRules/styles.ts b/frontend/src/container/FormAlertRules/styles.ts index 9fcaf4c59c..11205c0ab4 100644 --- a/frontend/src/container/FormAlertRules/styles.ts +++ b/frontend/src/container/FormAlertRules/styles.ts @@ -67,6 +67,13 @@ export const SeveritySelect = styled(Select)` 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)` width: 40% !important; `; diff --git a/frontend/src/pages/AlertList/index.tsx b/frontend/src/pages/AlertList/index.tsx index 336c399a2f..33f3ada0f9 100644 --- a/frontend/src/pages/AlertList/index.tsx +++ b/frontend/src/pages/AlertList/index.tsx @@ -12,6 +12,11 @@ function AllAlertList(): JSX.Element { children: , }, // { + // label: 'Planned Downtime', + // key: 'Planned Downtime', + // // children: , + // }, + // { // label: 'Map Alert Channels', // key = 'Map Alert Channels', // children: , diff --git a/frontend/src/types/api/alerts/def.ts b/frontend/src/types/api/alerts/def.ts index af3a4bc912..96fa86654f 100644 --- a/frontend/src/types/api/alerts/def.ts +++ b/frontend/src/types/api/alerts/def.ts @@ -14,6 +14,7 @@ export interface AlertDef { alertType?: string; alert?: string; ruleType?: string; + frequency?: number | undefined; condition: RuleCondition; labels?: Labels; annotations?: Labels; diff --git a/pkg/query-service/rules/manager.go b/pkg/query-service/rules/manager.go index 530bb30d14..95181eade6 100644 --- a/pkg/query-service/rules/manager.go +++ b/pkg/query-service/rules/manager.go @@ -525,7 +525,7 @@ func (m *Manager) prepareTask(acquireLock bool, r *PostableRule, taskName string rules = append(rules, tr) // 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 m.rules[ruleId] = tr @@ -547,7 +547,7 @@ func (m *Manager) prepareTask(acquireLock bool, r *PostableRule, taskName string rules = append(rules, pr) // 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 m.rules[ruleId] = pr diff --git a/pkg/query-service/rules/thresholdRule.go b/pkg/query-service/rules/thresholdRule.go index 0fdb3745ca..f358d80393 100644 --- a/pkg/query-service/rules/thresholdRule.go +++ b/pkg/query-service/rules/thresholdRule.go @@ -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)) // 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") lbls := labels.NewBuilder(labels.Labels{}) if !r.lastTimestampWithDatapoints.IsZero() {