特定のイベントが最後の「m」の期間に「n」回発生したかどうかを検出するルールを作成しようとしています。私はdroolsバージョン5.4.Finalを使用しています。5.5.Finalも試しましたが効果はありません。
Droolsがそれを呼んでいるように、いくつかの条件付き要素があり、蓄積して収集することがわかりました。以下のサンプルルールでcollectを使用しました
rule "check-login-attack-rule-1"
dialect "java"
when
$logMessage: LogMessage()
$logMessages : ArrayList ( size >= 3 )
from collect(LogMessage(getAction().equals(Action.Login)
&& isProcessed() == false)
over window:time(10s))
then
LogManager.debug(Poc.class, "!!!!! Login Attack detected. Generating alert.!!!"+$logMessages.size());
LogManager.debug(Poc.class, "Current Log Message: "+$logMessage.getEventName()+":"+(new Date($logMessage.getTime())));
int size = $logMessages.size();
for(int i = 0 ; i < size; i++) {
Object msgObj = $logMessages.get(i);
LogMessage msg = (LogMessage) msgObj;
LogManager.debug(Poc.class, "LogMessage: "+msg.getEventName()+":"+(new Date(msg.getTime())));
msg.setProcessed(true);
update(msgObj); // Does not work. Rule execution does not proceed beyond this point.
// retract(msgObj) // Does not work. Rule execution does not proceed beyond this point.
}
// Completed processing the logs over a given window. Now removing the processed logs.
//retract($logMessages) // Does not work. Rule execution does not proceed beyond this point.
終わり
ログを挿入するコードは以下のとおりです。このコードは、3秒ごとにログを挿入し、ルールを実行します。
final StatefulKnowledgeSession kSession = kBase.newStatefulKnowledgeSession();
long msgId = 0;
while(true) {
// Generate Log messages every 3 Secs.
// Every alternate log message will satisfy a rule condition
LogMessage log = null;
log = new LogMessage();
log.setEventName("msg:"+msgId);
log.setAction(LogMessage.Action.Login);
LogManager.debug(Poc.class, "PUSHING LOG: "+log.getEventName()+":"+log.getTime());
kSession.insert(log);
kSession.fireAllRules();
LogManager.debug(Poc.class, "PUSHED LOG: "+log.getEventName()+":"+(new Date(log.getTime())));
// Sleep for 3 secs
try {
sleep(3*1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
msgId++;
}
これで、私が達成できたのは、過去10秒間に上記のLogMessageの存在を確認することです。また、ルールをトリガーする最後の10秒間に発生したLogMessageの正確なセットを見つけることもできました。
問題は、これらのメッセージが処理されたら、次の評価サイクルに参加してはならないということです。これは私が達成できなかったことです。これを例を挙げて説明します。
以下のタイムラインを検討してください。タイムラインには、ログメッセージの挿入と、発生する必要のあるアラート生成の状態が表示されます。
期待される結果
秒- ログ - アラート
0-LogMessage1-アラートなし
3--LogMessage2-アラートなし
6 --LogMessage3 --Alert1(LogMessage1、LogMessage2、LogMessage3)
9--LogMessage4-アラートなし
12--LogMessage5-アラートなし
15 --LogMessage6-Alert2(LogMessage4、LogMessage5、LogMessage6)
しかし、現在のコードで何が起こっているのか
実結果
秒 - ログ - アラート
0-LogMessage1-アラートなし
3--LogMessage2-アラートなし
6 --LogMessage3 --Alert1(LogMessage1、LogMessage2、LogMessage3)
9 --LogMessage4-Alert2(LogMessage2、LogMessage3、LogMessage4)
12 --LogMessage5-Alert3(LogMessage3、LogMessage4、LogMessage5)
15 --LogMessage6-Alert4(LogMessage4、LogMessage5、LogMessage6)
基本的に、すでに処理されてアラート生成に参加しているメッセージを破棄することはできません。リトラクトを使用して、処理されたファクトを作業メモリーから削除しようとしました。しかし、ルールのその部分にリトラクトを追加すると、ルールはまったく実行されなくなりました。リトラクトを追加した後、ルールの実行が停止する理由を理解できませんでした。
どこがおかしいのか教えてください。