Drools:在一段时间内为组中的每个事实触发一个事件

时间:2015-10-09 10:59:34

标签: java drools rule-engine

我试图实现以下用例: 如果具有相同属性的多个警报在30秒的时间间隔内到达,则需要触发单根原因警报。

我编写了代码,但它有两个缺点:

  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 个答案:

答案 0 :(得分:2)

最好避免窗口:时间和累积。

这是一个实用程序类:

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