@@ -5,9 +5,14 @@ import {
55 Alert ,
66 AlertSeverity ,
77 AlertStates ,
8+ PrometheusAlert ,
89 PrometheusLabels ,
10+ PrometheusRule ,
911 RowFilter ,
1012 Rule ,
13+ RuleStates ,
14+ Silence ,
15+ SilenceStates ,
1116 Timestamp ,
1217} from '@openshift-console/dynamic-plugin-sdk' ;
1318import { AlertSource } from '../types' ;
@@ -420,3 +425,147 @@ export const NamespaceGroupVersionKind = {
420425 kind : NamespaceModel . kind ,
421426 version : null ,
422427} ;
428+
429+ // This function looks to take a alerts and rules and then apply a set of silences to them
430+ // This function mutates the arrays in place and then returns them
431+ export const applySilences = ( {
432+ alerts,
433+ silences,
434+ rules,
435+ } : {
436+ silences : Array < Silence > ;
437+ alerts : Array < Alert > ;
438+ rules : Array < Rule > ;
439+ } ) : { silences : Array < Silence > ; alerts : Array < Alert > ; rules : Array < Rule > } => {
440+ // We only need to check alerts that are either firing or silenced for if they are still silenced
441+ const firingAlerts = alerts . filter ( isAlertFiring ) ;
442+ applySilencesToAlerts ( { firingAlerts, silences } ) ;
443+
444+ // Only check rules that are firing, silenced or pending to see if they are still silenced
445+ const firingRules = rules . filter ( isRuleFiring ) ;
446+ applySilencesToRules ( { firingRules, silences } ) ;
447+
448+ // Add each alert that is being effected by a silence to the firingAlerts list on the silence
449+ const appliedSilences = silences . map ( ( silence ) => {
450+ silence . firingAlerts = firingAlerts . filter ( ( firingAlert ) =>
451+ isAlertSilenced ( firingAlert , silence ) ,
452+ ) ;
453+ return silence ;
454+ } ) ;
455+ return { alerts, silences : appliedSilences , rules } ;
456+ } ;
457+
458+ // This fucntion mutates the firingAlerts parameter in place to set silence fields on each alert
459+ const applySilencesToAlerts = ( {
460+ firingAlerts,
461+ silences,
462+ } : {
463+ silences : Array < Silence > ;
464+ firingAlerts : Array < Alert > ;
465+ } ) => {
466+ // For each firing alert, store a list of the Silences that are silencing it
467+ // and set its state to show it is silenced
468+ firingAlerts . forEach ( ( firingAlert ) => {
469+ firingAlert . silencedBy = silences . filter (
470+ ( silence ) =>
471+ silence . status ?. state === SilenceStates . Active && isAlertSilenced ( firingAlert , silence ) ,
472+ ) ;
473+
474+ if ( firingAlert . silencedBy . length ) {
475+ firingAlert . state = AlertStates . Silenced ;
476+ // Also set the state of Alerts in `rule.alerts`
477+
478+ firingAlert . rule . alerts . forEach ( ( ruleAlert ) => {
479+ if ( firingAlert . silencedBy ?. some ( ( silence ) => isAlertSilenced ( ruleAlert , silence ) ) ) {
480+ ruleAlert . state = AlertStates . Silenced ;
481+ }
482+ } ) ;
483+
484+ if (
485+ firingAlert . rule . alerts . length !== 0 &&
486+ firingAlert . rule . alerts . every ( ( alert ) => alert . state === AlertStates . Silenced )
487+ ) {
488+ firingAlert . rule . state = RuleStates . Silenced ;
489+
490+ firingAlert . rule . silencedBy = silences . filter (
491+ ( silence ) =>
492+ silence . status ?. state === SilenceStates . Active &&
493+ firingAlert . rule . alerts . some ( ( alert ) => isAlertSilenced ( alert , silence ) ) ,
494+ ) ;
495+ }
496+ }
497+ } ) ;
498+
499+ return firingAlerts ;
500+ } ;
501+
502+ // This fucntion mutates the firingRules parameter in place to set silence fields on each rule
503+ const applySilencesToRules = ( {
504+ firingRules,
505+ silences,
506+ } : {
507+ silences : Array < Silence > ;
508+ firingRules : Array < Rule > ;
509+ } ) => {
510+ // For each firing alert, store a list of the Silences that are silencing it
511+ // and set its state to show it is silenced
512+ firingRules . forEach ( ( firingRule ) => {
513+ firingRule . silencedBy = silences . filter (
514+ ( silence ) =>
515+ silence . status ?. state === SilenceStates . Active && isRuleSilenced ( firingRule , silence ) ,
516+ ) ;
517+
518+ if ( firingRule . silencedBy . length ) {
519+ firingRule . state = RuleStates . Silenced ;
520+
521+ firingRule . alerts . forEach ( ( ruleAlert ) => {
522+ if ( firingRule . silencedBy ?. some ( ( silence ) => isAlertSilenced ( ruleAlert , silence ) ) ) {
523+ ruleAlert . state = AlertStates . Silenced ;
524+ }
525+ } ) ;
526+
527+ if (
528+ firingRule . alerts . length !== 0 &&
529+ firingRule . alerts . every ( ( alert ) => alert . state === AlertStates . Silenced )
530+ ) {
531+ firingRule . state = RuleStates . Silenced ;
532+
533+ firingRule . silencedBy = silences . filter (
534+ ( silence ) =>
535+ silence . status ?. state === SilenceStates . Active &&
536+ firingRule . alerts . some ( ( alert ) => isAlertSilenced ( alert , silence ) ) ,
537+ ) ;
538+ }
539+ }
540+ } ) ;
541+
542+ return firingRules ;
543+ } ;
544+
545+ const isAlertFiring = ( alert : PrometheusAlert ) =>
546+ alert ?. state === AlertStates . Firing || alert ?. state === AlertStates . Silenced ;
547+
548+ const isRuleFiring = ( rule : PrometheusRule ) =>
549+ rule ?. state === RuleStates . Firing ||
550+ rule ?. state === RuleStates . Silenced ||
551+ rule ?. state === RuleStates . Pending ;
552+
553+ // Determine if an Alert is silenced by a Silence (if all of the Silence's matchers match one of the
554+ // Alert's labels)
555+ const isAlertSilenced = ( alert : PrometheusAlert , silence : Silence ) : boolean => {
556+ return (
557+ isAlertFiring ( alert ) &&
558+ silence . matchers . every ( ( matcher ) => {
559+ const alertValue = alert . labels [ matcher . name ] ?? '' ;
560+ const isMatch = matcher . isRegex
561+ ? new RegExp ( `^${ matcher . value } $` ) . test ( alertValue )
562+ : alertValue === matcher . value ;
563+ return matcher . isEqual === false && alertValue ? ! isMatch : isMatch ;
564+ } )
565+ ) ;
566+ } ;
567+
568+ // Determine if an Rule is silenced by a Silence (if all alerts for a rule are silenced)
569+ export const isRuleSilenced = ( rule : PrometheusRule , silence : Silence ) : boolean => {
570+ return isRuleFiring ( rule ) && rule . alerts . every ( ( alert ) => isAlertSilenced ( alert , silence ) ) ;
571+ } ;
0 commit comments