mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-13 21:26:02 +08:00
chore: fix alerting options (#4752)
This commit is contained in:
parent
0ac9f6f663
commit
31b1d58a70
@ -37,11 +37,16 @@
|
|||||||
"text_condition1": "Send a notification when",
|
"text_condition1": "Send a notification when",
|
||||||
"text_condition2": "the threshold",
|
"text_condition2": "the threshold",
|
||||||
"text_condition3": "during the last",
|
"text_condition3": "during the last",
|
||||||
|
"option_1min": "1 min",
|
||||||
"option_5min": "5 mins",
|
"option_5min": "5 mins",
|
||||||
"option_10min": "10 mins",
|
"option_10min": "10 mins",
|
||||||
"option_15min": "15 mins",
|
"option_15min": "15 mins",
|
||||||
|
"option_30min": "30 mins",
|
||||||
"option_60min": "60 mins",
|
"option_60min": "60 mins",
|
||||||
"option_4hours": "4 hours",
|
"option_4hours": "4 hours",
|
||||||
|
"option_3hours": "3 hours",
|
||||||
|
"option_6hours": "6 hours",
|
||||||
|
"option_12hours": "12 hours",
|
||||||
"option_24hours": "24 hours",
|
"option_24hours": "24 hours",
|
||||||
"field_threshold": "Alert Threshold",
|
"field_threshold": "Alert Threshold",
|
||||||
"option_allthetimes": "all the times",
|
"option_allthetimes": "all the times",
|
||||||
|
@ -37,11 +37,16 @@
|
|||||||
"text_condition1": "Send a notification when",
|
"text_condition1": "Send a notification when",
|
||||||
"text_condition2": "the threshold",
|
"text_condition2": "the threshold",
|
||||||
"text_condition3": "during the last",
|
"text_condition3": "during the last",
|
||||||
|
"option_1min": "1 min",
|
||||||
"option_5min": "5 mins",
|
"option_5min": "5 mins",
|
||||||
"option_10min": "10 mins",
|
"option_10min": "10 mins",
|
||||||
"option_15min": "15 mins",
|
"option_15min": "15 mins",
|
||||||
|
"option_30min": "30 mins",
|
||||||
"option_60min": "60 mins",
|
"option_60min": "60 mins",
|
||||||
|
"option_3hours": "3 hours",
|
||||||
"option_4hours": "4 hours",
|
"option_4hours": "4 hours",
|
||||||
|
"option_6hours": "6 hours",
|
||||||
|
"option_12hours": "12 hours",
|
||||||
"option_24hours": "24 hours",
|
"option_24hours": "24 hours",
|
||||||
"field_threshold": "Alert Threshold",
|
"field_threshold": "Alert Threshold",
|
||||||
"option_allthetimes": "all the times",
|
"option_allthetimes": "all the times",
|
||||||
|
@ -20,6 +20,7 @@ import {
|
|||||||
AlertDef,
|
AlertDef,
|
||||||
defaultCompareOp,
|
defaultCompareOp,
|
||||||
defaultEvalWindow,
|
defaultEvalWindow,
|
||||||
|
defaultFrequency,
|
||||||
defaultMatchType,
|
defaultMatchType,
|
||||||
} from 'types/api/alerts/def';
|
} from 'types/api/alerts/def';
|
||||||
import { EQueryType } from 'types/common/dashboard';
|
import { EQueryType } from 'types/common/dashboard';
|
||||||
@ -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 selectedCategory = getCategoryByOptionId(currentQuery?.unit || '');
|
||||||
|
|
||||||
const categorySelectOptions = getCategorySelectOptionByName(
|
const categorySelectOptions = getCategorySelectOptionByName(
|
||||||
@ -250,22 +280,7 @@ function RuleOptions({
|
|||||||
<VerticalLine>
|
<VerticalLine>
|
||||||
<Space direction="horizontal" align="center">
|
<Space direction="horizontal" align="center">
|
||||||
<Typography.Text>{t('text_alert_frequency')}</Typography.Text>
|
<Typography.Text>{t('text_alert_frequency')}</Typography.Text>
|
||||||
<Form.Item noStyle name={['condition', 'frequency']}>
|
{renderFrequency()}
|
||||||
<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>
|
|
||||||
</Space>
|
</Space>
|
||||||
</VerticalLine>
|
</VerticalLine>
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ export const defaultMatchType = '1';
|
|||||||
// default eval window
|
// default eval window
|
||||||
export const defaultEvalWindow = '5m0s';
|
export const defaultEvalWindow = '5m0s';
|
||||||
|
|
||||||
|
export const defaultFrequency = '1m0s';
|
||||||
|
|
||||||
// default compare op: above
|
// default compare op: above
|
||||||
export const defaultCompareOp = '1';
|
export const defaultCompareOp = '1';
|
||||||
|
|
||||||
@ -14,7 +16,7 @@ export interface AlertDef {
|
|||||||
alertType?: string;
|
alertType?: string;
|
||||||
alert?: string;
|
alert?: string;
|
||||||
ruleType?: string;
|
ruleType?: string;
|
||||||
frequency?: number | undefined;
|
frequency?: string;
|
||||||
condition: RuleCondition;
|
condition: RuleCondition;
|
||||||
labels?: Labels;
|
labels?: Labels;
|
||||||
annotations?: Labels;
|
annotations?: Labels;
|
||||||
|
@ -137,7 +137,7 @@ type RuleCondition struct {
|
|||||||
CompareOp CompareOp `yaml:"op,omitempty" json:"op,omitempty"`
|
CompareOp CompareOp `yaml:"op,omitempty" json:"op,omitempty"`
|
||||||
Target *float64 `yaml:"target,omitempty" json:"target,omitempty"`
|
Target *float64 `yaml:"target,omitempty" json:"target,omitempty"`
|
||||||
AlertOnAbsent bool `yaml:"alertOnAbsent,omitempty" json:"alertOnAbsent,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"`
|
MatchType MatchType `json:"matchType,omitempty"`
|
||||||
TargetUnit string `json:"targetUnit,omitempty"`
|
TargetUnit string `json:"targetUnit,omitempty"`
|
||||||
SelectedQuery string `json:"selectedQueryName,omitempty"`
|
SelectedQuery string `json:"selectedQueryName,omitempty"`
|
||||||
|
@ -31,7 +31,7 @@ func newApiErrorBadData(err error) *model.ApiError {
|
|||||||
|
|
||||||
// PostableRule is used to create alerting rule from HTTP api
|
// PostableRule is used to create alerting rule from HTTP api
|
||||||
type PostableRule struct {
|
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"`
|
AlertType string `yaml:"alertType,omitempty" json:"alertType,omitempty"`
|
||||||
Description string `yaml:"description,omitempty" json:"description,omitempty"`
|
Description string `yaml:"description,omitempty" json:"description,omitempty"`
|
||||||
RuleType RuleType `yaml:"ruleType,omitempty" json:"ruleType,omitempty"`
|
RuleType RuleType `yaml:"ruleType,omitempty" json:"ruleType,omitempty"`
|
||||||
@ -188,7 +188,7 @@ func (r *PostableRule) Validate() (errs []error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testTemplateParsing(rl *PostableRule) (errs []error) {
|
func testTemplateParsing(rl *PostableRule) (errs []error) {
|
||||||
if rl.Alert == "" {
|
if rl.AlertName == "" {
|
||||||
// Not an alerting rule.
|
// Not an alerting rule.
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
@ -200,7 +200,7 @@ func testTemplateParsing(rl *PostableRule) (errs []error) {
|
|||||||
tmpl := NewTemplateExpander(
|
tmpl := NewTemplateExpander(
|
||||||
context.TODO(),
|
context.TODO(),
|
||||||
defs+text,
|
defs+text,
|
||||||
"__alert_"+rl.Alert,
|
"__alert_"+rl.AlertName,
|
||||||
tmplData,
|
tmplData,
|
||||||
times.Time(timestamp.FromTime(time.Now())),
|
times.Time(timestamp.FromTime(time.Now())),
|
||||||
nil,
|
nil,
|
||||||
|
@ -503,7 +503,7 @@ func (m *Manager) prepareTask(acquireLock bool, r *PostableRule, taskName string
|
|||||||
rules := make([]Rule, 0)
|
rules := make([]Rule, 0)
|
||||||
var task Task
|
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))
|
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")
|
return task, fmt.Errorf("task load failed, at least one rule must be set")
|
||||||
}
|
}
|
||||||
@ -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*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
|
// add rule to memory
|
||||||
m.rules[ruleId] = tr
|
m.rules[ruleId] = tr
|
||||||
@ -536,7 +536,7 @@ func (m *Manager) prepareTask(acquireLock bool, r *PostableRule, taskName string
|
|||||||
pr, err := NewPromRule(
|
pr, err := NewPromRule(
|
||||||
ruleId,
|
ruleId,
|
||||||
r,
|
r,
|
||||||
log.With(m.logger, "alert", r.Alert),
|
log.With(m.logger, "alert", r.AlertName),
|
||||||
PromRuleOpts{},
|
PromRuleOpts{},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -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*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
|
// add rule to memory
|
||||||
m.rules[ruleId] = pr
|
m.rules[ruleId] = pr
|
||||||
@ -850,7 +850,7 @@ func (m *Manager) TestNotification(ctx context.Context, ruleStr string) (int, *m
|
|||||||
return 0, newApiErrorBadData(errs[0])
|
return 0, newApiErrorBadData(errs[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
var alertname = parsedRule.Alert
|
var alertname = parsedRule.AlertName
|
||||||
if alertname == "" {
|
if alertname == "" {
|
||||||
// alertname is not mandatory for testing, so picking
|
// alertname is not mandatory for testing, so picking
|
||||||
// a random string here
|
// a random string here
|
||||||
@ -858,7 +858,7 @@ func (m *Manager) TestNotification(ctx context.Context, ruleStr string) (int, *m
|
|||||||
}
|
}
|
||||||
|
|
||||||
// append name to indicate this is test alert
|
// 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 rule Rule
|
||||||
var err error
|
var err error
|
||||||
|
@ -71,7 +71,7 @@ func NewPromRule(
|
|||||||
|
|
||||||
p := PromRule{
|
p := PromRule{
|
||||||
id: id,
|
id: id,
|
||||||
name: postableRule.Alert,
|
name: postableRule.AlertName,
|
||||||
source: postableRule.Source,
|
source: postableRule.Source,
|
||||||
ruleCondition: postableRule.RuleCondition,
|
ruleCondition: postableRule.RuleCondition,
|
||||||
evalWindow: time.Duration(postableRule.EvalWindow),
|
evalWindow: time.Duration(postableRule.EvalWindow),
|
||||||
@ -612,7 +612,7 @@ func (r *PromRule) shouldAlert(series pql.Series) (pql.Sample, bool) {
|
|||||||
func (r *PromRule) String() string {
|
func (r *PromRule) String() string {
|
||||||
|
|
||||||
ar := PostableRule{
|
ar := PostableRule{
|
||||||
Alert: r.name,
|
AlertName: r.name,
|
||||||
RuleCondition: r.ruleCondition,
|
RuleCondition: r.ruleCondition,
|
||||||
EvalWindow: Duration(r.evalWindow),
|
EvalWindow: Duration(r.evalWindow),
|
||||||
Labels: r.labels.Map(),
|
Labels: r.labels.Map(),
|
||||||
|
@ -20,7 +20,7 @@ func (l testLogger) Log(args ...interface{}) error {
|
|||||||
|
|
||||||
func TestPromRuleShouldAlert(t *testing.T) {
|
func TestPromRuleShouldAlert(t *testing.T) {
|
||||||
postableRule := PostableRule{
|
postableRule := PostableRule{
|
||||||
Alert: "Test Rule",
|
AlertName: "Test Rule",
|
||||||
AlertType: "METRIC_BASED_ALERT",
|
AlertType: "METRIC_BASED_ALERT",
|
||||||
RuleType: RuleTypeProm,
|
RuleType: RuleTypeProm,
|
||||||
EvalWindow: Duration(5 * time.Minute),
|
EvalWindow: Duration(5 * time.Minute),
|
||||||
|
@ -102,7 +102,7 @@ func NewThresholdRule(
|
|||||||
|
|
||||||
t := ThresholdRule{
|
t := ThresholdRule{
|
||||||
id: id,
|
id: id,
|
||||||
name: p.Alert,
|
name: p.AlertName,
|
||||||
source: p.Source,
|
source: p.Source,
|
||||||
ruleCondition: p.RuleCondition,
|
ruleCondition: p.RuleCondition,
|
||||||
evalWindow: time.Duration(p.EvalWindow),
|
evalWindow: time.Duration(p.EvalWindow),
|
||||||
@ -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)))
|
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 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()))
|
zap.L().Info("no data found for rule condition", zap.String("ruleid", r.ID()))
|
||||||
lbls := labels.NewBuilder(labels.Labels{})
|
lbls := labels.NewBuilder(labels.Labels{})
|
||||||
if !r.lastTimestampWithDatapoints.IsZero() {
|
if !r.lastTimestampWithDatapoints.IsZero() {
|
||||||
@ -1289,7 +1289,7 @@ func (r *ThresholdRule) Eval(ctx context.Context, ts time.Time, queriers *Querie
|
|||||||
func (r *ThresholdRule) String() string {
|
func (r *ThresholdRule) String() string {
|
||||||
|
|
||||||
ar := PostableRule{
|
ar := PostableRule{
|
||||||
Alert: r.name,
|
AlertName: r.name,
|
||||||
RuleCondition: r.ruleCondition,
|
RuleCondition: r.ruleCondition,
|
||||||
EvalWindow: Duration(r.evalWindow),
|
EvalWindow: Duration(r.evalWindow),
|
||||||
Labels: r.labels.Map(),
|
Labels: r.labels.Map(),
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
func TestThresholdRuleCombinations(t *testing.T) {
|
func TestThresholdRuleCombinations(t *testing.T) {
|
||||||
postableRule := PostableRule{
|
postableRule := PostableRule{
|
||||||
Alert: "Tricky Condition Tests",
|
AlertName: "Tricky Condition Tests",
|
||||||
AlertType: "METRIC_BASED_ALERT",
|
AlertType: "METRIC_BASED_ALERT",
|
||||||
RuleType: RuleTypeThreshold,
|
RuleType: RuleTypeThreshold,
|
||||||
EvalWindow: Duration(5 * time.Minute),
|
EvalWindow: Duration(5 * time.Minute),
|
||||||
@ -339,7 +339,7 @@ func TestNormalizeLabelName(t *testing.T) {
|
|||||||
|
|
||||||
func TestPrepareLinksToLogs(t *testing.T) {
|
func TestPrepareLinksToLogs(t *testing.T) {
|
||||||
postableRule := PostableRule{
|
postableRule := PostableRule{
|
||||||
Alert: "Tricky Condition Tests",
|
AlertName: "Tricky Condition Tests",
|
||||||
AlertType: "LOGS_BASED_ALERT",
|
AlertType: "LOGS_BASED_ALERT",
|
||||||
RuleType: RuleTypeThreshold,
|
RuleType: RuleTypeThreshold,
|
||||||
EvalWindow: Duration(5 * time.Minute),
|
EvalWindow: Duration(5 * time.Minute),
|
||||||
@ -381,7 +381,7 @@ func TestPrepareLinksToLogs(t *testing.T) {
|
|||||||
|
|
||||||
func TestPrepareLinksToTraces(t *testing.T) {
|
func TestPrepareLinksToTraces(t *testing.T) {
|
||||||
postableRule := PostableRule{
|
postableRule := PostableRule{
|
||||||
Alert: "Links to traces test",
|
AlertName: "Links to traces test",
|
||||||
AlertType: "TRACES_BASED_ALERT",
|
AlertType: "TRACES_BASED_ALERT",
|
||||||
RuleType: RuleTypeThreshold,
|
RuleType: RuleTypeThreshold,
|
||||||
EvalWindow: Duration(5 * time.Minute),
|
EvalWindow: Duration(5 * time.Minute),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user