feat(monitor): F6 日志告警引擎 — AlertEngine 支持 type=log 规则查询Loki/ES+触发/恢复 + 数据源认证升级(none/basic/bearer/custom) + 从查询创建告警真实API对接
This commit is contained in:
1 parent
894cb16a05
commit
6bba6144f3
17 files changed
+657
-74
No files matched your search
@@ -14,6 +14,7 @@ import {
|
||||
} from '@/components/ui/dialog';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
import { alertApi } from '@/api';
|
||||
import { logCenterApi, type LogDataSource } from '@/api/monitor/log-center';
|
||||
import { parseChannels, getChannelIcon, getChannelTypeLabel } from './alertShared';
|
||||
import type { JsonData } from '@/types/common';
|
||||
|
||||
@@ -25,6 +26,7 @@ const emptyRuleForm = {
|
||||
expression: '',
|
||||
severity: 'warning',
|
||||
duration: 300,
|
||||
datasource_id: undefined as number | undefined,
|
||||
notify_channels: [] as string[],
|
||||
};
|
||||
|
||||
@@ -46,6 +48,18 @@ export function AlertRuleDialog({
|
||||
}) {
|
||||
const [ruleForm, setRuleForm] = useState({ ...emptyRuleForm });
|
||||
const [ruleSaving, setRuleSaving] = useState(false);
|
||||
const [logSources, setLogSources] = useState<LogDataSource[]>([]);
|
||||
|
||||
// 日志规则打开时加载对应类型的数据源列表 // Logan.Li
|
||||
useEffect(() => {
|
||||
if (!open || ruleForm.type !== 'log') {
|
||||
setLogSources([]);
|
||||
return;
|
||||
}
|
||||
logCenterApi.listDatasources(ruleForm.source).then((res) => {
|
||||
setLogSources(res?.list || []);
|
||||
}).catch(() => setLogSources([]));
|
||||
}, [open, ruleForm.type, ruleForm.source]);
|
||||
|
||||
// 打开时同步表单(编辑时填充,新建时重置)
|
||||
useEffect(() => {
|
||||
@@ -59,6 +73,7 @@ export function AlertRuleDialog({
|
||||
expression: editingRule.expression || '',
|
||||
severity: editingRule.severity || 'warning',
|
||||
duration: editingRule.duration || 300,
|
||||
datasource_id: editingRule.datasource_id,
|
||||
notify_channels: parseChannels(editingRule.notify_channels),
|
||||
});
|
||||
} else {
|
||||
@@ -91,6 +106,7 @@ export function AlertRuleDialog({
|
||||
expression: ruleForm.expression.trim(),
|
||||
severity: ruleForm.severity,
|
||||
duration: Number(ruleForm.duration) || 0,
|
||||
datasource_id: ruleForm.datasource_id,
|
||||
notify_channels: ruleForm.notify_channels,
|
||||
};
|
||||
if (editingRule) {
|
||||
@@ -162,7 +178,7 @@ export function AlertRuleDialog({
|
||||
<Label className="text-slate-300">数据源</Label>
|
||||
<select
|
||||
value={ruleForm.source}
|
||||
onChange={(e) => setRuleForm({ ...ruleForm, source: e.target.value })}
|
||||
onChange={(e) => setRuleForm({ ...ruleForm, source: e.target.value, datasource_id: undefined })}
|
||||
className="w-full h-9 px-3 rounded-md bg-slate-800/50 border border-slate-700 text-slate-200 text-sm"
|
||||
>
|
||||
{ruleForm.type === 'log' ? (
|
||||
@@ -181,6 +197,25 @@ export function AlertRuleDialog({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{ruleForm.type === 'log' && (
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-300">日志数据源 <span className="text-red-400">*</span></Label>
|
||||
<select
|
||||
value={ruleForm.datasource_id || ''}
|
||||
onChange={(e) => setRuleForm({ ...ruleForm, datasource_id: Number(e.target.value) || undefined })}
|
||||
className="w-full h-9 px-3 rounded-md bg-slate-800/50 border border-slate-700 text-slate-200 text-sm"
|
||||
>
|
||||
<option value="">请选择数据源</option>
|
||||
{logSources.map((s) => (
|
||||
<option key={s.id} value={s.id}>{s.name}{s.is_default ? ' (默认)' : ''}</option>
|
||||
))}
|
||||
</select>
|
||||
{logSources.length === 0 && (
|
||||
<p className="text-xs text-amber-400/80">请先前往「日志库」添加 {ruleForm.source === 'loki' ? 'Loki' : 'Elasticsearch'} 数据源</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-300">触发表达式 <span className="text-red-400">*</span></Label>
|
||||
<Input
|
||||
|
||||
Reference in new issue
Block a user