Skip to content

Commit

Permalink
chore: fix alerting options (#4752)
Browse files Browse the repository at this point in the history
  • Loading branch information
srikanthccv authored Mar 27, 2024
1 parent 0ac9f6f commit 31b1d58
Show file tree
Hide file tree
Showing 11 changed files with 63 additions and 36 deletions.
5 changes: 5 additions & 0 deletions frontend/public/locales/en-GB/alerts.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,16 @@
"text_condition1": "Send a notification when",
"text_condition2": "the threshold",
"text_condition3": "during the last",
"option_1min": "1 min",
"option_5min": "5 mins",
"option_10min": "10 mins",
"option_15min": "15 mins",
"option_30min": "30 mins",
"option_60min": "60 mins",
"option_4hours": "4 hours",
"option_3hours": "3 hours",
"option_6hours": "6 hours",
"option_12hours": "12 hours",
"option_24hours": "24 hours",
"field_threshold": "Alert Threshold",
"option_allthetimes": "all the times",
Expand Down
5 changes: 5 additions & 0 deletions frontend/public/locales/en/alerts.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,16 @@
"text_condition1": "Send a notification when",
"text_condition2": "the threshold",
"text_condition3": "during the last",
"option_1min": "1 min",
"option_5min": "5 mins",
"option_10min": "10 mins",
"option_15min": "15 mins",
"option_30min": "30 mins",
"option_60min": "60 mins",
"option_3hours": "3 hours",
"option_4hours": "4 hours",
"option_6hours": "6 hours",
"option_12hours": "12 hours",
"option_24hours": "24 hours",
"field_threshold": "Alert Threshold",
"option_allthetimes": "all the times",
Expand Down
47 changes: 31 additions & 16 deletions frontend/src/container/FormAlertRules/RuleOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
AlertDef,
defaultCompareOp,
defaultEvalWindow,
defaultFrequency,
defaultMatchType,
} from 'types/api/alerts/def';
import { EQueryType } from 'types/common/dashboard';
Expand Down Expand Up @@ -206,6 +207,35 @@ function RuleOptions({
});
};

const onChangeFrequency = (value: string | unknown): void => {
const freq = (value as string) || alertDef.frequency;
setAlertDef({
...alertDef,
frequency: freq,
});
};

const renderFrequency = (): JSX.Element => (
<InlineSelect
getPopupContainer={popupContainer}
defaultValue={defaultFrequency}
style={{ minWidth: '120px' }}
value={alertDef.frequency}
onChange={onChangeFrequency}
>
<Select.Option value="1m0s">{t('option_1min')}</Select.Option>
<Select.Option value="5m0s">{t('option_5min')}</Select.Option>
<Select.Option value="10m0s">{t('option_10min')}</Select.Option>
<Select.Option value="15m0s">{t('option_15min')}</Select.Option>
<Select.Option value="30m0s">{t('option_30min')}</Select.Option>
<Select.Option value="1h0m0s">{t('option_60min')}</Select.Option>
<Select.Option value="3h0m0s">{t('option_3hours')}</Select.Option>
<Select.Option value="6h0m0s">{t('option_6hours')}</Select.Option>
<Select.Option value="12h0m0s">{t('option_12hours')}</Select.Option>
<Select.Option value="24h0m0s">{t('option_24hours')}</Select.Option>
</InlineSelect>
);

const selectedCategory = getCategoryByOptionId(currentQuery?.unit || '');

