From 71d0401c803f70e7c52c4e352f459cb557d43fd1 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Mon, 22 Dec 2025 10:03:12 +0000 Subject: [PATCH] feat: Add guest filtering by tag and name prefix via Alert Configuration. Resolves #863 --- .../src/components/Alerts/ThresholdsTable.tsx | 120 ++++++++++++++++++ frontend-modern/src/pages/Alerts.tsx | 37 +++++- frontend-modern/src/types/alerts.ts | 3 + internal/alerts/alerts.go | 56 ++++++++ 4 files changed, 214 insertions(+), 2 deletions(-) diff --git a/frontend-modern/src/components/Alerts/ThresholdsTable.tsx b/frontend-modern/src/components/Alerts/ThresholdsTable.tsx index 46ba61301..e8e77db9f 100644 --- a/frontend-modern/src/components/Alerts/ThresholdsTable.tsx +++ b/frontend-modern/src/components/Alerts/ThresholdsTable.tsx @@ -244,6 +244,12 @@ interface ThresholdsTableProps { ) => void; dockerIgnoredPrefixes: () => string[]; setDockerIgnoredPrefixes: (value: string[] | ((prev: string[]) => string[])) => void; + ignoredGuestPrefixes: () => string[]; + setIgnoredGuestPrefixes: (value: string[] | ((prev: string[]) => string[])) => void; + guestTagWhitelist: () => string[]; + setGuestTagWhitelist: (value: string[] | ((prev: string[]) => string[])) => void; + guestTagBlacklist: () => string[]; + setGuestTagBlacklist: (value: string[] | ((prev: string[]) => string[])) => void; storageDefault: () => number; setStorageDefault: (value: number) => void; resetGuestDefaults?: () => void; @@ -432,6 +438,67 @@ export function ThresholdsTable(props: ThresholdsTableProps) { props.setHasUnsavedChanges(true); }; + const [ignoredGuestInput, setIgnoredGuestInput] = createSignal( + props.ignoredGuestPrefixes().join('\n'), + ); + const [guestTagWhitelistInput, setGuestTagWhitelistInput] = createSignal( + props.guestTagWhitelist().join('\n'), + ); + const [guestTagBlacklistInput, setGuestTagBlacklistInput] = createSignal( + props.guestTagBlacklist().join('\n'), + ); + + createEffect(() => { + const remote = props.ignoredGuestPrefixes(); + const local = ignoredGuestInput(); + const normalizedLocal = normalizeDockerIgnoredInput(local); + const isSynced = + remote.length === normalizedLocal.length && + remote.every((val, i) => val === normalizedLocal[i]); + if (!isSynced) setIgnoredGuestInput(remote.join('\n')); + }); + + createEffect(() => { + const remote = props.guestTagWhitelist(); + const local = guestTagWhitelistInput(); + const normalizedLocal = normalizeDockerIgnoredInput(local); + const isSynced = + remote.length === normalizedLocal.length && + remote.every((val, i) => val === normalizedLocal[i]); + if (!isSynced) setGuestTagWhitelistInput(remote.join('\n')); + }); + + createEffect(() => { + const remote = props.guestTagBlacklist(); + const local = guestTagBlacklistInput(); + const normalizedLocal = normalizeDockerIgnoredInput(local); + const isSynced = + remote.length === normalizedLocal.length && + remote.every((val, i) => val === normalizedLocal[i]); + if (!isSynced) setGuestTagBlacklistInput(remote.join('\n')); + }); + + const handleIgnoredGuestChange = (value: string) => { + setIgnoredGuestInput(value); + const normalized = normalizeDockerIgnoredInput(value); + props.setIgnoredGuestPrefixes(normalized); + props.setHasUnsavedChanges(true); + }; + + const handleGuestTagWhitelistChange = (value: string) => { + setGuestTagWhitelistInput(value); + const normalized = normalizeDockerIgnoredInput(value); + props.setGuestTagWhitelist(normalized); + props.setHasUnsavedChanges(true); + }; + + const handleGuestTagBlacklistChange = (value: string) => { + setGuestTagBlacklistInput(value); + const normalized = normalizeDockerIgnoredInput(value); + props.setGuestTagBlacklist(normalized); + props.setHasUnsavedChanges(true); + }; + // Set up keyboard shortcuts onMount(() => { const isEditableElement = (el: HTMLElement | null | undefined): boolean => { @@ -2552,6 +2619,59 @@ export function ThresholdsTable(props: ThresholdsTableProps) { + + toggleSection('guest-filtering')} + icon={} + emptyMessage="Configure guest filtering rules." + > +
+ +
+

Ignored Prefixes

+

Skip metrics for guests starting with:

+
+