Search code examples
aggregateespercumulocity

Esper counting repeating events in pattern


I have a sequence of events which goes like this:

  1. Event A starts the sequence
  2. Multiple Events B happen
  3. Event C stops the sequence

I did that with a pattern [every A -> (B until C)], it seems to be correct (what do you think?). But I'm struggling to retrieve and aggregate infos from the B events that arose in the sequence. I'd like to simply have a count and maybe some avgs but nothing seems to work (example1 returns 1, example 2 returns 0 and example 3 return null, even if my B events are present).

insert into CreateMeasurement
select
    C.source            as source,
    "carDrivingAnalyse" as type,
    C.time              as time,
    {
        "example1", count(*),
        "example2", count(B),
        "example3", B.countOf()
    } as fragments

from pattern [
    every A = EventCreated(
        type = "Ignition",
        getString(A, "Ignition.status") = "ON")

    -> (
        B = EventCreated(
            type = "DrivingEvent",
            source = A.source,
            getString(B, "DrivingEvent.prop1") = getString(A, "Ignition.prop1"),
            getNumber(B, "DrivingEvent.prop2") = getNumber(A, "Ignition.prop2"))

        until C = EventCreated(
            type = "Ignition",
            getString(C, "Ignition.status") = "OFF",
            source = A.source,
            getString(C, "Ignition.prop1") = getString(A, "Ignition.prop1"),
            getNumber(C, "Ignition.prop2") = getNumber(A, "Ignition.prop2"))
    )
]

Solution

  • I would choose a different approach for this use case and use a context instead of a pattern:

    create context EventContext
      context PartionBySource
        partition by event.source.value from EventCreated,
      context ContextBorders
        initiated by EventCreated(type="EventA") as startEvent 
        terminated by EventCreated(event.type="EventC");
    

    It is already a more complex context because it uses two nested contexts. The is some basic coverage of contexts in the Cumulocity docs (http://cumulocity.com/guides/event-language/advanced/#contexts) but for this advanced usage I would recommend the more detailed esper documentation http://www.espertech.com/esper/release-5.3.0/esper-reference/html/context.html

    In summary this context does this:

    Based on the EventCreated stream it will first partition the events by their source device. It will create a new context partition every time there is an EventA (only if there is no context partition for this device at the moment). With an arrival of an EventC the context partition for this device will end.

    Now you can make use of this context for example like this:

    context EventContext
    select
      count(*) as count,
      avg(getNumber(e, "speed")) as speed
    from EventCreated e
    where e.event.type = "EventB"
    output last when terminated;
    

    This statement uses the context. It will output the result at the moment the context partition ends (so when an EventC arrives). It will only output the last event (without the last keyword here it will output every event received while the partition was active). In this example it will output the number of events received during the existence of the context partition and the average value of the "speed" fragment in the EventB.

    Note that it is not necessary to do any filtering by source here because the context already partitions the events on EventCreated by source.