Creating a Monitor to Listen for Events

In this lesson, you will write an EPL program that monitors events coming into the correlator from a simulated event feed (the SensorTest.evt file). The correlator can understand these events because you created definitions for them in the SensorMonitorEvents.mon event definition file.

Your EPL program will instruct the correlator to monitor the Temperature events for a single sensor ID (“S001”). The correlator will check the data types of the incoming events to make sure that they match the data types provided in the event type definitions. Each time it detects a matching temperature event, the correlator will send information to the Eclipse console.

  1. Right-click on the monitors folder and Create new file SensorMonitor.mon.

  2. Open SensorMonitor.mon, the basic template of a monitor can be generated automatically by typing mon and selecting the auto-complete suggestion (generated by Apama Extension for Visual Studio Code). The generated content will be as following:

/**
 * This monitor is responsible for...
 */
monitor SensorMonitor {
    action onload() {
        log "Started monitor SensorMonitor.";
    }
}
Info
Every monitor must contain an onload() action. When a monitor is injected into the correlator, the correlator executes the monitor’s onload() action.

As the first rule for this monitor, you will write code that references the Temperature event type in the eventdefinitions/SensorMonitorEvents.mon file (that you defined as part of the “Defining Types of Events” lesson). Note that in the SensorTest.evt file, each Temperature and Pressure event is sent in on a specific channel. The monitor must first subscribe to that channel.

  1. Write the following code that uses the monitor.subscribe(“channel”) method to subscribe to the channel that the event data is sent into the correlator on:
action onload() {  
    // Subscribe to events.  
    monitor.subscribe("Factory1");
}
  1. Write the following code that listens for all Temperature events where the value of the sensor ID is “S001”:
monitor SensorMonitor {  
    action onload() {  
        // Subscribe to events.  
        monitor.subscribe("Factory1");  
        // Listen for all temperature events where ID = S001.
        on all Temperature (sensorId="S001"){ }
    }
}
  1. Save your changes.
Info
  • The monitor.subscribe method subscribes the context that the monitor is running in to the named channel. Without it, the correlator will not send events on that channel to the context and thus to the monitor. Subscribe to the channel on which data is sent in each monitor that listens for those events. The subscription is owned by the monitor, so when the monitor terminates, the subscription will end. Multiple subscriptions in a context are merged, so the existence of any subscription in a context will cause events to be sent to that context. This is particularly useful when using multiple contexts See Process Multiple Monitor Instances Simultaneously. Events on the default channel (which do not have a named channel in the evt file) are available to the main context and other public contexts.
  • In EPL, the on statement tells the correlator to create a listener, a construct that watches for specified events. The correlator observes the events, analyzing each event in turn until it finds a sequence of events that match the listener’s event expression. When this happens the listener triggers, causing the correlator to execute the listener action (defined in the next step). At this point, depending on the form of the event expression, the listener either terminates or continues listening for other matching event sequences.
  • The all keyword extends the on command to listen for all events that match the specified pattern. Without the all keyword, the listener would listen for only the first matching event. In this example, without the all keyword, the listener would terminate after it finds one Sensor ID S001 event.
    In EPL, an action is just a function that can be called. An action is similar to a method in other programming languages, such as Java and C++.
  1. For this listener’s action, add code that prints the text “Temperature received”.
monitor SensorMonitor {  
    action onload() {  
        // Subscribe to events.  
        monitor.subscribe("Factory1");  
        // Listen for all temperature events.  
        on all Temperature (sensorId="S001"){  
            // Print the temperature.  
            print "Temperature received.";
        }  
    }  
}  
  1. Save your changes.
Info
Whenever the correlator finds a Temperature event with a sensorId field that has a value of S001, it sends the text “Temperature Received”.

Testing the code.

Info
Before doing this follow steps mentioned in Getting started for Apama extension for Visual Studio Code
  1. Start correlator using : correlator -p 5000

  2. Right click on SensorMonitorEvents.mon and select correlator: engine inject
    (This should be in eventdefinitions folder see Defining Event Types)
    You should see:

Added type AddSensor
Added type Pressure
Added type Temperature
Injected MonitorScript from file /.../EPL_Fundamentals/eventdefinitions/SensorMonitorEvents.mon
  1. Right click on SensorMonitor.mon and select correlator: engine inject
    You should see:
Added monitor SensorMonitor
Injected MonitorScript from file /.../EPL_Fundamentals/monitors/SensorMonitor.mon
  1. Right click on SensorTest.mon and select correlator: engine send (This should be in events folder)
    You should see this text repeated 4 times: Temperature received.
Temperature received.
Temperature received.
Temperature received.
Temperature received.

EPL supports the ability to copy an event into a variable. This process is called coassignment. Follow these steps to coassign found Temperature events to a variable:

  1. Open the monitors/SensorMonitor.mon file.

  2. Use the as operator to coassign each Temperature event to a variable called temperature:

on all Temperature (sensorId="S001") as temperature {...}

This variable is only in scope in the processing block of the listener and has no effect on clashing local or global variables.

Info
If you wish to assign an incoming event to an already declared variable, you can do this by using the co-assignment operator : instead of the as operator.
For example:

Temperature temperature; // Defining an action-scope variable
  
on all Temperature (sensorId="S001"):temperature {...}
  1. Update the print statement to use this variable:
print "Temperature received: "+temperature;
  1. Save your changes.

Follow the above steps of testing the code:
You should now see output such as:

Temperature received: Temperature("S001",90)
Temperature received: Temperature("S001",100)
Temperature received: Temperature("S001",111)
Temperature received: Temperature("S001",120)
Info
From now on to run the project, follow these steps:
For all .mon files, right click and select correlator: engine inject
For all .evt files, right click and select correlator: engine send

You can import the completed solution for this lesson:

In the Apama Samples Git repository, navigate to the tutorials/EPL_Fundamentals_Completed directory.