const categorySelectOptions = getCategorySelectOptionByName(
Expand Down Expand Up @@ -250,22 +280,7 @@ function RuleOptions({
<VerticalLine>
<Space direction="horizontal" align="center">
<Typography.Text>{t('text_alert_frequency')}</Typography.Text>
<Form.Item noStyle name={['condition', 'frequency']}>
<InputNumber
defaultValue={1}
min={1}
value={alertDef?.frequency}
onChange={(value): void => {
setAlertDef({
...alertDef,
frequency: Number(value) || 0,
});
}}
type="number"
onWheel={(e): void => e.currentTarget.blur()}
/>
</Form.Item>
<Typography.Text>{t('text_for')}</Typography.Text>
{renderFrequency()}
</Space>
</VerticalLine>

Expand Down
4 changes: 3 additions & 1 deletion frontend/src/types/api/alerts/def.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export const defaultMatchType = '1';
// default eval window
export const defaultEvalWindow = '5m0s';

export const defaultFrequency = '1m0s';

// default compare op: above
export const defaultCompareOp = '1';

Expand All @@ -14,7 +16,7 @@ export interface AlertDef {
alertType?: string;
alert?: string;
ruleType?: string;
frequency?: number | undefined;
frequency?: string;
condition: RuleCondition;
labels?: Labels;
annotations?: Labels;
Expand Down
2 changes: 1 addition & 1 deletion pkg/query-service/rules/alerting.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ type RuleCondition struct {
CompareOp CompareOp `yaml:"op,omitempty" json:"op,omitempty"`
Target *float64 `yaml:"target,omitempty" json:"target,omitempty"`
AlertOnAbsent bool `yaml:"alertOnAbsent,omitempty" json:"alertOnAbsent,omitempty"`
AbsentFor time.Duration `yaml:"absentFor,omitempty" json:"absentFor,omitempty"`
AbsentFor uint64 `yaml:"absentFor,omitempty" json:"absentFor,omitempty"`
MatchType MatchType `json:"matchType,omitempty"`
TargetUnit string `json:"targetUnit,omitempty"`
SelectedQuery string `json:"selectedQueryName,omitempty"`
Expand Down
6 changes: 3 additions & 3 deletions pkg/query-service/rules/apiParams.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func newApiErrorBadData(err error) *model.ApiError {

// PostableRule is used to create alerting rule from HTTP api
type PostableRule struct {
Alert string `yaml:"alert,omitempty" json:"alert,omitempty"`
AlertName string `yaml:"alert,omitempty" json:"alert,omitempty"`
AlertType string `yaml:"alertType,omitempty" json:"alertType,omitempty"`
Description string `yaml:"description,omitempty" json:"description,omitempty"`
RuleType RuleType `yaml:"ruleType,omitempty" json:"ruleType,omitempty"`
Expand Down Expand Up @@ -188,7 +188,7 @@ func (r *PostableRule) Validate() (errs []error) {
}

func testTemplateParsing(rl *PostableRule) (errs []error) {
if rl.Alert == "" {
if rl.AlertName == "" {
// Not an alerting rule.
return errs
}
Expand All @@ -200,7 +200,7 @@ func testTemplateParsing(rl *PostableRule) (errs []error) {
tmpl := NewTemplateExpander(
context.TODO(),
defs+text,
"__alert_"+rl.Alert,
"__alert_"+rl.AlertName,
tmplData,
times.Time(timestamp.FromTime(time.Now())),
nil,
Expand Down
12 changes: 6 additions & 6 deletions pkg/query-service/rules/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ func (m *Manager) prepareTask(acquireLock bool, r *PostableRule, taskName string
rules := make([]Rule, 0)
var task Task

if r.Alert == "" {
if r.AlertName == "" {
zap.L().Error("task load failed, at least one rule must be set", zap.String("name", taskName))
return task, fmt.Errorf("task load failed, at least one rule must be set")
}
Expand All @@ -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*Duration(time.Minute)), rules, m.opts, m.prepareNotifyFunc())
task = newTask(TaskTypeCh, taskName, taskNamesuffix, time.Duration(r.Frequency), rules, m.opts, m.prepareNotifyFunc())

// add rule to memory
m.rules[ruleId] = tr
Expand All @@ -536,7 +536,7 @@ func (m *Manager) prepareTask(acquireLock bool, r *PostableRule, taskName string
pr, err := NewPromRule(
ruleId,
r,
log.With(m.logger, "alert", r.Alert),
log.With(m.logger, "alert", r.AlertName),
PromRuleOpts{},
)

Expand All @@ -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*Duration(time.Minute)), rules, m.opts, m.prepareNotifyFunc())
task = newTask(TaskTypeProm, taskName, taskNamesuffix, time.Duration(r.Frequency), rules, m.opts, m.prepareNotifyFunc())

// add rule to memory
m.rules[ruleId] = pr
Expand Down Expand Up @@ -850,15 +850,15 @@ func (m *Manager) TestNotification(ctx context.Context, ruleStr string) (int, *m
return 0, newApiErrorBadData(errs[0])
}

var alertname = parsedRule.Alert
var alertname = parsedRule.AlertName
if alertname == "" {
// alertname is not mandatory for testing, so picking
// a random string here
alertname = uuid.New().String()
}

// append name to indicate this is test alert
parsedRule.Alert = fmt.Sprintf("%s%s", alertname, TestAlertPostFix)
parsedRule.AlertName = fmt.Sprintf("%s%s", alertname, TestAlertPostFix)

var rule Rule
var err error
Expand Down
4 changes: 2 additions & 2 deletions pkg/query-service/rules/promRule.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func NewPromRule(

p := PromRule{
id: id,
name: postableRule.Alert,
name: postableRule.AlertName,
source: postableRule.Source,
ruleCondition: postableRule.RuleCondition,
evalWindow: time.Duration(postableRule.EvalWindow),
Expand Down Expand Up @@ -612,7 +612,7 @@ func (r *PromRule) shouldAlert(series pql.Series) (pql.Sample, bool) {
func (r *PromRule) String() string {

ar := PostableRule{
Alert: r.name,
AlertName: r.name,
RuleCondition: r.ruleCondition,
EvalWindow: Duration(r.evalWindow),
Labels: r.labels.Map(),
Expand Down
2 changes: 1 addition & 1 deletion pkg/query-service/rules/promrule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func (l testLogger) Log(args ...interface{}) error {

func TestPromRuleShouldAlert(t *testing.T) {
postableRule := PostableRule{
Alert: "Test Rule",
AlertName: "Test Rule",
AlertType: "METRIC_BASED_ALERT",
RuleType: RuleTypeProm,
EvalWindow: Duration(5 * time.Minute),
Expand Down
6 changes: 3 additions & 3 deletions pkg/query-service/rules/thresholdRule.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func NewThresholdRule(

t := ThresholdRule{
id: id,
name: p.Alert,
name: p.AlertName,
source: p.Source,
ruleCondition: p.RuleCondition,
evalWindow: time.Duration(p.EvalWindow),
Expand Down Expand Up @@ -713,7 +713,7 @@ func (r *ThresholdRule) runChQuery(ctx context.Context, db clickhouse.Conn, quer
zap.L().Debug("resultmap(potential alerts)", zap.String("ruleid", r.ID()), zap.Int("count", 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*time.Minute).Before(time.Now()) {
if r.ruleCondition.AlertOnAbsent && r.lastTimestampWithDatapoints.Add(time.Duration(r.Condition().AbsentFor)*time.Minute).Before(time.Now()) {
zap.L().Info("no data found for rule condition", zap.String("ruleid", r.ID()))
lbls := labels.NewBuilder(labels.Labels{})
if !r.lastTimestampWithDatapoints.IsZero() {
Expand Down Expand Up @@ -1289,7 +1289,7 @@ func (r *ThresholdRule) Eval(ctx context.Context, ts time.Time, queriers *Querie
func (r *ThresholdRule) String() string {

ar := PostableRule{
Alert: r.name,
AlertName: r.name,
RuleCondition: r.ruleCondition,
EvalWindow: Duration(r.evalWindow),
Labels: r.labels.Map(),
Expand Down
6 changes: 3 additions & 3 deletions pkg/query-service/rules/thresholdRule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

func TestThresholdRuleCombinations(t *testing.T) {
postableRule := PostableRule{
Alert: "Tricky Condition Tests",
AlertName: "Tricky Condition Tests",
AlertType: "METRIC_BASED_ALERT",
RuleType: RuleTypeThreshold,
EvalWindow: Duration(5 * time.Minute),
Expand Down Expand Up @@ -339,7 +339,7 @@ func TestNormalizeLabelName(t *testing.T) {

func TestPrepareLinksToLogs(t *testing.T) {
postableRule := PostableRule{
Alert: "Tricky Condition Tests",
AlertName: "Tricky Condition Tests",
AlertType: "LOGS_BASED_ALERT",
RuleType: RuleTypeThreshold,
EvalWindow: Duration(5 * time.Minute),
Expand Down Expand Up @@ -381,7 +381,7 @@ func TestPrepareLinksToLogs(t *testing.T) {

func TestPrepareLinksToTraces(t *testing.T) {
postableRule := PostableRule{
Alert: "Links to traces test",
AlertName: "Links to traces test",
AlertType: "TRACES_BASED_ALERT",
RuleType: RuleTypeThreshold,
EvalWindow: Duration(5 * time.Minute),
Expand Down

0 comments on commit 31b1d58

Please sign in to comment.