Drools:随着时间的推移,为组中的每个事实触发一个事件 window
Drools: fire one event for each fact in group over time window
我正在尝试实现以下用例:
如果具有相同属性的多个警报在 30s 时间间隔内到达,则需要触发单一根本原因警报。
我写了代码,但它有两个缺点:
- 它会为计数 > 1 的组中每个到达的警报触发警报
规则只有效一次。如果我在一分钟后发送警报,规则不会触发。
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
避window:time多积累就好
这是一个实用程序 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;
}
}
这里是规则 - 它们应该是不言自明的。
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
我正在尝试实现以下用例: 如果具有相同属性的多个警报在 30s 时间间隔内到达,则需要触发单一根本原因警报。
我写了代码,但它有两个缺点:
- 它会为计数 > 1 的组中每个到达的警报触发警报
规则只有效一次。如果我在一分钟后发送警报,规则不会触发。
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
避window:time多积累就好
这是一个实用程序 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;
}
}
这里是规则 - 它们应该是不言自明的。
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