Hi,
I am using the latest 5.1.1 (8/2010 release) Drools code to test out
rules. What I see is when I try to retract/insert an object from the
working memory, it doesn't seem to take effect.
The example is as follows. I pump metrics into the rule engine at 4s
interval. Drools is configured to run in STREAM mode to allow facts to
expire and to use the sliding window feature of Fusion. There are 2
rules, the set rule says that if the minimum value is > set threshold
over the sliding window interval, raise an alarm if not raised earlier
(it also inserts an alarm into the working memory). The clear rule says
that if the minimum value is < clear threshold over the sliding window
interval and if alarm exists, then clear the alarm and retract it.
I use the pseudo clock and advance every time I insert an event. Now, if
I use a data set, where all the values are > set threshold, then I see
that an alarm is raised and only once (as expected). But if I use a data
set that should cause a set/clear/set pattern, I see that after setting,
the clear happens twice, followed by set, which happens twice again.
I used the Drools debugger within Eclipse and saw that I was hitting the
RHS side twice in the clear/set rule. As I cannot put a break-point on
the LHS to see why it decided to do fire in the first place, I can't
tell the behavior.
Its as if drools ignores the insert/retract of the alarm action.
Thanks in advance,
sb
Here is the DRL:
package com.x.y.rules;
import java.util.Date;
import com.x.y.z.ruleengine.AlarmActionFactory;
import com.x.y.z.rule.Event.Srd;
import com.x.y.z.NaEvent;
import com.x.y.z.Common.SeverityLevels;
import com.x.y.z.Common.EventsStatus;
import com.x.y.z.rule.Event.Alarm;
global AlarmActionFactory actionFactory;
declare Srd
@role(event)
@expires(5s)
end
rule "Clear Srd threshold of 25.0 for 5s"
dialect "java"
when
$c : Srd(probeName == 'threstest1')
$SrdMin : Number(doubleValue <= 25.0) from accumulate(
Srd(probeName == $c.probeName,$v : value) over window:time(5s),
min($v)
)
$alarm : Alarm(type == 'Srd' && probeName == 'threstest1')
then
if($alarm !=null)
{
System.out.println("Clearing alarm, since Srd went below
25.0 threshold for 5s. Srd: "+$SrdMin);
System.out.println("Removing alarm from system "+$alarm);
retract($alarm);
String desc = "Clearing alarm as SessionRequestDelayMilliSecs went
below threshold 25.0 for probe threstest1";
actionFactory.logEvent(desc);
}
else
actionFactory.logEvent("WARN: clearing again, alarm doesnt
exist for Srd metric with probename threstest1");
end
rule "Set Srd threshold of 50.0 for 5s"
dialect "java"
when
$c : Srd(probeName == 'threstest1')
$minsrd : Number(doubleValue >= 50.0) from accumulate(
Srd(probeName == $c.probeName,$v : value) over window:time(5s),
min($v)
)
not Alarm(type == 'Srd' && probeName == 'threstest1')
then
System.out.println("Srd above 50.0 for 5s, raising alarm. min Srd:
"+$minsrd);
Alarm a = new Alarm("Srd","threstest1");
insert(a);
String desc = "Raised alarm as SessionRequestDelayMilliSecs hit
threshold 50.0 for probe threstest1";
actionFactory.logEvent(desc);
end
Here is the data set that is read by the java class pumping the events.
# the set/clear threshold in thres1_Srd.drl is set to 50/25.O
# the test program reads the values one line at a time
# the sliding window time and fact expiration time it set to 5s.
# the test program advances the pseudo clock by delta value
# which is the difference between the previous and the current token
value
# read from this file.
# the alarm raising pattern for this data should be
# set/clear/set
# NOTE: first value is time, second value is the actual event value.
1358,60
5359,66
9360,62
13361,24
17362,23
21363,24
25364,28
29365,21
33366,27
37367,67
41367,89
45367,92
49367,72
53367,65
57367,99
Snippet of main method of the java class
KnowledgeBuilder kbuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder();
boolean useSrdMetric = true;
kbuilder.add(ResourceFactory.newClassPathResource("threstest1_Srd.drl",
REAlarmFiringTest.class),
ResourceType.DRL);
// Check the builder for errors
if (kbuilder.hasErrors())
{
System.out.println(kbuilder.getErrors().toString());
throw new RuntimeException("Unable to compile "
+ ("Srd".equals(args[0]) ? "thres1_Srd.drl" :
"thres1_Owd.drl"));
}
// get the compiled packages (which are serializable)
Collection<KnowledgePackage> pkgs =
kbuilder.getKnowledgePackages();
// to use sliding windows, have to run the engine in stream mode
// default is cloud mode..where there are no concept of time and
// event ordering
KnowledgeBaseConfiguration kbaseconfig =
KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
kbaseconfig.setOption(EventProcessingOption.STREAM);
// add the packages to a knowledgebase (deploy the knowledge
packages).
KnowledgeBase kbase =
KnowledgeBaseFactory.newKnowledgeBase(kbaseconfig);
kbase.addKnowledgePackages(pkgs);
KnowledgeSessionConfiguration conf =
KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
conf.setOption(ClockTypeOption.get("pseudo"));
StatefulKnowledgeSession ksession =
kbase.newStatefulKnowledgeSession(conf, null);
// get clock to manually advance and test firing..
SessionPseudoClock clock = ksession.getSessionClock();
logger.info("Pseudo clock current time initialized to " +
clock.getCurrentTime());
// we will have one helper class AlarmActionFactory, that will
provide
// static methods for all the possible actions that can be taken
// when an alarm fires, including logging events.
ksession.setGlobal("actionFactory",
AlarmActionFactory.newInstance());
// this will send data to the std err stream
ksession.addEventListener(new DebugAgendaEventListener());
ksession.addEventListener(new DebugWorkingMemoryEventListener());
// setup the audit logging
KnowledgeRuntimeLogger krlogger =
KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, destdir
+ ("Srd".equals(args[0]) ? "srdaudit" :
"owdaudit"));
BufferedReader bf = new BufferedReader(new FileReader(args[1]));
String s;
int time = 0;
int count = 0;
int lastime = 0;
int delta = 0;
// NOTE: the drl are setup with a sliding window of 5s.
// We will insert objects into the RE every 4s, so that the
// previous objects linger long enough to contribute to the calc
while ((s = bf.readLine()) != null)
{
if (s.startsWith("#"))
continue;
String[] vals = s.split(",");
Event event = new Srd();
event.setValue(Integer.parseInt(vals[1]));
// set in ms
// for the first time, initialize time and lastime
// to the value read in from the first line.
time = Integer.parseInt(vals[0]);
if (count == 0)
{
lastime = time;
logger.info("Initialized lastime to " + lastime);
// this is basically time t0 when the first event gets
inserted
clock.advanceTime(time, TimeUnit.MILLISECONDS);
} else
{
// advance based on the read in time in ms
// do it only from the second insert onwards
// note that the time delta should be around 4s
delta = (int) (time - lastime);
clock.advanceTime(delta, TimeUnit.MILLISECONDS);
logger.info("Pseudo clock advanced " + delta + "ms");
}
event.setTimestamp(time);
// the probename has to be threstest1 as the drls are
configured with
// that probe name. so do not change this value.
event.setProbeName("threstest1");
logger.info("Inserted event " + event);
logger.info("Count: " + count + " Pseudo clock current time:
"
+ clock.getCurrentTime());
ksession.insert(event);
logger.info("calling drools fire rules");
ksession.fireAllRules();
count++;
lastime = time;
}
System.out.println("Inserted facts, current time is " + new
Date());
krlogger.close();
ksession.dispose();
bf.close();
System.out.println("Closed audit logger, disposing session,
exiting..");
Here is the log output of the run of the program above: Note the EVENT
MESSAGE green/red output, which gets printed as a consequence of the
rule firing. Red indicates it fired again without any other insertion of
event.
2010-09-24 11:53:17,039-INFO -[main]: Pseudo clock current time
initialized to 0
2010-09-24 11:53:17,053-INFO -[main]: Initialized lastime to 1358
2010-09-24 11:53:17,054-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=1358, value=60.0]
2010-09-24 11:53:17,054-INFO -[main]: Count: 0 Pseudo clock current
time: 1358
2010-09-24 11:53:17,074-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,076-INFO -[main]: EVENT MESSAGE: Raised alarm as
SessionRequ
estDelayMilliSecs hit threshold 50.0 for probe threstest1
2010-09-24 11:53:17,077-INFO -[main]: Pseudo clock advanced 4001ms
2010-09-24 11:53:17,077-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=5359, value=66.0]
2010-09-24 11:53:17,077-INFO -[main]: Count: 1 Pseudo clock current
time: 5359
2010-09-24 11:53:17,077-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,077-INFO -[main]: Pseudo clock advanced 4001ms
2010-09-24 11:53:17,078-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=9360, value=62.0]
2010-09-24 11:53:17,078-INFO -[main]: Count: 2 Pseudo clock current
time: 9360
2010-09-24 11:53:17,080-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,080-INFO -[main]: Pseudo clock advanced 4001ms
2010-09-24 11:53:17,080-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=13361, value=24.0]
2010-09-24 11:53:17,080-INFO -[main]: Count: 3 Pseudo clock current
time: 13361
2010-09-24 11:53:17,081-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,082-INFO -[main]: EVENT MESSAGE: Clearing alarm as
SessionRe
questDelayMilliSecs went below threshold 25.0 for probe threstest1
2010-09-24 11:53:17,082-INFO -[main]: EVENT MESSAGE: WARN: clearing
again, alarm
doesnt exist for Srd metric with probename threstest1
2010-09-24 11:53:17,082-INFO -[main]: Pseudo clock advanced 4001ms
2010-09-24 11:53:17,083-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=17362, value=23.0]
2010-09-24 11:53:17,083-INFO -[main]: Count: 4 Pseudo clock current
time: 17362
2010-09-24 11:53:17,083-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,083-INFO -[main]: Pseudo clock advanced 4001ms
2010-09-24 11:53:17,083-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=21363, value=24.0]
2010-09-24 11:53:17,084-INFO -[main]: Count: 5 Pseudo clock current
time: 21363
2010-09-24 11:53:17,084-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,084-INFO -[main]: Pseudo clock advanced 4001ms
2010-09-24 11:53:17,084-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=25364, value=28.0]
2010-09-24 11:53:17,085-INFO -[main]: Count: 6 Pseudo clock current
time: 25364
2010-09-24 11:53:17,085-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,085-INFO -[main]: Pseudo clock advanced 4001ms
2010-09-24 11:53:17,085-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=29365, value=21.0]
2010-09-24 11:53:17,086-INFO -[main]: Count: 7 Pseudo clock current
time: 29365
2010-09-24 11:53:17,086-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,086-INFO -[main]: Pseudo clock advanced 4001ms
2010-09-24 11:53:17,087-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=33366, value=27.0]
2010-09-24 11:53:17,087-INFO -[main]: Count: 8 Pseudo clock current
time: 33366
2010-09-24 11:53:17,087-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,088-INFO -[main]: Pseudo clock advanced 4001ms
2010-09-24 11:53:17,088-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=37367, value=67.0]
2010-09-24 11:53:17,088-INFO -[main]: Count: 9 Pseudo clock current
time: 37367
2010-09-24 11:53:17,088-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,089-INFO -[main]: Pseudo clock advanced 4000ms
2010-09-24 11:53:17,089-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=41367, value=89.0]
2010-09-24 11:53:17,089-INFO -[main]: Count: 10 Pseudo clock current
time: 41367
2010-09-24 11:53:17,090-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,090-INFO -[main]: EVENT MESSAGE: Raised alarm as
SessionRequ
estDelayMilliSecs hit threshold 50.0 for probe threstest1
2010-09-24 11:53:17,090-INFO -[main]: EVENT MESSAGE: Raised alarm as
SessionRequ
estDelayMilliSecs hit threshold 50.0 for probe threstest1
2010-09-24 11:53:17,091-INFO -[main]: Pseudo clock advanced 4000ms
2010-09-24 11:53:17,091-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=45367, value=92.0]
2010-09-24 11:53:17,091-INFO -[main]: Count: 11 Pseudo clock current
time: 45367
2010-09-24 11:53:17,092-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,092-INFO -[main]: Pseudo clock advanced 4000ms
2010-09-24 11:53:17,092-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=49367, value=72.0]
2010-09-24 11:53:17,092-INFO -[main]: Count: 12 Pseudo clock current
time: 49367
2010-09-24 11:53:17,093-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,093-INFO -[main]: Pseudo clock advanced 4000ms
2010-09-24 11:53:17,093-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=53367, value=65.0]
2010-09-24 11:53:17,093-INFO -[main]: Count: 13 Pseudo clock current
time: 53367
2010-09-24 11:53:17,094-INFO -[main]: calling drools fire rules
2010-09-24 11:53:17,094-INFO -[main]: Pseudo clock advanced 4000ms
2010-09-24 11:53:17,094-INFO -[main]: Inserted event Srd
[probeName=threstest1,
destIp=10.155.21.81, srcIp=10.155.21.82, timestamp=57367, value=99.0]
2010-09-24 11:53:17,094-INFO -[main]: Count: 14 Pseudo clock current
time: 57367
2010-09-24 11:53:17,095-INFO -[main]: calling drools fire rules