diff --git a/docs/content.en/docs/release-notes/_index.md b/docs/content.en/docs/release-notes/_index.md index 537ceabe..125342e6 100644 --- a/docs/content.en/docs/release-notes/_index.md +++ b/docs/content.en/docs/release-notes/_index.md @@ -17,6 +17,8 @@ Information about release notes of INFINI Console is provided here. ### Improvements +- add Buckets Diff to alerting rule + ## 1.28.1 (2025-01-24) - add credential settings for agent in enrolling agent diff --git a/docs/content.zh/docs/release-notes/_index.md b/docs/content.zh/docs/release-notes/_index.md index 8cf2b781..8e892a6b 100644 --- a/docs/content.zh/docs/release-notes/_index.md +++ b/docs/content.zh/docs/release-notes/_index.md @@ -17,6 +17,7 @@ title: "版本历史" ### Improvements +- 告警规则新增分桶对比 - 在注册 Agent 中新增 Agent 凭据设置 - 在集群编辑中新增采集模式 diff --git a/web/src/locales/en-US/alert.js b/web/src/locales/en-US/alert.js index 95d2e0cf..288f76cd 100644 --- a/web/src/locales/en-US/alert.js +++ b/web/src/locales/en-US/alert.js @@ -223,6 +223,7 @@ export default { //Configure alert objects 配置告警对象 "alert.rule.form.title.configure_alert_object": "Configure alert objects", "alert.rule.form.label.alert_metric": "Metrics", + "alert.rule.form.label.bucket_label_template": "Bucket Label Template", "alert.rule.form.label.alert_metric.groups": "Groups", "alert.rule.form.label.alert_metric.button.add_group": "Add group", "alert.rule.form.label.alert_metric.button.add_metric": "Add metrics", @@ -237,7 +238,13 @@ export default { "alert.rule.form.label.alert_condition": "Conditions", "alert.rule.form.label.event_title": "Event title", "alert.rule.form.label.event_message": "Event message", + "alert.rule.form.label.metrics_value": "Metrics value", + "alert.rule.form.label.buckets_diff": "Buckets diff", "alert.rule.form.label.above_metric": "Above metrics", + "alert.rule.form.label.size": "Docs count", + "alert.rule.form.label.content": "Content", + "alert.rule.form.label.in": "In", + "alert.rule.form.label.content.changed": "Changed", "alert.rule.form.label.lasts_periods": "Lasts {num} periods", "alert.rule.form.button.add_condition": "Add condition", "alert.rule.form.label.trigger": "Trigger", @@ -326,7 +333,9 @@ export default { "alert.message.detail.action_result": "Execution result", "alert.message.detail.action_result_error": "Exection error", "alert.message.detail.alert_info": "Alert Detail", + "alert.message.detail.condition.type": "Condition Type", "alert.message.detail.condition": "Condition", + "alert.message.detail.bucket_diff_type": "Bucket Diff Type", "alert.message.detail.recover_time": "Recovered Time", "alert.message.detail.title.event_detail": "Event Detail", "alert.message.detail.title.summary": "Summary", diff --git a/web/src/locales/zh-CN/alert.js b/web/src/locales/zh-CN/alert.js index dcffd4d5..5dd2ec99 100644 --- a/web/src/locales/zh-CN/alert.js +++ b/web/src/locales/zh-CN/alert.js @@ -211,6 +211,7 @@ export default { //Configure alert objects 配置告警对象 "alert.rule.form.title.configure_alert_object": "配置告警对象", "alert.rule.form.label.alert_metric": "告警指标", + "alert.rule.form.label.bucket_label_template": "分桶标签模板", "alert.rule.form.label.alert_metric.groups": "指标分组", "alert.rule.form.label.alert_metric.button.add_group": "添加分组", "alert.rule.form.label.alert_metric.button.add_metric": "添加指标", @@ -225,7 +226,13 @@ export default { "alert.rule.form.label.alert_condition": "告警条件", "alert.rule.form.label.event_title": "事件标题", "alert.rule.form.label.event_message": "事件内容", + "alert.rule.form.label.metrics_value": "指标数值", + "alert.rule.form.label.buckets_diff": "分桶对比", "alert.rule.form.label.above_metric": "以上指标", + "alert.rule.form.label.size": "文档数", + "alert.rule.form.label.content": "内容", + "alert.rule.form.label.in": "在", + "alert.rule.form.label.content.changed": "变更", "alert.rule.form.label.lasts_periods": "持续{num}个周期", "alert.rule.form.button.add_condition": "添加条件", "alert.rule.form.label.trigger": "触发", @@ -309,7 +316,9 @@ export default { "alert.message.detail.action_result": "执行结果", "alert.message.detail.action_result_error": "规则执行错误", "alert.message.detail.alert_info": "告警详情", + "alert.message.detail.condition.type": "触发条件类型", "alert.message.detail.condition": "触发条件", + "alert.message.detail.bucket_diff_type": "分桶对比类型", "alert.message.detail.recover_time": "恢复时间", "alert.message.detail.title.event_detail": "事件详情", "alert.message.detail.title.summary": "概览", diff --git a/web/src/pages/Alerting/Message/components/EventDetailCard.jsx b/web/src/pages/Alerting/Message/components/EventDetailCard.jsx index f0bae96a..58aa7239 100644 --- a/web/src/pages/Alerting/Message/components/EventDetailCard.jsx +++ b/web/src/pages/Alerting/Message/components/EventDetailCard.jsx @@ -8,6 +8,9 @@ import EventMessageStatus from "./EventMessageStatus"; export default ({msgItem})=>{ const labelSpan = 6; const vSpan = 18; + + const isBucketDiff = !!(msgItem && msgItem.bucket_conditions) + return (
@@ -46,6 +49,18 @@ export default ({msgItem})=>{ {formatMessage({ id: "alert.message.table.duration" })} {moment.duration(msgItem?.duration).humanize()} + + {formatMessage({ id: "alert.message.detail.condition.type" })} + {isBucketDiff ? formatMessage({id: `alert.rule.form.label.buckets_diff`}) : formatMessage({id: `alert.rule.form.label.metrics_value`})} + + { + isBucketDiff && msgItem?.bucket_diff_type ? ( + + {formatMessage({ id: "alert.message.detail.bucket_diff_type" })} + {formatMessage({id: `alert.rule.form.label.${msgItem.bucket_diff_type}`}) } + + ) : null + } {formatMessage({ id: "alert.message.detail.condition" })} {msgItem?.hit_condition} diff --git a/web/src/pages/Alerting/Rule/Edit.jsx b/web/src/pages/Alerting/Rule/Edit.jsx index d25e57e6..a03b4fcc 100644 --- a/web/src/pages/Alerting/Rule/Edit.jsx +++ b/web/src/pages/Alerting/Rule/Edit.jsx @@ -69,18 +69,20 @@ export default Form.create({ name: "rule_form_edit" })((props) => { const [editValue] = useMemo(() => { let editValue = value?._source || {}; - if (editValue?.metrics && editValue?.conditions) { + if (editValue?.metrics && (editValue?.conditions || editValue?.bucket_conditions)) { editValue.alert_objects = [ { name: editValue.name, metrics: editValue.metrics, conditions: editValue.conditions, + bucket_conditions: editValue.bucket_conditions, schedule: editValue.schedule, }, ]; delete editValue.name; delete editValue.metrics; delete editValue.conditions; + delete editValue.bucket_conditions; delete editValue.schedule; } return [editValue]; diff --git a/web/src/pages/Alerting/Rule/Form.jsx b/web/src/pages/Alerting/Rule/Form.jsx index 2dbb01f2..525f2d37 100644 --- a/web/src/pages/Alerting/Rule/Form.jsx +++ b/web/src/pages/Alerting/Rule/Form.jsx @@ -231,16 +231,20 @@ const RuleForm = (props) => { delete values.alert_objects; alert_objects = alert_objects.map((alert_object) => { - alert_object.conditions["operator"] = "any"; - alert_object.conditions.items = alert_object.conditions.items.map( - (item) => { - return { - ...item, - minimum_period_match: parseInt(item.minimum_period_match), - }; - } - ); - + if (alert_object.conditions) { + alert_object.conditions["operator"] = "any"; + alert_object.conditions.items = alert_object.conditions.items.map( + (item) => { + return { + ...item, + minimum_period_match: parseInt(item.minimum_period_match), + }; + } + ); + } + if (alert_object.bucket_conditions?.items) { + alert_object.bucket_conditions.items = alert_object.bucket_conditions.items.filter((item) => !!item.type); + } return { ...values, ...alert_object }; }); return alert_objects; diff --git a/web/src/pages/Alerting/Rule/FormAlertCondition.jsx b/web/src/pages/Alerting/Rule/FormAlertCondition.jsx index 21a515ce..d9ee6763 100644 --- a/web/src/pages/Alerting/Rule/FormAlertCondition.jsx +++ b/web/src/pages/Alerting/Rule/FormAlertCondition.jsx @@ -1,13 +1,45 @@ -import { Form, Input, Select, Button, Icon } from "antd"; -import { useCallback, useMemo, useState } from "react"; +import { Form, Input, Select, Button, Icon, Radio, InputNumber } from "antd"; +import { useCallback, useEffect, useMemo, useState } from "react"; import "./form.scss"; import { formatMessage } from "umi/locale"; import { PriorityColor } from "../utils/constants"; +import { cloneDeep } from "lodash"; const { Option } = Select; const InputGroup = Input.Group; +const lastsPeriods = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15] +const operators = ['equals', 'gte', 'gt', 'lt', 'lte', 'range'] + const FormAlertCondition = (props) => { + const { conditions, bucketConditions } = props; + const [type, setType] = useState('metrics_value') + + useEffect(() => { + if (bucketConditions?.items?.length > 0) { + setType('buckets_diff') + } + }, [JSON.stringify(conditions), JSON.stringify(bucketConditions)]) + + return ( + <> + setType(e.target.value)}> + { + ['metrics_value', 'buckets_diff'].map((item) => ( + {formatMessage({ + id: `alert.rule.form.label.${item}`, + })} + )) + } + + { type === 'metrics_value' ? : } + + ) +}; + +export default FormAlertCondition; + +const MetricsValue = (props) => { const { getFieldDecorator } = props.form; const alertObjectIndex = props.alertObjectIndex || 0; const conditions = props.conditions || {}; @@ -72,95 +104,18 @@ const FormAlertCondition = (props) => { props.onPreviewChartChange(); }} > - - - - - - - - - - - - + { + lastsPeriods.map((item) => ( + + )) + } )} @@ -187,12 +142,7 @@ const FormAlertCondition = (props) => { setOperatorState({ ...operatorState, [`op${i}`]: value }); }} > - - - - - - + { operators.map((item) => )} )} @@ -367,6 +317,326 @@ const FormAlertCondition = (props) => { })}
); -}; +} -export default FormAlertCondition; +const BucketsDiff = (props) => { + const { getFieldDecorator } = props.form; + const alertObjectIndex = props.alertObjectIndex || 0; + const conditions = props.bucketConditions || {}; + const [conditionItems, setConditionItems] = useState(conditions?.items || [{ type: 'size' }]); + + return ( +
+ {conditionItems.map((conditionItem, i) => { + return ( +
+ + + {getFieldDecorator( + `alert_objects[${alertObjectIndex}][bucket_conditions][items][${i}][type]`, + { + initialValue: conditionItem.type || "size", + } + )( + + )} + + + + + + {getFieldDecorator( + `alert_objects[${alertObjectIndex}][bucket_conditions][items][${i}][bucket_count]`, + { + initialValue: conditionItem.bucket_count || 10, + rules: [ + { + required: true, + message: "Please select period!", + }, + ], + } + )( + + )} + + + + + + {getFieldDecorator( + `alert_objects[${alertObjectIndex}][bucket_conditions][items][${i}][minimum_period_match]`, + { + initialValue: conditionItem.minimum_period_match || 1, + rules: [ + { + required: true, + message: "Please select periods match!", + }, + ], + } + )( + + )} + + <> + + {getFieldDecorator( + `alert_objects[${alertObjectIndex}][bucket_conditions][items][${i}][operator]`, + { + initialValue: conditionItem.operator, + rules: [ + { + required: true, + message: "Please select operator!", + }, + ], + } + )( + + )} + + + {conditionItem.operator === "range" ? ( + <> + + {getFieldDecorator( + `alert_objects[${alertObjectIndex}][bucket_conditions][items][${i}][values][0]`, + { + initialValue: conditionItem.values?.[0], + rules: [ + { + required: true, + message: "Please input min value!", + }, + ], + } + )( + { + props.onPreviewChartChange(); + }} + /> + )} + + + + + + {getFieldDecorator( + `alert_objects[${alertObjectIndex}][bucket_conditions][items][${i}][values][1]`, + { + initialValue: conditionItem.values?.[1], + rules: [ + { + required: true, + message: "Please input max value!", + }, + ], + } + )( + { + props.onPreviewChartChange(); + }} + /> + )} + + + ) : ( + + {getFieldDecorator( + `alert_objects[${alertObjectIndex}][bucket_conditions][items][${i}][values][0]`, + { + initialValue: conditionItem.values?.[0], + rules: [ + { + required: true, + message: "Please input value!", + }, + ], + } + )( + { + props.onPreviewChartChange(); + }} + /> + )} + + )} + + + + + + + {getFieldDecorator( + `alert_objects[${alertObjectIndex}][bucket_conditions][items][${i}][priority]`, + { + initialValue: conditionItem.priority, + rules: [ + { + required: true, + message: "Please select priority!", + }, + ], + } + )( + + )} + + {conditionItems.length > 1 && i > 0 ? ( + { + setConditionItems(conditionItems.filter((_, key) => key !== i)); + }} + /> + ) : null} + + {i == 0 ? ( + + + + ) : null} + +
+ ) + })} +
+ ); +} \ No newline at end of file diff --git a/web/src/pages/Alerting/Rule/FormAlertObject.jsx b/web/src/pages/Alerting/Rule/FormAlertObject.jsx index 7448d3f8..f1c02cdc 100644 --- a/web/src/pages/Alerting/Rule/FormAlertObject.jsx +++ b/web/src/pages/Alerting/Rule/FormAlertObject.jsx @@ -106,7 +106,9 @@ const FormAlertObject = (props) => { statPeriod={props.statPeriod} /> - + {