简体   繁体   中英

Drools: fire one event for each fact in group over time window

I'm trying to implement following use case: It needs to fire single root cause alarm if several alarms with the same property arrive in 30s time interval.

I wrote the code, but it has 2 several drawbacks:

  1. It fires alarm for each arrived alarm in group with count > 1
  2. Rule works only once. If I send alarm after one minute rule doesn't fire.

     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 

It is much better to avoid window:time and accumulate.

Here's a utility class:

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;
    }
}

And here are the rules - they should be rather self-explanatory.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM