feat(alerts): metric-alert rule-management UI (Phase 2)
Completes metric-threshold alerting end-to-end: /metric-alert-rules list/new/edit routes (mirroring log-scan-rules) with metric/comparator/ threshold fields, the workload scope picker, ToggleSwitch, and a ConfirmDialog delete flow; an api.ts MetricAlertRule CRUD client; an "Observe" nav entry; and a full metricalert.* i18n namespace (en/ru parity). Create-form cooldown defaults to 300s to match the server. Rules are now manageable in the WebUI; breaches already surface in the per-app activity timeline and fire any configured event-trigger webhook. Reviewed: typescript APPROVE (0 CRITICAL/HIGH).
This commit is contained in:
@@ -1375,3 +1375,56 @@ export function getLogScanStats(signal?: AbortSignal): Promise<LogScanStats> {
|
||||
return get<LogScanStats>('/api/log-scan-rules/stats', signal);
|
||||
}
|
||||
|
||||
// ── Metric alert rules ──────────────────────────────────────────────
|
||||
// Backend: internal/api/metric_alert_rules.go. Rules compare a sampled
|
||||
// container metric (cpu/memory) against a threshold using a comparator.
|
||||
// Scope model: workload_id="" → global; workload_id set → workload-only.
|
||||
// Unlike log-scan rules there is no override / test / effective-rules
|
||||
// concept — a metric-alert rule is a flat threshold check.
|
||||
|
||||
export interface MetricAlertRule {
|
||||
id: number;
|
||||
workload_id: string; // "" = global
|
||||
name: string;
|
||||
metric: 'cpu_percent' | 'memory_percent' | 'memory_bytes';
|
||||
comparator: 'gt' | 'lt';
|
||||
threshold: number;
|
||||
severity: 'info' | 'warn' | 'error';
|
||||
cooldown_seconds: number;
|
||||
enabled: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
export interface MetricAlertRuleInput {
|
||||
workload_id?: string;
|
||||
name: string;
|
||||
metric: 'cpu_percent' | 'memory_percent' | 'memory_bytes';
|
||||
comparator: 'gt' | 'lt';
|
||||
threshold: number;
|
||||
severity?: 'info' | 'warn' | 'error';
|
||||
cooldown_seconds?: number;
|
||||
enabled?: boolean;
|
||||
}
|
||||
export function listMetricAlertRules(opts?: {
|
||||
workloadID?: string;
|
||||
signal?: AbortSignal;
|
||||
}): Promise<MetricAlertRule[]> {
|
||||
const params = opts?.workloadID ? `?workload_id=${encodeURIComponent(opts.workloadID)}` : '';
|
||||
return get<MetricAlertRule[]>(`/api/metric-alert-rules${params}`, opts?.signal);
|
||||
}
|
||||
export function getMetricAlertRule(id: number, signal?: AbortSignal): Promise<MetricAlertRule> {
|
||||
return get<MetricAlertRule>(`/api/metric-alert-rules/${id}`, signal);
|
||||
}
|
||||
export function createMetricAlertRule(data: MetricAlertRuleInput): Promise<MetricAlertRule> {
|
||||
return post<MetricAlertRule>('/api/metric-alert-rules', data);
|
||||
}
|
||||
export function updateMetricAlertRule(
|
||||
id: number,
|
||||
data: MetricAlertRuleInput
|
||||
): Promise<MetricAlertRule> {
|
||||
return patch<MetricAlertRule>(`/api/metric-alert-rules/${id}`, data);
|
||||
}
|
||||
export function deleteMetricAlertRule(id: number): Promise<void> {
|
||||
return del<void>(`/api/metric-alert-rules/${id}`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user