2015-10-09 3 views
0

Я пытаюсь реализовать следующий прецедент: Нужно запустить один аварийный сигнал с первой причиной, если несколько аварийных сигналов с таким же свойством поступают с интервалом времени 30 секунд.Drools: пожар одного события для каждого факта в группе с течением времени

Я написал код, но он имеет 2 ряд недостатков:

  1. Это срабатывает сигнал тревоги для каждого пришел сигнал тревоги в группе со счетом> 1
  2. правило работает только один раз. Если я посылаю сигнал тревоги через одно минутное правило, не срабатывает.

    rule "fire rca when at least 2 events arrive in timeWindow" 
    when 
        $alert: AlertEvent(type == Type.RAISE, 
           this.isPropertySet("elementSystemID"), 
           ElementSystemID: alertProperties["elementSystemID"] 
           ) 
        accumulate(
        $a: AlertEvent(type == Type.RAISE, 
          alertProperties["elementSystemID"] == ElementSystemID, 
        ) over window:time(30s); 
        $cnt: count($a); 
        $cnt > 1 
    ) 
    then 
        HashMap<String,Object> props = new HashMap<String,Object>(); 
    
        props.put(AlertConstants.DISPLAY_NAME, "RCA on port"); 
        props.put(AlertConstants.PERCEIVED_SEVERITY, 6); 
        props.put(AlertConstants.ELEMENT_ID, $alert.getProperty("SystemID")); 
    
        ruleActions.raiseAlert(props, "Alert raised"); 
    end 
    

ответ

1

Это гораздо лучше, чтобы избежать окна: время и накапливать.

Вот утилита класса:

public class Monitor { 
    private final static long INTERVAL = 30*1000; 
    private int sysId; 
    private Date startTime; 
    private int count = 1; 
    public Monitor(int sysId, Date startTime){ 
     this.sysId = sysId; 
     this.startTime = startTime; 
    } 
    public int getSysId(){ return sysId; } 
    public Date getStartTime(){ return startTime; } 
    public void reset(Date startTime){ 
     this.startTime = startTime; 
     count = 1; 
    } 
    public int getCount(){ return count; } 
    public void incCount(){ count++; } 
    public boolean inInterval(Date t){ 
     return (t.getTime() - startTime.getTime()) < INTERVAL; 
    } 
} 

А вот правила - они должны быть достаточно само за себя.

rule "new id" 
when 
    $ae: AlertEvent($id: sysId) 
    not Monitor(sysId == $id) 
then 
    retract($ae); 
    insert(new Monitor($id, new Date())); 
end 

rule "same id, within interval, second" 
when 
    $ae: AlertEvent($id: sysId, $ts: timestamp) 
    $m: Monitor(sysId == $id, count == 1, 
       eval($m.inInterval($ts))) 
then 
    retract($ae); 
    modify($m){ incCount() } 
    System.out.println("alarm for " + $id); 
end 

// This rule is redundant - just in case. 
rule "same id, within interval, third or more" 
when 
    $ae: AlertEvent($id: sysId, $ts: timestamp) 
    $m: Monitor(sysId == $id, count > 1, 
        eval($m.inInterval($ts))) 
then 
    retract($ae); 
    modify($m){ incCount() } 
end 

rule "same id, not within interval" 
when 
    $ae: AlertEvent($id: sysId, $ts: timestamp) 
    $m: Monitor(sysId == $id, 
       eval(! $m.inInterval($ts))) 
then 
    retract($ae); 
    modify($m){ reset(new Date()) } 
end