Drools slowness in first calls
by Gael
Hi,
We are using Drools for a heavy process and we notice some slowness during
the first calls to kbases (containing about 1500 rules each) using
StatefulKnowledgeSession.
Even if the kbase is "loaded", we need to make some "fictive" calls (fire
the rules with some facts) until it begins to respond within a reasonable
time. It's like we need to warm it up..
Any idea about what Drools does during this time?
Is there a way to programmatically launch these processing without the need
to have facts ?
Thanks in advance and sorry for my english.
NB : we use Drools 5.5.
Regards,
Gael
--
View this message in context: http://drools.46999.n3.nabble.com/Drools-slowness-in-first-calls-tp402988...
Sent from the Drools: User forum mailing list archive at Nabble.com.
10 years, 5 months
Re: [rules-users] Monitoring applications using Drools
by Sushant Goyal
Thanks for your quick
response.
I am using 5.3.0 Final version of Drools. Attached are the
necessary files (DRL, fact, test class) required to reproduce the effect.
Please let me know if any further details are required.
Thanks!
On Thursday, 5 June 2014 2:23 PM, Wolfgang Laun <wolfgang.laun(a)gmail.com> wrote:
On first reading, both observations could be bugs. But it is difficult to
assess such situation without knowing the Drools version, without
having a complete (but minimal) set of Java and DRL code reproducing
the effect.
-W
On 05/06/2014, Sushant Goyal <sushantgoyal25(a)yahoo.co.in> wrote:
> Thanks again for your response Wolfgang.
>
> I found one of the explanations on how Sliding Windows
> operate in Drools while searching for an answer:
> "Events are expired
> from the time window when the clock advances"
>
> So, in my case if I am inserting events on T0 (insert 1st event), T1 (insert
> 2nd event), T2 (insert 3rd event) and
> advancing the clock to T3, T4 and T5; 1st event inserted at T0 is
> expired from the window. And the rule calculates the average of the last two
> events (2nd event & 3rd event) falling in the time
> window. And the output average calculated by the from accumulate function
> comes
> to be (26 +28 / 2 == 27) satisfying the contract of average temperature to
> be above
> the threshold value of 25.
>
> Now let's say I do the below (advancing the clock by 5
> minutes after the 3rd insert):
>
> T0 (insert 1st event)
> T1 (insert 2st event)
> T2 (insert 3st event)
> T3
> T4
> T5
> T6
> T7
> Fire all rules
>
> The average calculated by the rule is zero (0) since the
> three inserted events fall outside the time window of 5 minutes (as
> expected).
> But, my rule fires regardless of the fact I have the contract of average
> temperature
> to be greater than threshold in my rule :
>
> $averageTemp : Number(intValue
>> 25)
> from
> accumulate(SensorReading($temp : temperature)
> over
> window:time(5m) from
> entry-point "Temperature Reading", average($temp))
>
> As per the drools-fusion documentation, over window : time(X) is used to
> consider events that happened in
> the last X units. So, is there something that needs to be changed in my rule
> implementation?
>
> One more question here, does over window : time(X) really considers events
> occurred in the last
> X units. I tried going further by doing the below:
>
> T0 (insert 1st event - Sensor reading is 24)
> T1 (insert 2st event - Sensor reading is 26)
> T2 (insert 3st event - Sensor reading is 28)
> T3
> T4
> T5
> T6
> T7
> (insert event - Sensor reading is 30)
> Fire All rules
>
> With the above test setup, my rule gets invoked twice printing
> the average of temperatures as (30) and (30). But using over window:time(5m)
> shouldn't result in rule being triggered once ?
>
> Thanks in advance!
>
>
>
> On Thursday, 5 June 2014 12:31 PM, Wolfgang Laun <wolfgang.laun(a)gmail.com>
> wrote:
>
>
>
> Computations involving intervals where events arrive in real time
> should not depend on differences of one unit of the smalles unit of
> time for specifying durations (here: milliseconds).
>
> -W
>
>
>
>
> On 04/06/2014, Sushant Goyal <sushantgoyal25(a)yahoo.co.in> wrote:
>> Thanks for your response.
>> I was under the assumption that the window time frame begins, the moment
>> first event is inserted into the working memory. Or I am still missing out
>> something here (when you say that the first event is exactly at the
>> beginning of the window)? If I traverse backwards as below, then
>> definitely
>> the 1st event lies outside the window.
>>
>> insert 1st event
>> delay 1 minute ^ (4 + 1 = 5)
>> insert 2nd event
>> delay 1 minute ^ (3 + 1 = 4)
>> insert 3rd event
>> delay 1 minute ^ (2 + 1 = 3)
>> delay 2 minutes ^
>> fire all rules
>>
>> However, if I start from the 1st event, the possibility where 1st event
>> lies
>> out of time frame of 5 mins would be if certain amount of time is
>> consumed while inserting the 1st event. I tried to check it
>> programmatically
>> to see if there is any time lapsed during the insertion of the event by
>> printing the clock's current time using clock.getCurrentTime() method
>> before
>> and after inserting the 1st event, however, could not notice any
>> difference.
>>
>> But, if I change the time to be advanced by 1 minutes and 59 seconds
>> (instead of 2 minutes) towards the end after the three events have been
>> inserted, the rule seems to be working fine by considering all the three
>> events for calculating the average.
>>
>> I know I am definitely missing out something here as I can see the
>> difference in the behavior of the rule by merely reducing the total delay
>> in
>> time by 1 second (4 min 59 sec instead of 5 minutes) as stated above. But
>> I
>> am not able to figure that out.
>>
>> Could you please provide more insight.
>>
>> Thanks!
>>
>>
>> On Wednesday, 4 June 2014 9:01 PM, Wolfgang Laun <wolfgang.laun(a)gmail.com>
>> wrote:
>>
>>
>>
>> Your code does:
>> insert 1st event
>> delay 1 minute
>> insert 2nd event
>> delay 1 minute
>> insert 3rd event
>> delay 1 minute
>> delay (1 or) 2 minutes
>> fire all rules
>>
>> In the second case, 5 minutes have elapsed since the 1st insert. I
>> don't think that this means "that [the 1st insert] falls well within
>> the specified time range" - it is exactly at the beginning of the
>> window, and I'd expect the window to be an interval open at one end -
>> otherwise events smack on the point in time "separating" two intervals
>> would be in both windows.
>>
>> -W
>>
>>
>> On 04/06/2014, Sushant Goyal <sushantgoyal25(a)yahoo.co.in> wrote:
>>> Hi,
>>>
>>> I am
>>> trying to understand how Drools can be used to monitor events over a
>>> period
>>> of
>>> time using Sliding Time Windows. I have created a rule to sound an alarm
>>> when
>>> average temperature read from a sensor is above 25 degrees (threshold)
>>> over
>>> a
>>> time period of 5 minutes. The rule makes of use of the Stream processing
>>> mode so
>>> that continuous stream of events could be processed.
>>>
>>> Below
>>> is how my rule looks like:
>>>
>>> //declare any global
>>> variables here
>>> globaljava.lang.StringBuilder alertMessage
>>>
>>> // add declaration to
>>> change the Fact into an Event
>>> declareSensorReading
>>> @role(event)
>>> end
>>>
>>> /* Alert when average
>>> temperature is above 25
>>> over a time period of 5 minutes */
>>> rule"TemperatureAlarm1"
>>>
>>> when
>>> //conditions
>>> $averageTemp : Number(doubleValue >
>>> 25.00)
>>> fromaccumulate(SensorReading($temp
>>> : temperature)
>>> over
>>> window:time(5m) fromentry-point "Temperature Reading", average($temp))
>>> then
>>> //actions
>>> System.out.println("Fired rule:
>>> "+
>>> kcontext.getRule().getName());
>>> alertMessage.append("Threshold
>>> temperature breached!!"+
>>> "\nTurn on the
>>> Air Conditioner"+
>>> "\nAverage
>>> temperature over 5 minutes is above 25 ("+ $averageTemp.intValue() +
>>> ")\n");
>>>
>>> end
>>>
>>> And below
>>> is the snapshot of the fact (SensorReading) which is inserted as an event
>>> in
>>> the working memory:
>>>
>>> publicclassSensorReading {
>>>
>>> privatedoubletemperature;
>>>
>>> publicSensorReading(){}
>>>
>>> publicSensorReading(doubletemp){
>>> this.temperature= temp;
>>> }
>>>
>>> // getters and setters
>>> }
>>>
>>>
>>> In
>>> order to test the rule, I am using Pseudo Clock with Stream processing
>>> turned
>>> on. I am inserting three SensorReading objects in the working memory with
>>> temperature
>>> values as (24, 26, 28) after every minute, so that the average of the
>>> temperatures is above threshold and the rule is invoked. After the
>>> objects
>>> are
>>> inserted in the working memory, I am deliberately advancing the Pseudo
>>> clock
>>> by
>>> another 1 minute, so that the total time elapsed is 4 minutes. The rule
>>> works
>>> as expected with the above test setup and prints the average value as 26
>>> on
>>> the
>>> console.
>>>
>>> However,
>>> if I advance the clock by 2 minutes instead of 1 minute after three
>>> sensor
>>> reading objects have been inserted in the working memory (after every 1
>>> minute
>>> interval), the rule gets invoked but the average value gets changed to 27
>>> (26 +
>>> 28 / 2 == 27). Looks like the first temperature reading is getting
>>> ignored
>>> by
>>> the rule despite the fact that it falls well within the specified time
>>> range
>>> of
>>> 5 minutes. Below is the snapshot of my test class:
>>>
>>> publicclassTemperatureAlarmTest
>>> {
>>>
>>> staticKnowledgeBase kbase;
>>> staticStatefulKnowledgeSession ksession;
>>> staticKnowledgeRuntimeLogger logger;
>>> staticSessionPseudoClock clock;
>>>
>>> @BeforeClass
>>> publicstaticvoidsetupKsession() {
>>> try{
>>> // load up the
>>> knowledge base
>>> kbase= readKnowledgeBase();
>>> ksession= readKnowldedeSession(kbase);
>>> clock= ksession.getSessionClock();
>>>
>>> logger=
>>> KnowledgeRuntimeLoggerFactory.newThreadedFileLogger(ksession,
>>> "log/Errors",
>>> 500);
>>>
>>> } catch(Throwable t) {
>>> t.printStackTrace();
>>> }
>>> }
>>>
>>> /**
>>> *
>>> Create a new Stateful knowledge Session with a pseudo clock from the
>>> *
>>> knowledge base
>>> *
>>> * @paramkbase
>>> * @return
>>> * @throwsException
>>> */
>>> privatestaticStatefulKnowledgeSession readKnowldedeSession(
>>> KnowledgeBase kbase) throwsException {
>>>
>>> // Knowledge Session Configuration
>>> KnowledgeSessionConfiguration
>>> config = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
>>> config.setOption(ClockTypeOption.get("pseudo"));
>>> returnkbase.newStatefulKnowledgeSession(config, null);
>>>
>>> }
>>>
>>> @AfterClass
>>> publicstaticvoidcloseKsession() {
>>> try{
>>> // load up the
>>> knowledge base
>>> logger.close();
>>> ksession.dispose();
>>>
>>> } catch(Throwable t) {
>>> t.printStackTrace();
>>> }
>>> }
>>>
>>> @Test
>>> publicvoidTemperatureAlarm1_Test() {
>>>
>>> // Create Temperature list
>>> ArrayList<SensorReading>
>>> tempMetrics = newArrayList<SensorReading>();
>>> doubletemp = 24.00;
>>>
>>> while(tempMetrics.size()
>>> < 3) {
>>> tempMetrics.add(newSensorReading(temp));
>>> temp += 2;
>>> }
>>> System.out.println("Size of
>>> tempMetrics List: "+tempMetrics.size()+"\n");
>>> System.out.println("First Temp
>>> reading: "+tempMetrics.get(0).getTemperature());
>>> System.out.println("Second Temp
>>> reading: "+tempMetrics.get(1).getTemperature());
>>> System.out.println("Third Temp
>>> reading: "+tempMetrics.get(2).getTemperature()+"\n");
>>>
>>> // Separate stream for inserts
>>> WorkingMemoryEntryPoint
>>> temperatureStream = ksession.getWorkingMemoryEntryPoint( "Temperature
>>> Reading");
>>>
>>> // Create fact handle list
>>> ArrayList<FactHandle>
>>> factHandleList = newArrayList<FactHandle>();
>>>
>>> // Insert objects into working
>>> memory while advancing the clock
>>> for(inti = 0; i <
>>> tempMetrics.size(); i++) {
>>>
>>> factHandleList.add(temperatureStream.insert(tempMetrics.get(i)));
>>> clock.advanceTime(1,
>>> TimeUnit.MINUTES);
>>> System.out.println("Time advances
>>> by 1 minute");
>>> }
>>> System.out.println("Fact Count
>>> is: "+temperatureStream.getFactCount());
>>> System.out.println("Fact Entry
>>> Point is: "+temperatureStream.getEntryPointId());
>>> System.out.println("Size of
>>> FactHandleList: "+factHandleList.size()+"\n");
>>>
>>> clock.advanceTime(1,
>>> TimeUnit.MINUTES); //change in
>>> advanced time alters the rule behavior
>>>
>>> StringBuilder stringBuilder = newStringBuilder();
>>> ksession.setGlobal("alertMessage", stringBuilder);
>>> ksession.fireAllRules();
>>>
>>> // Remove facts
>>> for(inti = 0; i <
>>> factHandleList.size(); i++) {
>>> temperatureStream.retract(factHandleList.get(i));
>>> }
>>> System.out.println("After
>>> Removing facts");
>>> System.out.println("Fact Count
>>> is: "+temperatureStream.getFactCount());
>>>
>>> String result =
>>> stringBuilder.substring(0, 32);
>>> System.out.println("Alert Message
>>> is: \n"+ stringBuilder.toString());
>>> assertEquals("Alert Message
>>> is: ", "Threshold
>>> temperature breached!!", result);
>>> }
>>>
>>> /**
>>> *
>>> Create the knowledge base with stream processing turned on.
>>> *
>>> * @return
>>> * @throwsException
>>> */
>>> privatestaticKnowledgeBase
>>> readKnowledgeBase() throwsException {
>>> KnowledgeBuilder kbuilder =
>>> KnowledgeBuilderFactory.newKnowledgeBuilder();
>>>
>>> kbuilder.add(ResourceFactory.newClassPathResource("TemperatureAlarm1.drl"),ResourceType.DRL);
>>> hasErrors(kbuilder);
>>>
>>> // Stream processing turned on
>>> KnowledgeBaseConfiguration conf =
>>> KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
>>> conf.setOption(EventProcessingOption.STREAM);
>>> KnowledgeBase kbase =
>>> KnowledgeBaseFactory.newKnowledgeBase(conf);
>>> hasErrors(kbuilder);
>>>
>>> kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
>>>
>>> returnkbase;
>>> }
>>>
>>> /**
>>> *
>>> Report errors if any
>>> *
>>> * @paramkbuilder
>>> * @throwsException
>>> */
>>> privatestaticvoidhasErrors(KnowledgeBuilder kbuilder)
>>> throwsException
>>> {
>>> KnowledgeBuilderErrors errors =
>>> kbuilder.getErrors();
>>> if(errors.size() > 0) {
>>> for(KnowledgeBuilderError error : errors) {
>>> System.err.println(error);
>>> }
>>> thrownewIllegalArgumentException("Could not parse
>>> knowledge.");
>>> }
>>>
>>> }
>>>
>>> }
>>>
>>>
>>> Could
>>> anyone please help explain this change in the behavior of the rule?
>>>
>>> Regards,
>>> Sushant
10 years, 5 months
6.1.0.beta4 and identified a rule pattern inducing memory leaks
by Matteo Mortari
Ciao, I'm using 6.1.0.beta4 and I identified in my application a rule
pattern inducing memory leaks. I try to attach rule, screenshots,
and javacode to replicate the issue.
IF the rule "After No data received within the last 1 hour Error, now
resumed" is included, memory leaks happens, and pretty quickly.
IF such rule is commented out, application do manage to keep alive.
[>] Question kindly is: is this normal on 6.1.0.beta4, or shall I go ahead
and raise a JIRA for this, please?
This time I ask in the mailinglist first, just because last time I
experienced a similar issue and raised JIRA, but in fact at the end was
just another way to replicate a known issue.
Thank you in advance
Ciao,
MM
*package* com.acme.drools6test.anotherleak;
*import* com.acme.objectmodel.*
// we take time is insertion time of SensorReading
*declare* SensorReading
@role(event)
*end*
*declare* Alert
@role(event)
*end*
*declare* AlertErrorToken
@role(event)
@timestamp(ts)
ts : *long*
*end*
*declare* AMap
@role(fact)
map : java.util.HashMap
*end*
*query* "AMap"
$AMap : AMap()
*end*
*query* "Alerts"
$alert : Alert()
*end*
*query* "All"
$o : Object()
*end*
*rule* "init AMap"
*no-loop*
*when*
*not* ( AMap() )
*then*
AMap t = *new* AMap();
t.setMap( *new* java.util.HashMap() );
*insert*( t );
*end*
*rule* "to display a kind of single table that list most recent value"
*no-loop*
*when*
$sr : SensorReading($id : header.id , $value : value)
AMap($map : map)
*then*
$map.put($id, $value);
*end*
*rule* "No data received within the last 1 minutes Warning"
*no-loop*
*when*
$sr : SensorReading()
*not*( SensorReading( *this* != $sr, *this* after[0,1m] $sr ) )
*not*( Alert( sr == $sr, type == AlertType.WARNING ) )
*then*
Alert alert = *new*
Alert(kcontext.getKieRuntime().getSessionClock().getCurrentTime(), "No data
received within the last 1 minutes", AlertType.WARNING, $sr);
*insert*(alert);
System.out.println("1 minutes Warning insert " + alert);
// send WARNING notification
*end*
*rule* "No data received within the last 1 hour Error"
*no-loop*
*when*
$sr : SensorReading()
*not*( SensorReading( *this* != $sr, *this* after[0,1h] $sr ) )
*not*( Alert( sr == $sr, type == AlertType.ERROR ) )
*then*
*long* errTs =
kcontext.getKieRuntime().getSessionClock().getCurrentTime();
Alert alert = *new* Alert(errTs, "No data received within the last 1
hour", AlertType.ERROR, $sr);
*insert*(alert);
AlertErrorToken errToken = *new* AlertErrorToken();
errToken.setTs(errTs);
*insert*(errToken);
System.out.println("last 1 hour Error insert " + alert);
// send ERROR notification
*end*
*rule* "After No data received within the last 1 hour Error, now resumed"
*no-loop*
*when*
$errToken : AlertErrorToken()
$errAlert : Alert(*this* coincides $errToken)
SensorReading( *this* after $errToken )
*then*
*retract*($errToken);
System.out.println("now resumed retract " + $errToken);
// send INFO resume notification
*end*
*rule* "Housekeep rule"
*salience* -1000
*no-loop*
*dialect* "mvel"
*when*
$last : SensorReading( ) over window:length( 1 )
$earlier : SensorReading( *this* before $last, *this* != $last )
*then*
*retract*($earlier);
System.out.println("Housekeep : "+$earlier);
*end*
10 years, 5 months
Re: [rules-users] Monitoring applications using Drools
by Sushant Goyal
I found one of the explanations on how Sliding Windows
operate in Drools while searching for an answer:
“Events are expired
from the time window when the clock advances”
So, in my case if I am inserting events on T0 (insert 1st event), T1 (insert 2nd event), T2 (insert 3rd event) and
advancing the clock to T3, T4 and T5; 1st event inserted at T0 is
expired from the window. And the rule calculates the average of the last two
events (2nd event & 3rd event) falling in the time
window. And the output average calculated by the from accumulate function comes
to be (26 +28 / 2 == 27) satisfying the contract of average temperature to be above
the threshold value of 25.
Now let’s say I do the below (advancing the clock by 5
minutes after the 3rd insert):
T0 (insert 1st event)
T1 (insert 2st event)
T2 (insert 3st event)
T3
T4
T5
T6
T7
Fire all rules
The average calculated by the rule is zero (0) since the
three inserted events fall outside the time window of 5 minutes (as expected).
But, my rule fires regardless of the fact I have the contract of average temperature
to be greater than threshold in my rule :
$averageTemp : Number(intValue
> 25)
from accumulate(SensorReading($temp : temperature)
over window:time(5m) from
entry-point "Temperature Reading", average($temp))
As per the drools-fusion documentation, over window : time(X) is used to consider events that happened in
the last X units. So, is there something that needs to be changed in my rule
implementation?
One more question here, does over window : time(X) really considers events occurred in the last
X units. I tried going further by doing the below:
T0 (insert 1st event – Sensor reading is 24)
T1 (insert 2st event – Sensor reading is 26)
T2 (insert 3st event – Sensor reading is 28)
T3
T4
T5
T6
T7
(insert event – Sensor reading is 30)
Fire All rules
With the above test setup, my rule gets invoked twice printing
the average of temperatures as (30) and (30). But using over window:time(5m) shouldn’t result in rule being triggered once ?
Thanks in advance!
On Thursday, 5 June 2014 1:35 PM, Sushant Goyal <sushantgoyal25(a)yahoo.co.in> wrote:
Thanks again for your response Wolfgang.
I found one of the explanations on how Sliding Windows
operate in Drools while searching for an answer:
“Events are expired
from the time window when the clock advances”
So, in my case if I am inserting events on T0 (insert 1st event), T1 (insert 2nd event), T2 (insert 3rd event) and
advancing the clock to T3, T4 and T5; 1st event inserted at T0 is
expired from the window. And the rule calculates the average of the last two
events (2nd event & 3rd event) falling in the time
window. And the output average calculated by the from accumulate function comes
to be (26 +28 / 2 == 27) satisfying the contract of average temperature to be above
the threshold value of 25.
Now let’s say I do the below (advancing the clock by 5
minutes after the 3rd insert):
T0 (insert 1st event)
T1 (insert 2st event)
T2 (insert 3st event)
T3
T4
T5
T6
T7
Fire all rules
The average calculated by the rule is zero (0) since the
three inserted events fall outside the time window of 5 minutes (as expected).
But, my rule fires regardless of the fact I have the contract of average temperature
to be greater than threshold in my rule :
$averageTemp : Number(intValue
> 25)
from accumulate(SensorReading($temp : temperature)
over window:time(5m) from
entry-point "Temperature Reading", average($temp))
As per the drools-fusion documentation, over window : time(X) is used to consider events that happened in
the last X units. So, is there something that needs to be changed in my rule
implementation?
One more question here, does over window : time(X) really considers events occurred in the last
X units. I tried going further by doing the below:
T0 (insert 1st event – Sensor reading is 24)
T1 (insert 2st event – Sensor reading is 26)
T2 (insert 3st event – Sensor reading is 28)
T3
T4
T5
T6
T7
(insert event – Sensor reading is 30)
Fire All rules
With the above test setup, my rule gets invoked twice printing
the average of temperatures as (30) and (30). But using over window:time(5m) shouldn’t result in rule being triggered once ?
Thanks in advance!
On Thursday, 5 June 2014 12:31 PM, Wolfgang Laun <wolfgang.laun(a)gmail.com> wrote:
Computations involving intervals where events arrive in real time
should not depend on differences of one unit of the smalles unit of
time for specifying durations (here: milliseconds).
-W
On 04/06/2014, Sushant Goyal <sushantgoyal25(a)yahoo.co.in> wrote:
> Thanks for your response.
> I was under the assumption that the window time frame begins, the moment
> first event is inserted into the working memory. Or I am still missing out
> something here (when you say that the first event is exactly at the
> beginning of the window)? If I traverse backwards as below, then definitely
> the 1st event lies outside the
window.
>
> insert 1st event
> delay 1 minute ^ (4 + 1 = 5)
> insert 2nd event
> delay 1 minute ^ (3 + 1 = 4)
> insert 3rd event
> delay 1 minute ^ (2 + 1 = 3)
> delay 2 minutes ^
> fire all rules
>
> However, if I start from the 1st event, the possibility where 1st event lies
> out of time frame of 5 mins would be if certain amount of time is
> consumed while inserting the 1st event. I tried to check
it programmatically
> to see if there is any time lapsed during the insertion of the event by
> printing the clock's current time using clock.getCurrentTime() method before
> and after inserting the 1st event, however, could not notice any difference.
>
> But, if I change the time to be advanced by 1 minutes and 59 seconds
> (instead of 2 minutes) towards the end after the three events have been
> inserted, the rule seems to be working fine by considering all the three
> events for calculating the average.
>
> I know I am definitely missing out something here as I can see the
> difference in the behavior of the rule by merely reducing the total delay in
> time by 1 second (4 min 59 sec instead of 5 minutes) as stated above. But I
> am not able to figure that out.
>
> Could you please provide more insight.
>
> Thanks!
>
>
> On Wednesday, 4 June 2014 9:01 PM, Wolfgang Laun <wolfgang.laun(a)gmail.com>
> wrote:
>
>
>
> Your code does:
> insert 1st event
> delay 1 minute
> insert 2nd event
> delay 1 minute
> insert 3rd event
> delay 1 minute
> delay (1 or) 2 minutes
> fire all rules
>
> In the second case, 5 minutes have elapsed since the 1st insert. I
> don't think that this means "that [the 1st insert] falls well within
> the specified time range" - it is exactly at the beginning of the
>
window, and I'd expect the window to be an interval open at one end -
> otherwise events smack on the point in time "separating" two intervals
> would be in both windows.
>
> -W
>
>
> On 04/06/2014, Sushant Goyal <sushantgoyal25(a)yahoo.co.in> wrote:
>> Hi,
>>
>> I am
>> trying to understand how Drools can be used to monitor events over a
>> period
>> of
>> time using Sliding Time Windows. I have created a rule to sound an alarm
>> when
>> average temperature read from a sensor is above 25 degrees (threshold)
>> over
>> a
>> time period of 5 minutes. The rule makes of use of the Stream processing
>> mode so
>> that continuous stream of events could be processed.
>>
>> Below
>> is how my rule looks like:
>>
>> //declare any global
>>
variables here
>> globaljava.lang.StringBuilder alertMessage
>>
>> // add declaration to
>> change the Fact into an Event
>> declareSensorReading
>> @role(event)
>> end
>>
>> /* Alert when average
>> temperature is above 25
>> over a time period of 5 minutes */
>> rule"TemperatureAlarm1"
>>
>> when
>>
//conditions
>> $averageTemp : Number(doubleValue >
>> 25.00)
>> fromaccumulate(SensorReading($temp
>> : temperature)
>> over
>> window:time(5m) fromentry-point "Temperature Reading", average($temp))
>> then
>> //actions
>> System.out.println("Fired rule:
>> "+
>> kcontext.getRule().getName());
>> alertMessage.append("Threshold
>> temperature breached!!"+
>> "\nTurn on the
>> Air Conditioner"+
>> "\nAverage
>> temperature over 5 minutes is above 25 ("+ $averageTemp.intValue() +
>> ")\n");
>>
>> end
>>
>> And below
>> is the snapshot of the fact (SensorReading) which is inserted as an event
>> in
>> the working memory:
>>
>> publicclassSensorReading {
>>
>> privatedoubletemperature;
>>
>> publicSensorReading(){}
>>
>> publicSensorReading(doubletemp){
>> this.temperature= temp;
>>
}
>>
>> // getters and setters
>> }
>>
>>
>> In
>> order to test the rule, I am using Pseudo Clock with Stream processing
>> turned
>> on. I am inserting three SensorReading objects in the working memory with
>> temperature
>> values as (24, 26, 28) after every minute, so that the average of the
>> temperatures is above threshold and the rule is invoked. After the objects
>> are
>> inserted in the working memory, I am deliberately advancing the Pseudo
>> clock
>> by
>> another 1 minute, so that the total time elapsed is 4 minutes. The rule
>> works
>> as expected with the above test setup and prints the average value as 26
>> on
>> the
>> console.
>>
>> However,
>> if I advance the clock by 2 minutes instead of 1 minute after three sensor
>> reading objects have been inserted in the working memory (after every 1
>> minute
>> interval), the rule gets invoked but the average value gets changed to 27
>> (26 +
>> 28 / 2 == 27). Looks like the first temperature reading is getting ignored
>> by
>> the rule despite the fact that it falls well within the specified time
>> range
>> of
>> 5 minutes. Below is the snapshot of my test class:
>>
>> publicclassTemperatureAlarmTest
>> {
>>
>> staticKnowledgeBase
kbase;
>> staticStatefulKnowledgeSession ksession;
>> staticKnowledgeRuntimeLogger logger;
>> staticSessionPseudoClock clock;
>>
>> @BeforeClass
>> publicstaticvoidsetupKsession() {
>> try{
>> // load up the
>> knowledge base
>>
kbase= readKnowledgeBase();
>> ksession= readKnowldedeSession(kbase);
>> clock= ksession.getSessionClock();
>>
>> logger=
>> KnowledgeRuntimeLoggerFactory.newThreadedFileLogger(ksession,
>> "log/Errors",
>> 500);
>>
>> } catch(Throwable t) {
>>
t.printStackTrace();
>> }
>> }
>>
>> /**
>> *
>> Create a new Stateful knowledge Session with a pseudo clock from the
>> *
>> knowledge base
>> *
>> * @paramkbase
>> * @return
>> *
@throwsException
>> */
>> privatestaticStatefulKnowledgeSession readKnowldedeSession(
>> KnowledgeBase kbase) throwsException {
>>
>> // Knowledge Session Configuration
>> KnowledgeSessionConfiguration
>> config = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
>> config.setOption(ClockTypeOption.get("pseudo"));
>> returnkbase.newStatefulKnowledgeSession(config, null);
>>
>> }
>>
>> @AfterClass
>> publicstaticvoidcloseKsession() {
>> try{
>> // load up the
>> knowledge base
>> logger.close();
>>
ksession.dispose();
>>
>> } catch(Throwable t) {
>> t.printStackTrace();
>> }
>> }
>>
>> @Test
>> publicvoidTemperatureAlarm1_Test() {
>>
>> // Create Temperature list
>>
ArrayList<SensorReading>
>> tempMetrics = newArrayList<SensorReading>();
>> doubletemp = 24.00;
>>
>> while(tempMetrics.size()
>> < 3) {
>> tempMetrics.add(newSensorReading(temp));
>> temp += 2;
>> }
>>
System.out.println("Size of
>> tempMetrics List: "+tempMetrics.size()+"\n");
>> System.out.println("First Temp
>> reading: "+tempMetrics.get(0).getTemperature());
>> System.out.println("Second Temp
>> reading: "+tempMetrics.get(1).getTemperature());
>> System.out.println("Third Temp
>> reading: "+tempMetrics.get(2).getTemperature()+"\n");
>>
>> // Separate stream for inserts
>> WorkingMemoryEntryPoint
>> temperatureStream = ksession.getWorkingMemoryEntryPoint( "Temperature
>> Reading");
>>
>> // Create fact handle list
>> ArrayList<FactHandle>
>> factHandleList = newArrayList<FactHandle>();
>>
>> // Insert objects into working
>> memory while advancing the clock
>>
for(inti = 0; i <
>> tempMetrics.size(); i++) {
>>
>> factHandleList.add(temperatureStream.insert(tempMetrics.get(i)));
>> clock.advanceTime(1,
>> TimeUnit.MINUTES);
>> System.out.println("Time advances
>> by 1 minute");
>> }
>> System.out.println("Fact Count
>> is: "+temperatureStream.getFactCount());
>> System.out.println("Fact Entry
>> Point is: "+temperatureStream.getEntryPointId());
>> System.out.println("Size of
>> FactHandleList: "+factHandleList.size()+"\n");
>>
>> clock.advanceTime(1,
>> TimeUnit.MINUTES); //change in
>> advanced time alters the rule behavior
>>
>> StringBuilder stringBuilder = newStringBuilder();
>> ksession.setGlobal("alertMessage", stringBuilder);
>> ksession.fireAllRules();
>>
>> // Remove facts
>> for(inti = 0; i <
>> factHandleList.size(); i++) {
>> temperatureStream.retract(factHandleList.get(i));
>> }
>> System.out.println("After
>> Removing facts");
>> System.out.println("Fact Count
>> is: "+temperatureStream.getFactCount());
>>
>> String result =
>> stringBuilder.substring(0, 32);
>> System.out.println("Alert Message
>> is: \n"+ stringBuilder.toString());
>> assertEquals("Alert Message
>> is: ", "Threshold
>> temperature breached!!", result);
>> }
>>
>> /**
>> *
>> Create the knowledge base with stream processing turned on.
>> *
>> * @return
>> * @throwsException
>> */
>> privatestaticKnowledgeBase
>> readKnowledgeBase() throwsException {
>> KnowledgeBuilder
kbuilder =
>> KnowledgeBuilderFactory.newKnowledgeBuilder();
>>
>> kbuilder.add(ResourceFactory.newClassPathResource("TemperatureAlarm1.drl"),ResourceType.DRL);
>> hasErrors(kbuilder);
>>
>> // Stream processing turned on
>> KnowledgeBaseConfiguration conf =
>> KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
>> conf.setOption(EventProcessingOption.STREAM);
>> KnowledgeBase kbase =
>> KnowledgeBaseFactory.newKnowledgeBase(conf);
>> hasErrors(kbuilder);
>> kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
>>
>> returnkbase;
>> }
>>
>> /**
>> *
>> Report errors if any
>>
*
>> * @paramkbuilder
>> * @throwsException
>> */
>> privatestaticvoidhasErrors(KnowledgeBuilder kbuilder)
>> throwsException
>> {
>> KnowledgeBuilderErrors errors =
>> kbuilder.getErrors();
>> if(errors.size() > 0) {
>> for(KnowledgeBuilderError error :
errors) {
>> System.err.println(error);
>> }
>> thrownewIllegalArgumentException("Could not parse
>> knowledge.");
>> }
>>
>> }
>>
>> }
>>
>>
>> Could
>> anyone please help explain this change in the behavior of the rule?
>>
>> Regards,
>> Sushant
10 years, 5 months
Monitoring applications using Drools
by Sushant Goyal
Hi,
I am
trying to understand how Drools can be used to monitor events over a period of
time using Sliding Time Windows. I have created a rule to sound an alarm when
average temperature read from a sensor is above 25 degrees (threshold) over a
time period of 5 minutes. The rule makes of use of the Stream processing mode so
that continuous stream of events could be processed.
Below
is how my rule looks like:
//declare any global
variables here
globaljava.lang.StringBuilder alertMessage
// add declaration to
change the Fact into an Event
declareSensorReading
@role(event)
end
/* Alert when average
temperature is above 25
over a time period of 5 minutes */
rule"TemperatureAlarm1"
when
//conditions
$averageTemp : Number(doubleValue >
25.00)
fromaccumulate(SensorReading($temp
: temperature)
over
window:time(5m) fromentry-point "Temperature Reading", average($temp))
then
//actions
System.out.println("Fired rule:
"+
kcontext.getRule().getName());
alertMessage.append("Threshold
temperature breached!!"+
"\nTurn on the
Air Conditioner"+
"\nAverage
temperature over 5 minutes is above 25 ("+ $averageTemp.intValue() + ")\n");
end
And below
is the snapshot of the fact (SensorReading) which is inserted as an event in
the working memory:
publicclassSensorReading {
privatedoubletemperature;
publicSensorReading(){}
publicSensorReading(doubletemp){
this.temperature= temp;
}
// getters and setters
}
In
order to test the rule, I am using Pseudo Clock with Stream processing turned
on. I am inserting three SensorReading objects in the working memory with temperature
values as (24, 26, 28) after every minute, so that the average of the
temperatures is above threshold and the rule is invoked. After the objects are
inserted in the working memory, I am deliberately advancing the Pseudo clock by
another 1 minute, so that the total time elapsed is 4 minutes. The rule works
as expected with the above test setup and prints the average value as 26 on the
console.
However,
if I advance the clock by 2 minutes instead of 1 minute after three sensor
reading objects have been inserted in the working memory (after every 1 minute
interval), the rule gets invoked but the average value gets changed to 27 (26 +
28 / 2 == 27). Looks like the first temperature reading is getting ignored by
the rule despite the fact that it falls well within the specified time range of
5 minutes. Below is the snapshot of my test class:
publicclassTemperatureAlarmTest
{
staticKnowledgeBase kbase;
staticStatefulKnowledgeSession ksession;
staticKnowledgeRuntimeLogger logger;
staticSessionPseudoClock clock;
@BeforeClass
publicstaticvoidsetupKsession() {
try{
// load up the
knowledge base
kbase= readKnowledgeBase();
ksession= readKnowldedeSession(kbase);
clock= ksession.getSessionClock();
logger=
KnowledgeRuntimeLoggerFactory.newThreadedFileLogger(ksession, "log/Errors", 500);
} catch(Throwable t) {
t.printStackTrace();
}
}
/**
*
Create a new Stateful knowledge Session with a pseudo clock from the
*
knowledge base
*
* @paramkbase
* @return
* @throwsException
*/
privatestaticStatefulKnowledgeSession readKnowldedeSession(
KnowledgeBase kbase) throwsException {
// Knowledge Session Configuration
KnowledgeSessionConfiguration
config = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
config.setOption(ClockTypeOption.get("pseudo"));
returnkbase.newStatefulKnowledgeSession(config, null);
}
@AfterClass
publicstaticvoidcloseKsession() {
try{
// load up the
knowledge base
logger.close();
ksession.dispose();
} catch(Throwable t) {
t.printStackTrace();
}
}
@Test
publicvoidTemperatureAlarm1_Test() {
// Create Temperature list
ArrayList<SensorReading>
tempMetrics = newArrayList<SensorReading>();
doubletemp = 24.00;
while(tempMetrics.size()
< 3) {
tempMetrics.add(newSensorReading(temp));
temp += 2;
}
System.out.println("Size of
tempMetrics List: "+tempMetrics.size()+"\n");
System.out.println("First Temp
reading: "+tempMetrics.get(0).getTemperature());
System.out.println("Second Temp
reading: "+tempMetrics.get(1).getTemperature());
System.out.println("Third Temp
reading: "+tempMetrics.get(2).getTemperature()+"\n");
// Separate stream for inserts
WorkingMemoryEntryPoint
temperatureStream = ksession.getWorkingMemoryEntryPoint( "Temperature
Reading");
// Create fact handle list
ArrayList<FactHandle>
factHandleList = newArrayList<FactHandle>();
// Insert objects into working
memory while advancing the clock
for(inti = 0; i <
tempMetrics.size(); i++) {
factHandleList.add(temperatureStream.insert(tempMetrics.get(i)));
clock.advanceTime(1,
TimeUnit.MINUTES);
System.out.println("Time advances
by 1 minute");
}
System.out.println("Fact Count
is: "+temperatureStream.getFactCount());
System.out.println("Fact Entry
Point is: "+temperatureStream.getEntryPointId());
System.out.println("Size of
FactHandleList: "+factHandleList.size()+"\n");
clock.advanceTime(1,
TimeUnit.MINUTES); //change in
advanced time alters the rule behavior
StringBuilder stringBuilder = newStringBuilder();
ksession.setGlobal("alertMessage", stringBuilder);
ksession.fireAllRules();
// Remove facts
for(inti = 0; i <
factHandleList.size(); i++) {
temperatureStream.retract(factHandleList.get(i));
}
System.out.println("After
Removing facts");
System.out.println("Fact Count
is: "+temperatureStream.getFactCount());
String result =
stringBuilder.substring(0, 32);
System.out.println("Alert Message
is: \n"+ stringBuilder.toString());
assertEquals("Alert Message
is: ", "Threshold
temperature breached!!", result);
}
/**
*
Create the knowledge base with stream processing turned on.
*
* @return
* @throwsException
*/
privatestaticKnowledgeBase
readKnowledgeBase() throwsException {
KnowledgeBuilder kbuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("TemperatureAlarm1.drl"),ResourceType.DRL);
hasErrors(kbuilder);
// Stream processing turned on
KnowledgeBaseConfiguration conf =
KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
conf.setOption(EventProcessingOption.STREAM);
KnowledgeBase kbase =
KnowledgeBaseFactory.newKnowledgeBase(conf);
hasErrors(kbuilder);
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
returnkbase;
}
/**
*
Report errors if any
*
* @paramkbuilder
* @throwsException
*/
privatestaticvoidhasErrors(KnowledgeBuilder kbuilder) throwsException {
KnowledgeBuilderErrors errors =
kbuilder.getErrors();
if(errors.size() > 0) {
for(KnowledgeBuilderError error : errors) {
System.err.println(error);
}
thrownewIllegalArgumentException("Could not parse knowledge.");
}
}
}
Could
anyone please help explain this change in the behavior of the rule?
Regards,
Sushant
10 years, 5 months
Help write rule drools
by nill
My structure is composed of 2 classes (Node, Link)
class Node {
List <Link> out;
List <Link> in;
}
class Link {
Source node;
Target node;
}
they are inserted as facts in working memory.
I have to write a rule that will unite for each node joins the links that
have the same destination, and if there is then the inverse must also join
the latter.
eg.
A - link1 -> B
A - link2 -> B
A - link3 -> C
C - link4 -> D
B - link5 -> A
result
A - link1 + link2 +link5 -> B
A - link3 -> C
C - link4 -> D
Can anyone help me?
--
View this message in context: http://drools.46999.n3.nabble.com/Help-write-rule-drools-tp4029841.html
Sent from the Drools: User forum mailing list archive at Nabble.com.
10 years, 5 months
Fuse ESB & Drools 6 problem
by s b
I'm testing the drools new version (6.1.0.Beta4) but I have a problem with
the Stateful Drools Session.
I have deployed in JBoss Fuse ESB the last versión of the drools (drools
camel, jbpm, spring, etc), I have atached my camel context bundle (It's a
maven project).
This is my camel-context
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:kie="http://drools.org/schema/kie-spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://drools.org/schema/kie-spring
http://drools.org/schema/kie-spring.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<kie:kmodule id="kModule">
<kie:kbase name="rules" packages="rules">
<kie:ksession name="ksession1" type="stateful">
<!--<kie:batch>
<kie:fire-all-rules/>
</kie:batch> -->
<kie:configuration>
<kie:jpa-persistence>
<kie:transaction-manager ref="txManager"/>
<kie:entity-manager-factory ref="myEmf"/>
</kie:jpa-persistence>
</kie:configuration>
</kie:ksession>
</kie:kbase>
</kie:kmodule>
<kie:environment id="env">
<kie:entity-manager-factory ref="myEmf"/>
<kie:transaction-manager ref="txManager"/>
</kie:environment>
<bean class="org.postgresql.ds.PGPoolingDataSource" id="jbpm-ds">
<property name="serverName" value="localhost"></property>
<property name="databaseName" value="drools"></property>
<property name="portNumber" value="5432"></property>
<property name="user" value="DWP"></property>
<property name="password" value="DWP"></property>
</bean>
<bean id="myEmf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="jbpm-ds"/>
<property name="persistenceUnitName"
value="org.jbpm.persistence.jpa.local"/>
</bean>
<bean id="txManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf"/>
</bean>
<bean id="kiePostProcessor"
class="org.drools.osgi.spring.OsgiKModuleBeanFactoryPostProcessor"/>
<bean id="fireALlRulesCommand"
class="com.execute.command.FireAllRules"/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route trace="false" id="testRoute">
<from uri="timer:testRoute?period=10s"/>
<to uri="log:message"/>
<to uri="kie:ksession1?action=insertBody" id="AgeVerification"/>
<bean method="fireAllRules" ref="fireALlRulesCommand"/>
<to uri="kie:ksession1?action=execute"/>
</route>
</camelContext>
</beans>
As you can see it is an scenario where Drools is in an stateful session
with persistence configured.
The bundle is executed without errors but I want that Drools executes my
rules each time that the route is executed ( fireUntilHalt mode but I
wasn't able as seems that this command is not availble in a persisted
environment ), for this reason I've created a bean with the command:
fireAllRules and I use <to uri="kie:ksession1?action=execute"/> to execute
the rules but the problem is that the rules are only executed the first
time, only the first time and never in subsequents executions of the route.
The persistece seems to work well ( I can see the datamodel created and
populated as expeted in the DB ).
However if I change to use stateless mode ( no persistence then ), the
rules are executed each time that route is executed ( as expected ), and
therefore I don´t need the command fireAllRules
<bean method="fireAllRules" ref="fireALlRulesCommand"/>
<to uri="kie:ksession1?action=execute"/>
Questions:
Is it possible to have a stateful fireUntilHalt drools session that keeps
using the same knowledge session in subsequent camel route executions?
If it is not possible, Can I have a stateful ( persisted )drools session
and invoke "fireAllRules" whenever I make changes in the knowledge session
( new Facts are inserted )?
I've deep dived into the web looking for examples or documentation of this
scenario both in Spring and Blueprint. Does anyone of you have any pointers
to documentation on the matter?
Kind Regards,
10 years, 5 months
Grouping of rule and range check
by Chaturvedi Dewashish
Hi,
I have a requirement which is as
1. There are three rules lets say rule1, rule2 and rule3
2. rule1 says there is a person
Age < 40
Age >= 20
Then do something
3. rule2 says there is a person
Age < 60
Age >= 40
Then do something else
4. rule3 says there is a person
Age >= 60
Then do something new
Now I am feeding person object as whole as event based from other
application.
So the requirement in form of test cases is
1. Age = 22 - do something
2. Age = 25 - Nothing as rule1 is already triggered and "do something" done
3. Age = 42 - do something else
4. Age = 45 - Nothing as rule1 is already triggered and "do something else"
done
4. Age = 65 - do something new
5. Age = 68 - nothing
6. Age = 25 - do something
7. Age = 45 - do something else
Is there any way to do this using the guvnor UI?
Thanks and regards,
Chaturvedi Dewashish
Nirvana Solutions
10 years, 5 months
After numerous of different approaches I am looking for some help
by dBijkoo
I'm dealing with the problem and I am looking for some help. I thoroughly
studied the documentation and tried several different approaches myself but
can't seem to get it working the way i want it to work.
Let me start by describing the problem:
Observation has a duration which is a multiplication of 5 (minutes), besides
this it has one or more required disciplines (explained later).
ScheduleBlockPeriod is a period of 5 minutes which is connected to a
scheduleBlock
ScheduleBlock contains a list of disciplines which can be performed in this
block (there can be 1..* scheduleBlocks)
Explanation:
An observation has to be planned into one or more scheduleBlockPeriod(s)
since a observations duration can be bigger then a scheduleBlockPeriods
period. I checked out the VRP application and based my model on that.
The reason why scheduleBlockPeriod is chained has to do with the amount of
periods there are. I will write a custom move at some point which limits the
nextScheduleBlockperiod to only select a period which is from the same
ScheduleBlock and is right after the current one.
Below I added a classdiagram how i would want it to work:
<http://drools.46999.n3.nabble.com/file/n4029842/planning_class_diagram_2.png>
After I run a construction heuristic on the program implemented as described
in the classdiagram it tells me the solution is uninitialized, which is
obvious because it assigns 1 scheduleBlockPeriod to the Observation. Because
the duration of the observation is 5 minutes(the same as the duration of a
scheduleBlockPeriod).
This makes the chained variable nextScheduleBlockPeriod null, which it
should be since it is 1 scheduleBlockPeriod "long".
So basically im wondering if there is some sort of work around for this or
perhaps someone is able to tell me that I am totally modelling it the wrong
way.
--
View this message in context: http://drools.46999.n3.nabble.com/After-numerous-of-different-approaches-...
Sent from the Drools: User forum mailing list archive at Nabble.com.
10 years, 5 months