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