time for specifying durations
(here: milliseconds).
On 04/06/2014, Sushant Goyal <
sushantgoyal25@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@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@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